]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/LookupService.java
Sync git svn branch with SVN repository r33269.
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / LookupService.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph;\r
13 \r
14 import java.util.HashMap;\r
15 import java.util.Map;\r
16 import java.util.logging.Level;\r
17 import java.util.logging.Logger;\r
18 \r
19 /**\r
20  * A synchronized reference implementation of {@link ILookupService}.\r
21  * \r
22  * @author Tuukka Lehtonen\r
23  */\r
24 public class LookupService implements ILookupService {\r
25 \r
26     private final Object             lookupLock = new Object();\r
27     private final Map<String, INode> toNode     = new HashMap<String, INode>();\r
28     private final Map<INode, String> toId       = new HashMap<INode, String>();\r
29 \r
30     Logger                     logger     = Logger.getLogger(getClass().getName());\r
31 \r
32     @Override\r
33     public INode map(String id, INode node) {\r
34         if (id == null)\r
35             throw new NullPointerException("null id");\r
36         if (node == null)\r
37             throw new NullPointerException("null node");\r
38 \r
39         INode oldNode;\r
40         String oldId;\r
41         synchronized (lookupLock) {\r
42             oldNode = toNode.put(id, node);\r
43             oldId = toId.put(node, id);\r
44 \r
45             // Keep the mapping a consistent bijection:\r
46             // If ID => INode mapping is removed, the INode => ID mappings must\r
47             // removed also.\r
48 \r
49             if (oldNode != null && !oldNode.equals(node)) {\r
50                 String removedId = toId.remove(oldNode);\r
51                 if (!id.equals(removedId))\r
52                     toNode.remove(removedId);\r
53             }\r
54             if (oldId != null && !oldId.equals(id)) {\r
55                 INode removedNode = toNode.remove(oldId);\r
56                 if (removedNode != node)\r
57                     toId.remove(removedNode);\r
58             }\r
59         }\r
60         if (logger.isLoggable(Level.FINE))\r
61             logger.fine("map(" + id + ", " + node + ")");\r
62         if (oldNode != null || oldId != null) {\r
63             if (logger.isLoggable(Level.INFO)) {\r
64                 logger.info("replaced mappings for ID " + oldId + " and node " + oldNode);\r
65             }\r
66         }\r
67         return oldNode;\r
68     }\r
69 \r
70     @Override\r
71     public INode unmap(String id) {\r
72         INode node;\r
73         String mappedId;\r
74         synchronized (lookupLock) {\r
75             node = toNode.remove(id);\r
76             if (node == null)\r
77                 return null;\r
78             mappedId = toId.remove(node);\r
79         }\r
80         if (logger.isLoggable(Level.FINE))\r
81             logger.fine("unmap(" + id + "): " + node);\r
82         if (mappedId != null && !mappedId.equals(id)) {\r
83             if (logger.isLoggable(Level.WARNING))\r
84                 logger.log(Level.WARNING, "mapping was out-of-sync: " + id + " => " + node + " & " + mappedId + " => " + node, new Exception("trace"));\r
85         }\r
86         return node;\r
87     }\r
88 \r
89     @Override\r
90     public String unmap(INode node) {\r
91         String id;\r
92         INode mappedNode;\r
93         synchronized (lookupLock) {\r
94             id = toId.remove(node);\r
95             if (node == null)\r
96                 return null;\r
97             mappedNode = toNode.remove(id);\r
98         }\r
99         if (logger.isLoggable(Level.FINE))\r
100             logger.fine("unmap(" + node + "): " + id);\r
101         if (mappedNode != null && node != mappedNode) {\r
102             if (logger.isLoggable(Level.WARNING))\r
103                 logger.log(Level.WARNING, "mapping was out-of-sync: " + node + " => " + id + " & " + id + " => " + mappedNode, new Exception("trace"));\r
104         }\r
105         return id;\r
106     }\r
107 \r
108     @Override\r
109     public INode lookupNode(String id) {\r
110         synchronized (lookupLock) {\r
111             return toNode.get(id);\r
112         }\r
113     }\r
114 \r
115     @Override\r
116     public String lookupId(INode node) {\r
117         synchronized (lookupLock) {\r
118             return toId.get(node);\r
119         }\r
120     }\r
121 \r
122 }\r