001/*-------------------------------------------------------------------------+ 002| | 003| Copyright 2005-2011 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016+-------------------------------------------------------------------------*/ 017package org.conqat.lib.commons.collections; 018 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Map.Entry; 022 023import org.conqat.lib.commons.assertion.CCSMAssert; 024 025/** 026 * A collection which implements a bidirectional mapping. 027 */ 028public class BidirectionalMap<S, T> { 029 030 /** Mapping from s to t. */ 031 private final Map<S, T> stMap; 032 033 /** Mapping from t to s. */ 034 private final Map<T, S> tsMap; 035 036 /** Creates new bidirectional map based on hash maps. */ 037 public BidirectionalMap() { 038 stMap = new HashMap<S, T>(); 039 tsMap = new HashMap<T, S>(); 040 } 041 042 /** Creates new bidirectional map based given maps. */ 043 @SuppressWarnings("null") 044 public BidirectionalMap(Map<S, T> stMap, Map<T, S> tsMap) { 045 CCSMAssert.isTrue(stMap != null && tsMap != null, "Maps may not be null!"); 046 CCSMAssert.isTrue(stMap != tsMap, "Maps may not be equal!"); 047 CCSMAssert.isTrue(stMap.isEmpty() && tsMap.isEmpty(), "Maps may not be used (filled)!"); 048 049 this.stMap = stMap; 050 this.tsMap = tsMap; 051 } 052 053 /** Get first element. */ 054 public S getFirst(T t) { 055 return tsMap.get(t); 056 } 057 058 /** Get second element. */ 059 public T getSecond(S s) { 060 return stMap.get(s); 061 } 062 063 /** Returns whether this map is empty. */ 064 public boolean isEmpty() { 065 return stMap.isEmpty(); 066 } 067 068 /** Returns the size. */ 069 public int size() { 070 return stMap.size(); 071 } 072 073 /** Clears the map. */ 074 public void clear() { 075 stMap.clear(); 076 tsMap.clear(); 077 } 078 079 /** 080 * Returns whether the given element is in the first set (the domain of the 081 * bijection). 082 */ 083 public boolean containsFirst(S s) { 084 return stMap.containsKey(s); 085 } 086 087 /** 088 * Returns whether the given element is in the second set (the range of the 089 * bijection). 090 */ 091 public boolean containsSecond(T t) { 092 return tsMap.containsKey(t); 093 } 094 095 /** Returns the first set (the domain). */ 096 public UnmodifiableSet<S> getFirstSet() { 097 return CollectionUtils.asUnmodifiable(stMap.keySet()); 098 } 099 100 /** Returns the second set (the range). */ 101 public UnmodifiableSet<T> getSecondSet() { 102 return CollectionUtils.asUnmodifiable(tsMap.keySet()); 103 } 104 105 /** Returns the entries. */ 106 public UnmodifiableSet<Entry<S, T>> getEntrySet() { 107 return CollectionUtils.asUnmodifiable(stMap.entrySet()); 108 } 109 110 /** Returns the inverted entries. */ 111 public UnmodifiableSet<Entry<T, S>> getInvertedEntrySet() { 112 return CollectionUtils.asUnmodifiable(tsMap.entrySet()); 113 } 114 115 /** 116 * Inserts the given pair into the bijection. Any mapping associated with 117 * those values is removed before. This map does not support null values. 118 */ 119 public void put(S s, T t) { 120 CCSMAssert.isTrue(s != null && t != null, "null values not supported."); 121 122 removeFirst(s); 123 removeSecond(t); 124 125 stMap.put(s, t); 126 tsMap.put(t, s); 127 } 128 129 /** Removes the first object */ 130 public void removeFirst(S s) { 131 T t = stMap.get(s); 132 if (t != null) { 133 stMap.remove(s); 134 tsMap.remove(t); 135 } 136 } 137 138 /** Removes the second object */ 139 public void removeSecond(T t) { 140 S s = tsMap.get(t); 141 if (s != null) { 142 stMap.remove(s); 143 tsMap.remove(t); 144 } 145 } 146 147 /** {@inheritDoc} */ 148 @Override 149 public String toString() { 150 return stMap.toString(); 151 } 152 153}