X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.utils.datastructures%2Fsrc%2Forg%2Fsimantics%2Futils%2Fdatastructures%2FBijectionMap.java;fp=bundles%2Forg.simantics.utils.datastructures%2Fsrc%2Forg%2Fsimantics%2Futils%2Fdatastructures%2FBijectionMap.java;h=ab48c195e208ba0dd88cfbe2c6241dfee4bf58f5;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/BijectionMap.java b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/BijectionMap.java new file mode 100644 index 000000000..ab48c195e --- /dev/null +++ b/bundles/org.simantics.utils.datastructures/src/org/simantics/utils/datastructures/BijectionMap.java @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2007- VTT Technical Research Centre of Finland. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +/* + * Created on Jan 21, 2005 + * + * Copyright Toni Kalajainen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.simantics.utils.datastructures; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +/** + * Bijection map is a Map that has no values or keys, only 1:1 mappings + * of values. These value/keys will be called with left and right side + * values. + * + * Each value can exist only once on a side + * + * @author Toni Kalajainen + */ +public class BijectionMap { + + /** The keys of tableLeft are left-side-values and + * values are right-side-values */ + private final Map tableLeft = new HashMap(); + /** The keys of tableRight are right-side-values and + * values on it are left-side-values */ + private final Map tableRight = new HashMap(); + + /** The keys of tableLeft are left-side-values and + * values are right-side-values */ + private final Map imTableLeft = Collections.unmodifiableMap(tableLeft); + /** The keys of tableRight are right-side-values and + * values on it are left-side-values */ + private final Map imTableRight = Collections.unmodifiableMap(tableRight); + + private final Set imLeftSet = Collections.unmodifiableSet(tableLeft.keySet()); + private final Set imRightSet = Collections.unmodifiableSet(tableRight.keySet()); + + public BijectionMap() { + + } + + public BijectionMap(BijectionMap copyFrom) { + this.tableLeft.putAll(copyFrom.tableLeft); + this.tableRight.putAll(copyFrom.tableRight); + } + + public void addAll(BijectionMap map) + { + for (Entry e : map.getEntries()) + map(e.getKey(), e.getValue()); + } + + public boolean retainAllLeft(Collection values) + { + boolean result = false; + Collection remove = new ArrayList(size()); + for (L lValue : imLeftSet) { + if (!values.contains(lValue)) { + remove.add(lValue); + result = true; + } + } + if (!remove.isEmpty()) { + for (L lValue : remove) + removeWithLeft(lValue); + } + return result; + } + + public boolean retainAllRight(Collection values) + { + boolean result = false; + Collection remove = new ArrayList(size()); + for (R rValue : imRightSet) { + if (!values.contains(rValue)) { + remove.add(rValue); + result = true; + } + } + if (!remove.isEmpty()) { + for (R rValue : remove) + removeWithRight(rValue); + } + return result; + } + + public Set> getEntries() + { + return tableLeft.entrySet(); + } + + public boolean containsLeft(L leftValue) + { + return tableLeft.containsKey(leftValue); + } + + public boolean containsRight(R rightValue) + { + return tableRight.containsKey(rightValue); + } + + public boolean contains(L leftValue, R rightValue) + { + if (leftValue==null || rightValue==null) return false; + return rightValue.equals(tableLeft.get(leftValue)); + } + + public void map(L leftValue, R rightValue) + { + if (leftValue == null || rightValue == null) + throw new NullPointerException(); + // Remove possible old mapping + R oldRight = tableLeft.remove(leftValue); + if (oldRight != null) { + tableRight.remove(oldRight); + } else { + L oldLeft = tableRight.remove(rightValue); + if (oldLeft != null) { + tableLeft.remove(oldLeft); + } + } + + tableLeft.put(leftValue, rightValue); + tableRight.put(rightValue, leftValue); + } + + public boolean isEmpty() { + return tableLeft.isEmpty(); + } + + public int size() + { + return tableLeft.size(); + } + + public L getLeft(R rightValue) { + return tableRight.get(rightValue); + } + + public R getRight(L leftValue) { + return tableLeft.get(leftValue); + } + + public R removeWithLeft(L leftValue) { + R rightValue = tableLeft.remove(leftValue); + if (rightValue!=null) + tableRight.remove(rightValue); + return rightValue; + } + + public L removeWithRight(R rightValue) { + L leftValue = tableRight.remove(rightValue); + if (leftValue!=null) + tableLeft.remove(leftValue); + return leftValue; + } + + /** + * Get set of left values + * + * @return read-only set + */ + public Set getLeftSet() { + return imLeftSet; + } + + /** + * Get set of right values + * + * @return read-only set + */ + public Set getRightSet() { + return imRightSet; + } + + /** + * Get left-to-right map + * + * @return read only map + */ + public Map getLeftToRightMap() { + return imTableLeft; + } + + /** + * Get right-to-left map + * + * @return read only map + */ + public Map getRightToLeftMap() { + return imTableRight; + } + + public void clear() { + tableLeft.clear(); + tableRight.clear(); + } + + @Override + public String toString() { + int count = 0; + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (Entry e : tableLeft.entrySet()) + { + if (count++>0) sb.append(", "); + sb.append(e.getKey().toString()); + sb.append("="); + sb.append(e.getValue().toString()); + } + sb.append("]"); + return sb.toString(); + } + + @Override + public BijectionMap clone() { + return new BijectionMap(this); + } + +}