]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.databoard/src/org/simantics/databoard/util/BijectionMap.java
Re-implement URIStringUtils escape and unescape using Unicode
[simantics/platform.git] / bundles / org.simantics.databoard / src / org / simantics / databoard / util / BijectionMap.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
3  * All rights reserved. This program and the accompanying materials\r
4  * are made available under the terms of the Eclipse Public License v1.0\r
5  * which accompanies this distribution, and is available at\r
6  * http://www.eclipse.org/legal/epl-v10.html\r
7  *\r
8  * Contributors:\r
9  *     VTT Technical Research Centre of Finland - initial API and implementation\r
10  *******************************************************************************/\r
11 /*\r
12  * Created on Jan 21, 2005\r
13  *\r
14  * Copyright Toni Kalajainen\r
15  *\r
16  * Licensed under the Apache License, Version 2.0 (the "License");\r
17  * you may not use this file except in compliance with the License.\r
18  * You may obtain a copy of the License at\r
19  *\r
20  *     http://www.apache.org/licenses/LICENSE-2.0\r
21  *\r
22  * Unless required by applicable law or agreed to in writing, software\r
23  * distributed under the License is distributed on an "AS IS" BASIS,\r
24  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
25  * See the License for the specific language governing permissions and\r
26  * limitations under the License.\r
27  */\r
28 package org.simantics.databoard.util;\r
29 \r
30 import java.util.ArrayList;\r
31 import java.util.Collection;\r
32 import java.util.Collections;\r
33 import java.util.HashMap;\r
34 import java.util.Map;\r
35 import java.util.Map.Entry;\r
36 import java.util.Set;\r
37 \r
38 /**\r
39  * Bijection map is a Map that has no values or keys, only 1:1 mappings\r
40  * of values. These value/keys will be called with left and right side\r
41  * values.\r
42  *\r
43  * Each value can exist only once on a side\r
44  *\r
45  * @author Toni Kalajainen\r
46  */\r
47 public class BijectionMap<L, R> {\r
48 \r
49     /** The keys of tableLeft are left-side-values and\r
50      * values are right-side-values */\r
51     private final Map<L, R> tableLeft = new HashMap<L, R>();\r
52     /** The keys of tableRight are right-side-values and\r
53      * values on it are left-side-values */\r
54     private final Map<R, L> tableRight = new HashMap<R, L>();\r
55 \r
56     /** The keys of tableLeft are left-side-values and\r
57      * values are right-side-values */\r
58     private final Map<L, R> imTableLeft = Collections.unmodifiableMap(tableLeft);\r
59     /** The keys of tableRight are right-side-values and\r
60      * values on it are left-side-values */\r
61     private final Map<R, L> imTableRight = Collections.unmodifiableMap(tableRight);\r
62 \r
63     private final Set<L> imLeftSet = Collections.unmodifiableSet(tableLeft.keySet());\r
64     private final Set<R> imRightSet = Collections.unmodifiableSet(tableRight.keySet());\r
65 \r
66         public BijectionMap() {\r
67 \r
68         }\r
69 \r
70         public BijectionMap(BijectionMap<L, R> copyFrom) {\r
71                 this.tableLeft.putAll(copyFrom.tableLeft);\r
72                 this.tableRight.putAll(copyFrom.tableRight);\r
73         }\r
74 \r
75         public void addAll(BijectionMap<L, R> map)\r
76         {\r
77                 for (Entry<L, R> e : map.getEntries())\r
78                         map(e.getKey(), e.getValue());\r
79         }\r
80 \r
81     public boolean retainAllLeft(Collection<L> values)\r
82     {\r
83         boolean result = false;\r
84         Collection<L> remove = new ArrayList<L>(size());\r
85         for (L lValue : imLeftSet) {\r
86             if (!values.contains(lValue)) {\r
87                 remove.add(lValue);\r
88                 result = true;\r
89             }\r
90         }\r
91         if (!remove.isEmpty()) {\r
92             for (L lValue : remove)\r
93                 removeWithLeft(lValue);\r
94         }\r
95         return result;\r
96     }\r
97 \r
98     public boolean retainAllRight(Collection<R> values)\r
99     {\r
100         boolean result = false;\r
101         Collection<R> remove = new ArrayList<R>(size());\r
102         for (R rValue : imRightSet) {\r
103             if (!values.contains(rValue)) {\r
104                 remove.add(rValue);\r
105                 result = true;\r
106             }\r
107         }\r
108         if (!remove.isEmpty()) {\r
109             for (R rValue : remove)\r
110                 removeWithRight(rValue);\r
111         }\r
112         return result;\r
113     }\r
114 \r
115         public Set<Entry<L, R>> getEntries()\r
116         {\r
117                 return tableLeft.entrySet();\r
118         }\r
119 \r
120         public boolean containsLeft(L leftValue)\r
121         {\r
122                 return tableLeft.containsKey(leftValue);\r
123         }\r
124 \r
125         public boolean containsRight(R rightValue)\r
126         {\r
127                 return tableRight.containsKey(rightValue);\r
128         }\r
129 \r
130         public boolean contains(L leftValue, R rightValue)\r
131         {\r
132                 if (leftValue==null || rightValue==null) return false;\r
133                 return rightValue.equals(tableLeft.get(leftValue));\r
134         }\r
135 \r
136         public void map(L leftValue, R rightValue)\r
137         {\r
138         if (leftValue == null || rightValue == null)\r
139             throw new NullPointerException();\r
140         // Remove possible old mapping\r
141         R oldRight = tableLeft.remove(leftValue);\r
142         if (oldRight != null) {\r
143             tableRight.remove(oldRight);\r
144         } else {\r
145             L oldLeft = tableRight.remove(rightValue);\r
146             if (oldLeft != null) {\r
147                 tableLeft.remove(oldLeft);\r
148             }\r
149         }\r
150 \r
151                 tableLeft.put(leftValue, rightValue);\r
152                 tableRight.put(rightValue, leftValue);\r
153         }\r
154 \r
155         public boolean isEmpty() {\r
156             return tableLeft.isEmpty();\r
157         }\r
158 \r
159     public int size()\r
160     {\r
161         return tableLeft.size();\r
162     }\r
163 \r
164         public L getLeft(R rightValue) {\r
165                 return tableRight.get(rightValue);\r
166         }\r
167 \r
168         public R getRight(L leftValue) {\r
169                 return tableLeft.get(leftValue);\r
170         }\r
171 \r
172         public R removeWithLeft(L leftValue) {\r
173                 R rightValue = tableLeft.remove(leftValue);\r
174                 if (rightValue!=null)\r
175                         tableRight.remove(rightValue);\r
176                 return rightValue;\r
177         }\r
178 \r
179         public L removeWithRight(R rightValue) {\r
180                 L leftValue = tableRight.remove(rightValue);\r
181                 if (leftValue!=null)\r
182                         tableLeft.remove(leftValue);\r
183                 return leftValue;\r
184         }\r
185 \r
186         /**\r
187          * Get set of left values\r
188          *\r
189          * @return read-only set\r
190          */\r
191     public Set<L> getLeftSet() {\r
192         return imLeftSet;\r
193     }\r
194 \r
195     /**\r
196      * Get set of right values\r
197      *\r
198      * @return read-only set\r
199      */\r
200     public Set<R> getRightSet() {\r
201         return imRightSet;\r
202     }\r
203 \r
204     /**\r
205      * Get left-to-right map\r
206      *\r
207      * @return read only map\r
208      */\r
209     public Map<L, R> getLeftToRightMap() {\r
210         return imTableLeft;\r
211     }\r
212 \r
213     /**\r
214      * Get right-to-left map\r
215      *\r
216      * @return read only map\r
217      */\r
218     public Map<R, L> getRightToLeftMap() {\r
219         return imTableRight;\r
220     }\r
221 \r
222     public void clear() {\r
223         tableLeft.clear();\r
224         tableRight.clear();\r
225     }\r
226 \r
227     @Override\r
228     public String toString() {\r
229         int count = 0;\r
230         StringBuilder sb = new StringBuilder();\r
231         sb.append("[");\r
232         for (Entry<L, R> e : tableLeft.entrySet())\r
233         {\r
234                 if (count++>0) sb.append(", ");\r
235                 sb.append(e.getKey().toString());\r
236                 sb.append("=");\r
237                 sb.append(e.getValue().toString());\r
238         }\r
239         sb.append("]");\r
240         return sb.toString();\r
241     }\r
242 \r
243     @Override\r
244     public BijectionMap<L, R> clone() {\r
245         return new BijectionMap<L, R>(this);\r
246     }\r
247 \r
248 }\r