]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop/src/org/simantics/interop/utils/LinkedBijectionMap.java
refs #3169
[simantics/interop.git] / org.simantics.interop / src / org / simantics / interop / utils / LinkedBijectionMap.java
1 package org.simantics.interop.utils;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Collections;\r
6 import java.util.LinkedHashMap;\r
7 import java.util.Map;\r
8 import java.util.Set;\r
9 import java.util.Map.Entry;\r
10 \r
11 import org.simantics.utils.datastructures.BijectionMap;\r
12 \r
13 public class LinkedBijectionMap<L, R> {\r
14         /** The keys of tableLeft are left-side-values and\r
15      * values are right-side-values */\r
16     private final Map<L, R> tableLeft = new LinkedHashMap<L, R>();\r
17     /** The keys of tableRight are right-side-values and\r
18      * values on it are left-side-values */\r
19     private final Map<R, L> tableRight = new LinkedHashMap<R, L>();\r
20 \r
21     /** The keys of tableLeft are left-side-values and\r
22      * values are right-side-values */\r
23     private final Map<L, R> imTableLeft = Collections.unmodifiableMap(tableLeft);\r
24     /** The keys of tableRight are right-side-values and\r
25      * values on it are left-side-values */\r
26     private final Map<R, L> imTableRight = Collections.unmodifiableMap(tableRight);\r
27 \r
28     private final Set<L> imLeftSet = Collections.unmodifiableSet(tableLeft.keySet());\r
29     private final Set<R> imRightSet = Collections.unmodifiableSet(tableRight.keySet());\r
30 \r
31         public LinkedBijectionMap() {\r
32 \r
33         }\r
34 \r
35         public LinkedBijectionMap(LinkedBijectionMap<L, R> copyFrom) {\r
36                 this.tableLeft.putAll(copyFrom.tableLeft);\r
37                 this.tableRight.putAll(copyFrom.tableRight);\r
38         }\r
39 \r
40         public void addAll(BijectionMap<L, R> map)\r
41         {\r
42                 for (Entry<L, R> e : map.getEntries())\r
43                         map(e.getKey(), e.getValue());\r
44         }\r
45 \r
46     public boolean retainAllLeft(Collection<L> values)\r
47     {\r
48         boolean result = false;\r
49         Collection<L> remove = new ArrayList<L>(size());\r
50         for (L lValue : imLeftSet) {\r
51             if (!values.contains(lValue)) {\r
52                 remove.add(lValue);\r
53                 result = true;\r
54             }\r
55         }\r
56         if (!remove.isEmpty()) {\r
57             for (L lValue : remove)\r
58                 removeWithLeft(lValue);\r
59         }\r
60         return result;\r
61     }\r
62 \r
63     public boolean retainAllRight(Collection<R> values)\r
64     {\r
65         boolean result = false;\r
66         Collection<R> remove = new ArrayList<R>(size());\r
67         for (R rValue : imRightSet) {\r
68             if (!values.contains(rValue)) {\r
69                 remove.add(rValue);\r
70                 result = true;\r
71             }\r
72         }\r
73         if (!remove.isEmpty()) {\r
74             for (R rValue : remove)\r
75                 removeWithRight(rValue);\r
76         }\r
77         return result;\r
78     }\r
79 \r
80         public Set<Entry<L, R>> getEntries()\r
81         {\r
82                 return tableLeft.entrySet();\r
83         }\r
84 \r
85         public boolean containsLeft(L leftValue)\r
86         {\r
87                 return tableLeft.containsKey(leftValue);\r
88         }\r
89 \r
90         public boolean containsRight(R rightValue)\r
91         {\r
92                 return tableRight.containsKey(rightValue);\r
93         }\r
94 \r
95         public boolean contains(L leftValue, R rightValue)\r
96         {\r
97                 if (leftValue==null || rightValue==null) return false;\r
98                 return rightValue.equals(tableLeft.get(leftValue));\r
99         }\r
100 \r
101         public void map(L leftValue, R rightValue)\r
102         {\r
103         if (leftValue == null || rightValue == null)\r
104             throw new NullPointerException();\r
105         // Remove possible old mapping\r
106         R oldRight = tableLeft.remove(leftValue);\r
107         if (oldRight != null) {\r
108             tableRight.remove(oldRight);\r
109         } else {\r
110             L oldLeft = tableRight.remove(rightValue);\r
111             if (oldLeft != null) {\r
112                 tableLeft.remove(oldLeft);\r
113             }\r
114         }\r
115 \r
116                 tableLeft.put(leftValue, rightValue);\r
117                 tableRight.put(rightValue, leftValue);\r
118         }\r
119 \r
120         public boolean isEmpty() {\r
121             return tableLeft.isEmpty();\r
122         }\r
123 \r
124     public int size()\r
125     {\r
126         return tableLeft.size();\r
127     }\r
128 \r
129         public L getLeft(R rightValue) {\r
130                 return tableRight.get(rightValue);\r
131         }\r
132 \r
133         public R getRight(L leftValue) {\r
134                 return tableLeft.get(leftValue);\r
135         }\r
136 \r
137         public R removeWithLeft(L leftValue) {\r
138                 R rightValue = tableLeft.remove(leftValue);\r
139                 if (rightValue!=null)\r
140                         tableRight.remove(rightValue);\r
141                 return rightValue;\r
142         }\r
143 \r
144         public L removeWithRight(R rightValue) {\r
145                 L leftValue = tableRight.remove(rightValue);\r
146                 if (leftValue!=null)\r
147                         tableLeft.remove(leftValue);\r
148                 return leftValue;\r
149         }\r
150 \r
151         /**\r
152          * Get set of left values\r
153          *\r
154          * @return read-only set\r
155          */\r
156     public Set<L> getLeftSet() {\r
157         return imLeftSet;\r
158     }\r
159 \r
160     /**\r
161      * Get set of right values\r
162      *\r
163      * @return read-only set\r
164      */\r
165     public Set<R> getRightSet() {\r
166         return imRightSet;\r
167     }\r
168 \r
169     /**\r
170      * Get left-to-right map\r
171      *\r
172      * @return read only map\r
173      */\r
174     public Map<L, R> getLeftToRightMap() {\r
175         return imTableLeft;\r
176     }\r
177 \r
178     /**\r
179      * Get right-to-left map\r
180      *\r
181      * @return read only map\r
182      */\r
183     public Map<R, L> getRightToLeftMap() {\r
184         return imTableRight;\r
185     }\r
186 \r
187     public void clear() {\r
188         tableLeft.clear();\r
189         tableRight.clear();\r
190     }\r
191 \r
192     @Override\r
193     public String toString() {\r
194         int count = 0;\r
195         StringBuilder sb = new StringBuilder();\r
196         sb.append("[");\r
197         for (Entry<L, R> e : tableLeft.entrySet())\r
198         {\r
199                 if (count++>0) sb.append(", ");\r
200                 sb.append(e.getKey().toString());\r
201                 sb.append("=");\r
202                 sb.append(e.getValue().toString());\r
203         }\r
204         sb.append("]");\r
205         return sb.toString();\r
206     }\r
207 \r
208     @Override\r
209     public LinkedBijectionMap<L, R> clone() {\r
210         return new LinkedBijectionMap<L, R>(this);\r
211     }\r
212 }\r