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