1 package org.andromda.core.metafacade;
2
3 import java.io.Serializable;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 /**
8 * A global cache for metafacades. Used by the {@link MetafacadeFactory}when constructing or retrieving metafacade
9 * instances. If the cache constains the metafacade it should not be constructed again.
10 *
11 * @author Chad Brandon
12 */
13 public final class MetafacadeCache
14 implements Serializable
15 {
16 private static final long serialVersionUID = 34L;
17
18 /**
19 * Constructs a new instance of this class.
20 *
21 * @return the new instance
22 */
23 public static MetafacadeCache newInstance()
24 {
25 return new MetafacadeCache();
26 }
27
28 private MetafacadeCache()
29 {
30 // don't allow instantiation
31 }
32
33 /**
34 * The namespace to which the cache currently applies
35 */
36 private String namespace;
37
38 /**
39 * Sets the namespace to which the cache currently applies.
40 *
41 * @param namespace the current namespace.
42 */
43 public final void setNamespace(final String namespace)
44 {
45 this.namespace = namespace;
46 }
47
48 /**
49 * The cache for already created metafacades.
50 */
51 private final Map<Object, Map<Class, Map<String, MetafacadeBase>>> metafacadeCache = new HashMap<Object, Map<Class, Map<String, MetafacadeBase>>>();
52
53 /**
54 * <p>
55 * Returns the metafacade from the metafacade cache. The Metafacades are cached first by according to its
56 * <code>mappingObject</code>, next the <code>metafacadeClass</code>, and finally by the current namespace. </p>
57 * <p>
58 * Metafacades must be cached in order to keep track of the state of its validation. If we keep creating a new one
59 * each time, we can never tell whether or not a metafacade has been previously validated. Not to mention tremendous
60 * performance gains. </p>
61 *
62 * @param mappingObject the object to which the mapping applies
63 * @param metafacadeClass the class of the metafacade.
64 * @return MetafacadeBase stored in the cache.
65 */
66 public final MetafacadeBase get(
67 final Object mappingObject,
68 final Class metafacadeClass)
69 {
70 MetafacadeBase metafacade = null;
71 final Map<Class, Map<String, MetafacadeBase>> namespaceMetafacadeCache = this.metafacadeCache.get(mappingObject);
72 if (namespaceMetafacadeCache != null)
73 {
74 final Map<String, MetafacadeBase> metafacadeCache = namespaceMetafacadeCache.get(metafacadeClass);
75 if (metafacadeCache != null)
76 {
77 metafacade = metafacadeCache.get(this.namespace);
78 }
79 }
80 return metafacade;
81 }
82
83 /**
84 * Adds the <code>metafacade</code> to the cache according to first <code>mappingObject</code>, second the
85 * <code>metafacade</code>, and finally by the current <code>namespace</code>.
86 *
87 * @param mappingObject the mappingObject for which to cache the metafacade.
88 * @param metafacade the metafacade to cache.
89 */
90 public final void add(
91 final Object mappingObject,
92 final MetafacadeBase metafacade)
93 {
94 Map<Class, Map<String, MetafacadeBase>> namespaceMetafacadeCache = this.metafacadeCache.get(mappingObject);
95 if (namespaceMetafacadeCache == null)
96 {
97 namespaceMetafacadeCache = new HashMap<Class, Map<String, MetafacadeBase>>();
98 this.metafacadeCache.put(mappingObject, namespaceMetafacadeCache);
99 }
100 Map<String, MetafacadeBase> metafacadeCache = namespaceMetafacadeCache.get(metafacade.getClass());
101 if (metafacadeCache == null)
102 {
103 metafacadeCache = new HashMap<String, MetafacadeBase>();
104 namespaceMetafacadeCache.put(
105 metafacade.getClass(),
106 metafacadeCache);
107 }
108 metafacadeCache.put(this.namespace, metafacade);
109 }
110
111 /**
112 * Clears the cache of any metafacades
113 */
114 public final void clear()
115 {
116 this.metafacadeCache.clear();
117 }
118
119 /**
120 * @see Object#toString()
121 */
122 public String toString()
123 {
124 return this.metafacadeCache.toString();
125 }
126 }