View Javadoc

1   /*
2      Copyright 2007 Ramon Servadei
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  package fulmine.util.reference;
17  
18  import java.util.Collection;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import fulmine.util.collection.CollectionFactory;
23  import fulmine.util.collection.CollectionUtils;
24  
25  /**
26   * This implementation manages a {@link Map} of objects against their key. When
27   * the store is requested for an object, identified by its key, it returns the
28   * cached object. The store uses an internal {@link IObjectBuilder} to create
29   * instances of objects that do not exist.
30   * <p>
31   * This is thread safe; all methods are synchronized and return a copy of the
32   * collection where appropriate.
33   * 
34   * @author Ramon Servadei
35   * 
36   * @param <KEY>
37   *            The type of the key used to access objects in this store
38   * @param <TYPE>
39   *            The type of canonical objects this returns
40   */
41  public final class AutoCreatingStore<KEY, TYPE> implements
42      IAutoCreatingStore<KEY, TYPE>
43  {
44      /** The builder to create the canonical object for each key */
45      private final IObjectBuilder<KEY, TYPE> builder;
46  
47      /** The registry of canonical objects against their canonical representation */
48      private final Map<KEY, TYPE> registry = CollectionFactory.newMap(1);
49  
50      /**
51       * Standard constructor
52       * 
53       * @param builder
54       *            the builder to use when constructing new canonical object
55       *            instances
56       */
57      public AutoCreatingStore(IObjectBuilder<KEY, TYPE> builder)
58      {
59          super();
60          this.builder = builder;
61      }
62  
63      public synchronized TYPE get(KEY key)
64      {
65          if (!registry.containsKey(key))
66          {
67              registry.put(key, builder.create(key));
68          }
69          return registry.get(key);
70      }
71  
72      public synchronized TYPE remove(KEY key)
73      {
74          if (registry.containsKey(key))
75          {
76              return registry.remove(key);
77          }
78          return null;
79      }
80  
81      public synchronized boolean containsKey(KEY key)
82      {
83          return registry.containsKey(key);
84      }
85  
86      public synchronized void clear()
87      {
88          this.registry.clear();
89      }
90  
91      public synchronized Set<KEY> keySet()
92      {
93          return CollectionFactory.newSet(this.registry.keySet());
94      }
95  
96      public synchronized Collection<TYPE> values()
97      {
98          return CollectionFactory.newList(this.registry.values());
99      }
100 
101     public synchronized void destroy()
102     {
103         this.registry.clear();
104     }
105 
106     @Override
107     public synchronized String toString()
108     {
109         return getClass().getSimpleName()
110             + CollectionUtils.toFormattedString(this.registry);
111     }
112 
113     @Override
114     public synchronized int hashCode()
115     {
116         final int prime = 31;
117         int result = 1;
118         result =
119             prime * result + ((registry == null) ? 0 : registry.hashCode());
120         return result;
121     }
122 
123     @SuppressWarnings("unchecked")
124     @Override
125     public synchronized boolean equals(Object obj)
126     {
127         if (is.same(this, obj))
128         {
129             return true;
130         }
131         if (is.differentClass(this, obj))
132         {
133             return false;
134         }
135         final AutoCreatingStore other = (AutoCreatingStore) obj;
136         return is.eq(this.registry, other.registry);
137     }
138 }