View Javadoc

1   /*
2    * Copyright (C) 2004 TiongHiang Lee
3    *
4    * This library is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Lesser General Public
6    * License as published by the Free Software Foundation; either
7    * version 2.1 of the License, or (at your option) any later version.
8    *
9    * This library is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this library; if not,  write to the Free Software
16   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17   *
18   * Email: thlee@onemindsoft.org
19   */
20  
21  package org.onemind.commons.java.datastructure;
22  
23  import java.util.HashMap;
24  /***
25   * A simple bi-directional map. It uses another map to store the inverse
26   * of this map. The key has to be unique in key space and the value need to
27   * be unique in the value space so that the value can be resolved to the key correctly.
28   * This class is not thread safe. 
29   * @author TiongHiang Lee (thlee@onemindsoft.org)
30   * @version $Id: BiMap.java,v 1.1 2004/09/29 02:45:35 thlee Exp $ $Name:  $
31   */
32  public class BiMap extends HashMap
33  {
34  
35      /*** the inverse **/
36      private final BiMap _inverse;
37  
38      /***
39       * Constructor
40       */
41      public BiMap()
42      {
43          _inverse = new BiMap(this);
44      }
45  
46      /***
47       * Constructor
48       * @param map the inverse
49       */
50      private BiMap(BiMap inverse)
51      {
52          _inverse = inverse;
53      }
54  
55      /***
56       * Get the inverse bimap
57       * @return the bimap
58       */
59      public BiMap getInverse()
60      {
61          return _inverse;
62      }
63  
64      /*** 
65       * {@inheritDoc}
66       */
67      public void clear()
68      {
69          super.clear();
70          _inverse.clear();
71      }
72  
73      /*** 
74       * {@inheritDoc}
75       */
76      public Object put(Object key, Object value)
77      {
78          //some critical checks that ensure correctness
79          if (containsKey(key))
80          {
81              if (_inverse.containsKey(value))
82              {//make sure it is true
83                  Object v = get(key);
84                  boolean sameValue = (v == null) ? v == value : v.equals(value);
85                  if (!sameValue)
86                  {
87                      throw new IllegalArgumentException("Value " + value + " exists in inverse");
88                  } //else ok
89              } //else ok
90          } else
91          {
92              if (_inverse.containsKey(value))
93              {//will cause conflict
94                  throw new IllegalArgumentException("Value " + value + " exists in inverse");
95              }
96          }
97          //pass the tests, do the things
98          remove(key);
99          _inverse.rawPut(value, key);
100         return rawPut(key, value);
101     }
102 
103     /***
104      * Put the key value association with super.put()
105      * @param key the key
106      * @param value the value
107      */
108     private Object rawPut(Object key, Object value)
109     {
110         return super.put(key, value);
111     }
112 
113     /***
114      * Remove the key
115      * @param key the key
116      * @return the value by super.remove();
117      */
118     private Object rawRemove(Object key)
119     {
120         return super.remove(key);
121     }
122 
123     /*** 
124      * {@inheritDoc}
125      */
126     public Object remove(Object key)
127     {
128         if (containsKey(key))
129         {
130             return _inverse.rawRemove(rawRemove(key));
131         } else
132         {
133             return null;
134         }
135     }
136 }