]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/NodeMapper.java
Merge commit 'd186091'
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / utils / NodeMapper.java
1 package org.simantics.scenegraph.utils;\r
2 \r
3 import java.util.Collection;\r
4 import java.util.HashMap;\r
5 import java.util.Map;\r
6 import java.util.UUID;\r
7 \r
8 import org.simantics.scenegraph.ILookupService;\r
9 import org.simantics.scenegraph.INode;\r
10 \r
11 /**\r
12  * A scene graph utility that manages a set of String ID <-> {@link INode}\r
13  * mappings by ensuring that a specified set of nodes have ID mappings.\r
14  * \r
15  * When a node mapper is no longer needed, you should perform cleanup by\r
16  * invoking {@link #clear()}. This will remove all the ID <-> INode mappings\r
17  * managed by the mapper.\r
18  * \r
19  * The implementation is not thread-safe, it should only be used from the canvas\r
20  * context thread (see {@link ICanvasContext#getThreadAccess()).\r
21  * \r
22  * @author Tuukka Lehtonen\r
23  */\r
24 public final class NodeMapper {\r
25 \r
26     Map<INode, String> nodes        = new HashMap<INode, String>();\r
27     Map<INode, String> managedNodes = new HashMap<INode, String>();\r
28 \r
29     public NodeMapper() {\r
30     }\r
31 \r
32     public NodeMapper(INode node) {\r
33         add0(node);\r
34     }\r
35 \r
36     public void clear() {\r
37         for (Map.Entry<INode, String> entry : managedNodes.entrySet()) {\r
38             ILookupService lu = NodeUtil.tryGetLookupService(entry.getKey());\r
39             if (lu != null) {\r
40                 String mappedId = lu.lookupId(entry.getKey());\r
41                 if (entry.getValue().equals(mappedId)) {\r
42                     lu.unmap(entry.getKey());\r
43                 }\r
44             }\r
45         }\r
46         managedNodes.clear();\r
47         nodes.clear();\r
48     }\r
49 \r
50     public NodeMapper(Collection<? extends INode> nodes) {\r
51         addAll(nodes);\r
52     }\r
53 \r
54     public String add(INode node) {\r
55         return add0(node);\r
56     }\r
57 \r
58     public void addAll(Collection<? extends INode> nodes) {\r
59         for (INode n : nodes) {\r
60             add0(n);\r
61         }\r
62     }\r
63 \r
64     /**\r
65      * @param node\r
66      * @return\r
67      */\r
68     public String remove(INode node) {\r
69         return remove0(node);\r
70     }\r
71 \r
72     public String getId(INode node) {\r
73         return nodes.get(node);\r
74     }\r
75 \r
76     private String add0(INode node) {\r
77         String id = nodes.get(node);\r
78         if (id != null)\r
79             return id;\r
80 \r
81         id = NodeUtil.lookupId(node);\r
82         if (id != null) {\r
83             nodes.put(node, id);\r
84             return id;\r
85         }\r
86 \r
87         id = UUID.randomUUID().toString();\r
88         NodeUtil.map(node, id);\r
89         nodes.put(node, id);\r
90         managedNodes.put(node, id);\r
91         return id;\r
92     }\r
93 \r
94     /**\r
95      * Removes mapping for specified node if and only if it is mapped through\r
96      * <em>this</em> mapper and the ID currently mapped to matches this mapper's\r
97      * conception of what the ID should be.\r
98      * \r
99      * @param node\r
100      * @return\r
101      */\r
102     private String remove0(INode node) {\r
103         String id = null;\r
104         if ((id = nodes.remove(node)) != null) {\r
105             if (managedNodes.remove(node) != null) {\r
106                 ILookupService lu = NodeUtil.tryGetLookupService(node);\r
107                 if (lu != null) {\r
108                     String mappedId = lu.lookupId(node);\r
109                     if (id.equals(mappedId)) {\r
110                         lu.unmap(node);\r
111                     }\r
112                 }\r
113             }\r
114         }\r
115         return id;\r
116     }\r
117 \r
118 }\r