View Javadoc

1   /*
2    * Copyright (c) 2005-2007 Creative Sphere Limited.
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
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.extend.server.support;
14  
15  import java.util.Collection;
16  import java.util.LinkedHashMap;
17  import java.util.LinkedHashSet;
18  import java.util.Map;
19  import java.util.Set;
20  
21  /**
22   * This map maintains separate set of values. This allows if two key/value pairs contain same
23   * value and {@link #remove(Object)} method is called with value both values are going to be
24   * removed from the map. Also, having set of values {@link #values()} method returns that
25   * set which is faster. Values set is implemented as {@link LinkedHashSet}
26   * 
27   */
28  public class EnhancedMap<KeyType, ValueType> implements Map<KeyType, ValueType> {
29  
30      /** Map */
31      protected LinkedHashMap<KeyType, ValueType> map = new LinkedHashMap<KeyType, ValueType>();
32      
33      /** Values */
34      protected InternalSet<ValueType> values = new InternalSet<ValueType>();
35      
36      /** Empty constractor */
37      public EnhancedMap() {
38      }
39  
40      /**
41       * Returns get value
42       * @param key key
43       * @return value
44       */
45      public ValueType get(Object key) {
46          return map.get(key);
47      }
48      
49      /**
50       * Adds new element to the map
51       * @param key key
52       * @param value value
53       * @return previous value under that key
54       */
55      public ValueType put(KeyType key, ValueType value) {
56          values.add(value);
57          ValueType res = map.put(key, value);
58          return res;
59      }
60  
61      /**
62       * Removes value value
63       * @param value value to be removed
64       * @return <code>true</code> if removed
65       */
66      @SuppressWarnings("unchecked")
67      public ValueType remove(Object value) {
68          if (values.remove(value)) {
69              while (map.values().remove(value)) {
70              }
71              return (ValueType)value;
72          } else {
73              ValueType result = map.remove(value);
74              if (result != null) {
75                  if (!map.values().contains(result)) {
76                      values.remove(result);
77                  }
78              }
79              return result;
80          }
81      }
82      
83  
84      /**
85       * Clears the map.
86       */
87      public void clear() {
88          map.clear();
89          values.clear();
90      }
91  
92      /**
93       * Returns values
94       * @return values
95       */
96      public Collection<ValueType> values() {
97          return values;
98      }
99  
100     /**
101      * Checks map if key exsits
102      * @param key key
103      * @return <code>true</code> if key exists
104      */
105     public boolean containsKey(Object key) {
106         return map.containsKey(key);
107     }
108 
109     /**
110      * Checks values set if value exsits
111      * @param value value
112      * @return <code>true</code> if value exists
113      */
114     public boolean containsValue(Object value) {
115         return values.contains(value);
116     }
117 
118     /**
119      * Returns entry set of a map
120      * @return entry set of a map
121      */
122     public Set<Map.Entry<KeyType, ValueType>> entrySet() {
123         return map.entrySet();
124     }
125 
126     /**
127      * Returns if is empty
128      * @return <code>true</code> if is empty
129      */
130     public boolean isEmpty() {
131         return values.isEmpty();
132     }
133 
134     /**
135      * Returns key set
136      * @return key set
137      */
138     public Set<KeyType> keySet() {
139         return map.keySet();
140     }
141 
142     /**
143      * Stores all
144      * @param t map
145      */
146     public void putAll(Map<? extends KeyType, ? extends ValueType> t) {
147         values.addAll(t.values());
148         map.putAll(t);
149     }
150 
151     /**
152      * Returns map size
153      * @return map size
154      */
155     public int size() {
156         return map.size();
157     }
158     
159     /**
160      * Internal implementation of {@link LinkedHashSet} so invoking {@link LinkedHashSet#remove(Object)}
161      * method removes all values from the map as well
162      * 
163      * @param <Type>
164      * @author Daniel Sendula
165      */
166     protected class InternalSet<Type> extends LinkedHashSet<Type> {
167         public boolean remove(Object object) {
168             if (removeInternal(object)) {
169                 while (map.values().remove(object)) {
170                 }                
171                 return true;
172             } else {
173                 return false;
174             }
175         }
176        
177         /**
178          * Internal remove method - invokes super remove method.
179          * @param object object to be removed
180          * @return <code>true</code> if removed
181          */
182         protected boolean removeInternal(Object object) {
183             boolean removed = super.remove(object);
184             return removed;
185         }
186     }
187     
188     public static void main(String[] args) throws Exception {
189         EnhancedMap<String, Object>  map = new EnhancedMap<String, Object>();
190         
191         String key1 = "key1";
192         String key2 = "key2";
193         String key3 = "key3";
194         
195         Object o1 = new Object() { public String toString() { return "o1"; } };
196         Object o2 = new Object() { public String toString() { return "o2"; } };
197         
198         map.put(key1, o1);
199         map.put(key2, o2);
200         map.put(key3, o1);
201         
202         System.out.println("-----");
203         
204         for (Object value : map.values()) {
205             System.out.println(value);
206         }
207 
208         map.remove(key2);
209         
210         System.out.println("-----");
211         
212         for (Object value : map.values()) {
213             System.out.println(value);
214         }
215         
216         
217     }
218 }