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