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
9 * VTT Technical Research Centre of Finland - initial API and implementation
10 *******************************************************************************/
12 * Created on Jan 21, 2005
14 * Copyright Toni Kalajainen
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
20 * http://www.apache.org/licenses/LICENSE-2.0
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.
28 package org.simantics.databoard.util;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.HashMap;
35 import java.util.Map.Entry;
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
43 * Each value can exist only once on a side
45 * @author Toni Kalajainen
47 public class BijectionMap<L, R> {
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>();
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);
63 private final Set<L> imLeftSet = Collections.unmodifiableSet(tableLeft.keySet());
64 private final Set<R> imRightSet = Collections.unmodifiableSet(tableRight.keySet());
66 public BijectionMap() {
70 public BijectionMap(BijectionMap<L, R> copyFrom) {
71 this.tableLeft.putAll(copyFrom.tableLeft);
72 this.tableRight.putAll(copyFrom.tableRight);
75 public void addAll(BijectionMap<L, R> map)
77 for (Entry<L, R> e : map.getEntries())
78 map(e.getKey(), e.getValue());
81 public boolean retainAllLeft(Collection<L> values)
83 boolean result = false;
84 Collection<L> remove = new ArrayList<L>(size());
85 for (L lValue : imLeftSet) {
86 if (!values.contains(lValue)) {
91 if (!remove.isEmpty()) {
92 for (L lValue : remove)
93 removeWithLeft(lValue);
98 public boolean retainAllRight(Collection<R> values)
100 boolean result = false;
101 Collection<R> remove = new ArrayList<R>(size());
102 for (R rValue : imRightSet) {
103 if (!values.contains(rValue)) {
108 if (!remove.isEmpty()) {
109 for (R rValue : remove)
110 removeWithRight(rValue);
115 public Set<Entry<L, R>> getEntries()
117 return tableLeft.entrySet();
120 public boolean containsLeft(L leftValue)
122 return tableLeft.containsKey(leftValue);
125 public boolean containsRight(R rightValue)
127 return tableRight.containsKey(rightValue);
130 public boolean contains(L leftValue, R rightValue)
132 if (leftValue==null || rightValue==null) return false;
133 return rightValue.equals(tableLeft.get(leftValue));
136 public void map(L leftValue, R rightValue)
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);
145 L oldLeft = tableRight.remove(rightValue);
146 if (oldLeft != null) {
147 tableLeft.remove(oldLeft);
151 tableLeft.put(leftValue, rightValue);
152 tableRight.put(rightValue, leftValue);
155 public boolean isEmpty() {
156 return tableLeft.isEmpty();
161 return tableLeft.size();
164 public L getLeft(R rightValue) {
165 return tableRight.get(rightValue);
168 public R getRight(L leftValue) {
169 return tableLeft.get(leftValue);
172 public R removeWithLeft(L leftValue) {
173 R rightValue = tableLeft.remove(leftValue);
174 if (rightValue!=null)
175 tableRight.remove(rightValue);
179 public L removeWithRight(R rightValue) {
180 L leftValue = tableRight.remove(rightValue);
182 tableLeft.remove(leftValue);
187 * Get set of left values
189 * @return read-only set
191 public Set<L> getLeftSet() {
196 * Get set of right values
198 * @return read-only set
200 public Set<R> getRightSet() {
205 * Get left-to-right map
207 * @return read only map
209 public Map<L, R> getLeftToRightMap() {
214 * Get right-to-left map
216 * @return read only map
218 public Map<R, L> getRightToLeftMap() {
222 public void clear() {
228 public String toString() {
230 StringBuilder sb = new StringBuilder();
232 for (Entry<L, R> e : tableLeft.entrySet())
234 if (count++>0) sb.append(", ");
235 sb.append(e.getKey().toString());
237 sb.append(e.getValue().toString());
240 return sb.toString();
244 public BijectionMap<L, R> clone() {
245 return new BijectionMap<L, R>(this);