/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.gephi.data.attributes; import it.unimi.dsi.fastutil.objects.Object2ObjectAVLTreeMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.SortedMap; import org.gephi.data.attributes.api.AttributeColumn; import org.gephi.data.attributes.api.AttributeDictionary; import org.gephi.data.attributes.api.AttributeUtils; import org.gephi.data.attributes.api.AttributeValue; import org.gephi.graph.api.Attributable; /** * * @author Eduardo Ramos<eduramiba@gmail.com> */ public final class AttributeDictionaryImpl implements AttributeDictionary { private static final boolean DEFAULT_TRIMMING_ENABLED = false; private static final int DEFAULT_TRIMMING_FREQUENCY = 30; private AttributeColumn column; private Map<Object, Set<Attributable>> map; private Set<Attributable> nullSet; private boolean sortableColumn; private boolean trimmingEnabled; private int trimmingFrequency; private int countDownToTrim; public AttributeDictionaryImpl(AttributeColumn column, boolean trimmingEnabled, int trimmingFrequency) { this.column = column; this.trimmingEnabled = trimmingEnabled; this.trimmingFrequency = trimmingFrequency; this.nullSet = new ObjectOpenHashSet<Attributable>(); buildMap(); } public AttributeDictionaryImpl(AttributeColumn column) { this(column, DEFAULT_TRIMMING_ENABLED, DEFAULT_TRIMMING_FREQUENCY); } private void buildMap() { sortableColumn = AttributeUtils.getDefault().isNumberColumn(column); if (sortableColumn) { //Column type is sortable: map = new Object2ObjectAVLTreeMap<Object, Set<Attributable>>(); trimmingEnabled = false;//No need to trim TreeMap } else { //Column type is not sortable: map = new Object2ObjectOpenHashMap<Object, Set<Attributable>>(); countDownToTrim = trimmingFrequency; } } private Set<Attributable> getValueSet(Object value) { if (value == null) { return nullSet; } if (map.containsKey(value)) { return map.get(value); } else { Set<Attributable> set = new ObjectOpenHashSet<Attributable>(); map.put(value, set); return set; } } public synchronized void putValue(AttributeValue value) { Object objVal = value.getValue(); Set<Attributable> set = getValueSet(objVal); set.add(value.getSource()); } public synchronized void removeValue(AttributeValue value) { Object objVal = value.getValue(); Set<Attributable> set = getValueSet(objVal); set.remove(value.getSource()); if (set.isEmpty() && objVal != null) { map.remove(objVal); if (trimmingEnabled) { countDownToTrim--; if (countDownToTrim == 0) { ((Object2ObjectOpenHashMap) map).trim(); countDownToTrim = trimmingFrequency; } } } } public void replaceValue(AttributeValue oldValue, AttributeValue newValue) { removeValue(oldValue); putValue(newValue); } public synchronized Set<Object> getValues() { return Collections.unmodifiableSet(map.keySet()); } public synchronized int getValueFrequency(Object value) { if (value == null) { return nullSet.size(); } if (map.containsKey(value)) { return map.get(value).size(); } else { return 0; } } public synchronized Set<Attributable> getValueRows(Object value) { Set<Attributable> set; if (value == null) { set = nullSet; } else { set = map.get(value); } return set != null ? Collections.unmodifiableSet(set) : null; } public synchronized Object getMinValue() { if (sortableColumn) { if (map.isEmpty()) { return null; } else { return ((SortedMap) map).firstKey(); } } else { throw new UnsupportedOperationException(column.getTitle() + " is not a sortable column."); } } public synchronized Object getMaxValue() { if (sortableColumn) { if (map.isEmpty()) { return null; } else { return ((SortedMap) map).lastKey(); } } else { throw new UnsupportedOperationException(column.getTitle() + " is not a sortable column."); } } public boolean isSortableColumn() { return sortableColumn; } public AttributeColumn getColumn() { return column; } public int getCountDownToTrim() { return countDownToTrim; } public boolean isTrimmingEnabled() { return trimmingEnabled; } public int getTrimmingFrequency() { return trimmingFrequency; } }