/* * Copyright (c) 2014 Oculus Info Inc. http://www.oculusinfo.com/ * * Released under the MIT License. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.oculusinfo.annotation; import com.oculusinfo.binning.TileData; import com.oculusinfo.binning.impl.DenseTileData; import com.oculusinfo.factory.util.Pair; import java.io.Serializable; import java.util.*; /** * This class represents a bin's worth of annotations. As the annotation API uses * the binning-utilities packages generic types for serialization, this class is * used to encapsulate the unique behaviour needed for adding and removing annotations * from each bin object. * * An annotation bin is a map from each group string to a list of annotation * certificates. Each certificate is represented as a uuid and a timestamp in * the form of a Pair<String, Long> * * { * "Urgent" : [ (UUID, TIMESTAMP), ... ], * "High" : [ (UUID, TIMESTAMP), ... ], * "Medium" : [ (UUID, TIMESTAMP), ... ], * "Low" : [ (UUID, TIMESTAMP), ... ] * } * */ public class AnnotationBin implements Serializable { private static final long serialVersionUID = 1L; private static class CertificateComparator implements Comparator< Pair<String, Long> > { @Override public int compare( Pair<String, Long> a, Pair<String, Long> b ) { // java sorts in ascending order, we want descending ( new certificates first ) // so we negate the compareTo return -a.getSecond().compareTo( b.getSecond() ); } } private Map<String, List<Pair<String, Long>>> _bin; public AnnotationBin(){ _bin = new LinkedHashMap<>(); } public AnnotationBin( Map<String, List<Pair<String, Long>>> rawBin ) { if ( rawBin != null ) { _bin = rawBin; } else { _bin = new LinkedHashMap<>(); } } public static List< AnnotationBin > convertFromRaw( TileData<Map<String, List<Pair<String, Long>>>> rawTile ) { List<Map<String, List<Pair<String, Long>>>> rawData = DenseTileData.getData(rawTile); List< AnnotationBin > bins = new ArrayList<>(); for (Map<String, List<Pair<String, Long>>> rawBin: rawData) { if ( rawBin != null ) { bins.add( new AnnotationBin( rawBin ) ); } else { bins.add( null ); } } return bins; } public static List< Map<String, List<Pair<String, Long>>> > convertToRaw( List< AnnotationBin > bins ) { List< Map<String, List<Pair<String, Long>>> > rawBins = new ArrayList<>(); for ( AnnotationBin bin : bins) { if ( bin != null ) { rawBins.add( bin.getData() ); } else { rawBins.add( null ); } } return rawBins; } public boolean isEmpty() { return _bin.isEmpty(); } public Map<String, List<Pair<String, Long>>> getData() { return _bin; } public void addData( AnnotationData<?> data ) { String group = data.getGroup(); Pair<String, Long> certificate = data.getCertificate(); List< Pair<String, Long> > entries; if ( _bin.containsKey( group ) ) { entries = _bin.get( group ); if ( !entries.contains( certificate ) ) { entries.add( certificate ); } } else { entries = new LinkedList<>(); entries.add( certificate ); _bin.put( group, entries ); } // sort certificates after insertion... maybe instead use a SortedSet? Collections.sort( entries, new CertificateComparator() ); } public void removeData( AnnotationData<?> data ) { String group = data.getGroup(); Pair<String, Long> certificate = data.getCertificate(); if ( _bin.containsKey(group) ) { List<Pair<String, Long>> entries = _bin.get(group); if (entries.contains(certificate)) { entries.remove(certificate); } if (entries.isEmpty()) { // remove certificates for group _bin.remove( group ); } } } public List<Pair<String, Long>> getCertificates( String group ) { if ( _bin.containsKey( group ) ) { return _bin.get( group ); } else { return new LinkedList<>(); } } public List<Pair<String, Long>> getAllCertificates() { List<Pair<String, Long>> allCertificates = new LinkedList<>(); // for each group group in a bin for ( List<Pair<String, Long>> certificates : _bin.values() ) { allCertificates.addAll(certificates); } return allCertificates; } }