]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/MappingWithContext.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.utils.datastructures / src / org / simantics / utils / datastructures / MappingWithContext.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 /*\r
13  *\r
14  * @author Toni Kalajainen\r
15  */\r
16 package org.simantics.utils.datastructures;\r
17 \r
18 import java.util.Collections;\r
19 import java.util.HashMap;\r
20 import java.util.HashSet;\r
21 import java.util.Map;\r
22 import java.util.Set;\r
23 import java.util.Map.Entry;\r
24 \r
25 \r
26 /**\r
27  * Context dependent Key to Key Bijection Mapping.  \r
28  *\r
29  * @param <Context>\r
30  * @param <Key>\r
31  */\r
32 public class MappingWithContext<Context, Key> {\r
33 \r
34         public static class IntersectingContextsException extends Exception {\r
35                 private static final long serialVersionUID = 3411795376917295313L;\r
36                 public IntersectingContextsException(Object c, Object key1, Object key2) {\r
37                         super("The two keys "+key1+" and "+key2+" are intersecting in context "+c);\r
38                 }\r
39         };\r
40         \r
41         Map<Context, BijectionMap<Key, Key>> maps = \r
42                 new HashMap<Context, BijectionMap<Key, Key>>();\r
43         \r
44         /**\r
45          * Add mapping. null context applies always.\r
46          * \r
47          * @param context\r
48          * @param leftKey\r
49          * @param rightKey\r
50          */\r
51         public synchronized void addMapping(Context context, Key leftKey, Key rightKey)\r
52         {\r
53                 BijectionMap<Key, Key> map = getOrCreateMap(context);\r
54                 map.map(leftKey, rightKey);             \r
55         }\r
56 \r
57         /**\r
58          * Get right value with left key\r
59          * @param contexts effective contexts\r
60          * @param leftKey\r
61          * @return a single right value or null\r
62          * @throws IntersectingContextsException\r
63          */\r
64         public synchronized Key getAtMostOneMappingWithLeftKey(Context[] contexts, Key leftKey)\r
65         throws IntersectingContextsException\r
66         {\r
67                 Key result = null;\r
68                 Context resultContext = null;\r
69                 for (Context c : contexts)\r
70                 {\r
71                         BijectionMap<Key, Key> map = maps.get(c);\r
72                         if (map==null) continue;\r
73                         Key value = map.getRight(leftKey);\r
74                         if (value==null) continue;\r
75                         if (result!=null) throw new IntersectingContextsException(resultContext, value, result);\r
76                         result = value;\r
77                         resultContext = c;\r
78                 }\r
79 \r
80                 return result;\r
81         }\r
82 \r
83         /**\r
84          * Get left value with right key\r
85          * @param contexts effective contexts\r
86          * @param rightKey\r
87          * @return a single left value or null\r
88          * @throws IntersectingContextsException\r
89          */\r
90         public synchronized Key getAtMostOneMappingWithRightKey(Context[] contexts, Key rightKey)\r
91         throws IntersectingContextsException\r
92         {\r
93                 Key result = null;\r
94                 Context resultContext = null;\r
95                 for (Context c : contexts)\r
96                 {\r
97                         BijectionMap<Key, Key> map = maps.get(c);\r
98                         if (map==null) continue;\r
99                         Key value = map.getLeft(rightKey);\r
100                         if (value==null) continue;\r
101                         if (result!=null) throw new IntersectingContextsException(resultContext, value, result);\r
102                         result = value;\r
103                         resultContext = c;\r
104                 }\r
105 \r
106                 return result;\r
107         }\r
108         \r
109         /**\r
110          * Get all right values with left key\r
111          * @param contexts effective contexts\r
112          * @param leftKey\r
113          * @return a single right value or null\r
114          * @throws IntersectingContextsException\r
115          */\r
116         public synchronized Set<Key> getMappingWithLeftKey(Context[] contexts, Key leftKey)\r
117         throws IntersectingContextsException\r
118         {\r
119                 Set<Key> result = new HashSet<Key>();\r
120                 for (Context c : contexts)\r
121                 {\r
122                         BijectionMap<Key, Key> map = maps.get(c);\r
123                         if (map==null) continue;\r
124                         Key value = map.getRight(leftKey);\r
125                         if (value==null) continue;\r
126                         result.add(value);\r
127                 }\r
128                 return result;\r
129         }\r
130 \r
131         /**\r
132          * Get all left values with right key\r
133          * @param contexts effective contexts\r
134          * @param rightKey\r
135          * @return a single left value or null\r
136          * @throws IntersectingContextsException\r
137          */\r
138         public synchronized Set<Key> getMappingWithRightKey(Context[] contexts, Key rightKey)\r
139         throws IntersectingContextsException\r
140         {\r
141                 Set<Key> result = new HashSet<Key>();\r
142                 for (Context c : contexts)\r
143                 {\r
144                         BijectionMap<Key, Key> map = maps.get(c);\r
145                         if (map==null) continue;\r
146                         Key value = map.getLeft(rightKey);\r
147                         if (value==null) continue;\r
148                         result.add(value);\r
149                 }\r
150                 return result;\r
151         }       \r
152         \r
153         private synchronized BijectionMap<Key, Key> getOrCreateMap(Context context)\r
154         {\r
155                 BijectionMap<Key, Key> result = maps.get(context);\r
156                 if (result!=null) return result;\r
157                 result = new BijectionMap<Key, Key>();\r
158                 maps.put(context, result);              \r
159                 return result; \r
160         }\r
161         \r
162         public synchronized void addMapToContext(Context context, BijectionMap<Key, Key> map)\r
163         {\r
164                 BijectionMap<Key, Key> m = getOrCreateMap(context);\r
165                 m.addAll(map);\r
166         }\r
167         \r
168         public synchronized Set<Context> getContexts()\r
169         {\r
170                 return Collections.unmodifiableSet(maps.keySet());\r
171         }\r
172         \r
173         public synchronized Set<Key> getLeftKeys(Context context)\r
174         {\r
175                 BijectionMap<Key, Key> map = maps.get(context);\r
176                 if (map==null) return null;\r
177                 return Collections.unmodifiableSet(map.getLeftSet());           \r
178         }\r
179         \r
180         public synchronized Set<Key> getRightKeys(Context context)\r
181         {\r
182                 BijectionMap<Key, Key> map = maps.get(context);\r
183                 if (map==null) return null;\r
184                 return Collections.unmodifiableSet(map.getRightSet());          \r
185         }\r
186 \r
187         public synchronized Set<Key> getAllLeftKeys()\r
188         {\r
189                 Set<Key> result = new HashSet<Key>();\r
190                 for (Context context : getContexts())\r
191                         result.addAll(getLeftKeys(context));\r
192                 return result;\r
193         }\r
194         \r
195         public synchronized Set<Key> getAllRightKeys()\r
196         {\r
197                 Set<Key> result = new HashSet<Key>();\r
198                 for (Context context : getContexts())\r
199                         result.addAll(getRightKeys(context));\r
200                 return result;\r
201         }\r
202         \r
203     @Override\r
204     public String toString() {\r
205         int count = 0;\r
206         StringBuilder sb = new StringBuilder();\r
207         sb.append("[");\r
208         for (Entry<Context, BijectionMap<Key, Key>> e : maps.entrySet())\r
209         {\r
210                 if (count++>0) sb.append(", ");\r
211                 sb.append((e.getKey()==null?"null":e.getKey().toString()));\r
212                 sb.append("=");\r
213                 sb.append(e.getValue().toString());             \r
214         }\r
215         sb.append("]");\r
216         return sb.toString();\r
217     }   \r
218         \r
219 }\r