package org.simantics.scenegraph.utils; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.simantics.scenegraph.ILookupService; import org.simantics.scenegraph.INode; /** * A scene graph utility that manages a set of String ID <-> {@link INode} * mappings by ensuring that a specified set of nodes have ID mappings. * * When a node mapper is no longer needed, you should perform cleanup by * invoking {@link #clear()}. This will remove all the ID <-> INode mappings * managed by the mapper. * * The implementation is not thread-safe, it should only be used from the canvas * context thread (see {@link ICanvasContext#getThreadAccess()). * * @author Tuukka Lehtonen */ public final class NodeMapper { Map nodes = new HashMap(); Map managedNodes = new HashMap(); public NodeMapper() { } public NodeMapper(INode node) { add0(node); } public void clear() { for (Map.Entry entry : managedNodes.entrySet()) { ILookupService lu = NodeUtil.tryGetLookupService(entry.getKey()); if (lu != null) { String mappedId = lu.lookupId(entry.getKey()); if (entry.getValue().equals(mappedId)) { lu.unmap(entry.getKey()); } } } managedNodes.clear(); nodes.clear(); } public NodeMapper(Collection nodes) { addAll(nodes); } public String add(INode node) { return add0(node); } public void addAll(Collection nodes) { for (INode n : nodes) { add0(n); } } /** * @param node * @return */ public String remove(INode node) { return remove0(node); } public String getId(INode node) { return nodes.get(node); } private String add0(INode node) { String id = nodes.get(node); if (id != null) return id; id = NodeUtil.lookupId(node); if (id != null) { nodes.put(node, id); return id; } id = UUID.randomUUID().toString(); NodeUtil.map(node, id); nodes.put(node, id); managedNodes.put(node, id); return id; } /** * Removes mapping for specified node if and only if it is mapped through * this mapper and the ID currently mapped to matches this mapper's * conception of what the ID should be. * * @param node * @return */ private String remove0(INode node) { String id = null; if ((id = nodes.remove(node)) != null) { if (managedNodes.remove(node) != null) { ILookupService lu = NodeUtil.tryGetLookupService(node); if (lu != null) { String mappedId = lu.lookupId(node); if (id.equals(mappedId)) { lu.unmap(node); } } } } return id; } }