package edu.stanford.nlp.util; import edu.stanford.nlp.ling.CoreAnnotation; import edu.stanford.nlp.ling.CoreLabel; import java.util.*; /** * Utility functions for working with {@link CoreMap}'s. * * @author dramage * @author Gabor Angeli (merge() method) */ public class CoreMaps { private CoreMaps() {} // static stuff /** * Merge one CoreMap into another -- that is, overwrite and add any keys in * the base CoreMap with those in the one to be merged. * This method is functional -- neither of the argument CoreMaps are changed. * @param base The CoreMap to serve as the base (keys in this are lower priority) * @param toBeMerged The CoreMap to merge in (keys in this are higher priority) * @return A new CoreMap representing the merge of the two inputs */ public static CoreMap merge(CoreMap base, CoreMap toBeMerged){ //(variables) CoreMap rtn = new ArrayCoreMap(base.size()); //(copy base) for(Class key : base.keySet()){ rtn.set(key, base.get(key)); } //(merge) for(Class key : toBeMerged.keySet()){ rtn.set(key,toBeMerged.get(key)); } //(return) return rtn; } /** * see merge(CoreMap base, CoreMap toBeMerged) */ public static CoreLabel merge(CoreLabel base, CoreLabel toBeMerged){ //(variables) CoreLabel rtn = new CoreLabel(base.size()); //(copy base) for(Class key : base.keySet()){ rtn.set(key,base.get(key)); } //(merge) for(Class key : toBeMerged.keySet()){ rtn.set(key,toBeMerged.get(key)); } //(return) return rtn; } /** * Returns a view of a collection of CoreMaps as a Map from each CoreMap to * the value it stores under valueKey. Changes to the map are propagated * directly to the coremaps in the collection and to the collection itself in * the case of removal operations. Keys added or removed from the given * collection by anything other than the returned map will leave the map * in an undefined state. */ public static <V, CM extends CoreMap, COLL extends Collection<CM>> Map<CM,V> asMap(final COLL coremaps, final Class<? extends TypesafeMap.Key<V>> valueKey) { final IdentityHashMap<CM,Boolean> references = new IdentityHashMap<>(); for(CM map : coremaps){ references.put(map, true); } // an EntrySet view of the elements of coremaps final Set<Map.Entry<CM, V>> entrySet = new AbstractSet<Map.Entry<CM,V>>() { @Override public Iterator<Map.Entry<CM, V>> iterator() { return new Iterator<Map.Entry<CM,V>>() { Iterator<CM> it = coremaps.iterator(); CM last = null; public boolean hasNext() { return it.hasNext(); } public Map.Entry<CM, V> next() { final CM next = it.next(); last = next; return new Map.Entry<CM,V>() { public CM getKey() { return next; } public V getValue() { return next.get(valueKey); } public V setValue(V value) { return next.set(valueKey, value); } }; } public void remove() { references.remove(last); it.remove(); } }; } @Override public int size() { return coremaps.size(); } }; return new AbstractMap<CM,V>() { @Override public int size() { return coremaps.size(); } @Override public boolean containsKey(Object key) { return coremaps.contains(key); } @Override public V get(Object key) { if (!references.containsKey(key)) { return null; } return ((CoreMap)key).get(valueKey); } @Override public V put(CM key, V value) { if (!references.containsKey(key)) { coremaps.add(key); references.put(key,true); } return key.set(valueKey, value); } @Override public V remove(Object key) { if (!references.containsKey(key)) { return null; } return coremaps.remove(key) ? ((CoreMap)key).get(valueKey) : null; } @Override public Set<Map.Entry<CM, V>> entrySet() { return entrySet; } }; } /** * Utility function for dumping all the keys and values of a CoreMap to a String. */ public static String dumpCoreMap(CoreMap cm) { StringBuilder sb = new StringBuilder(); dumpCoreMapToStringBuilder(cm, sb); return sb.toString(); } @SuppressWarnings("unchecked") public static void dumpCoreMapToStringBuilder(CoreMap cm, StringBuilder sb) { for (Class<?> rawKey : cm.keySet()) { Class<CoreAnnotation<Object>> key = (Class<CoreAnnotation<Object>>) rawKey; String className = key.getSimpleName(); Object value = cm.get(key); sb.append(className).append(": ").append(value).append("\n"); } } }