1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jdo.impl.model.java;
18
19 import java.util.Iterator;
20 import java.util.Map;
21 import java.util.HashMap;
22
23 import org.apache.jdo.model.ModelException;
24 import org.apache.jdo.model.ModelFatalException;
25 import org.apache.jdo.model.java.JavaModel;
26 import org.apache.jdo.model.java.JavaModelFactory;
27 import org.apache.jdo.model.java.JavaType;
28 import org.apache.jdo.util.I18NHelper;
29
30 /***
31 * Abstract super class for JavaModelFactory implementations. It provides a
32 * JavaModel cache and implements the JavaModel lookup method
33 * {@link #getJavaModel(Object key)}.
34 * <p>
35 * A non-abstract subclass must implement method
36 * {@link #createJavaModel(Object key)}. The lookup method calls this
37 * method if it cannot find a JavaModel instance in the cache. The method
38 * should also check whether the specified key is of an appropriate type
39 * for the JavaModelFactory implementation. A subclass should check whether
40 * it can implement method {@link #getJavaType(Object typeDesc)}. The
41 * implementation in AbstractJavaModelFactory always throws a
42 * ModelFatalException.
43 *
44 * @author Michael Bouschen
45 * @since 1.0.1
46 * @version 2.0
47 */
48 abstract public class AbstractJavaModelFactory
49 implements JavaModelFactory
50 {
51 /***
52 * Map of JavaModel instances, key is implementation specific.
53 * @see #getJavaModel(Object key)
54 */
55 private Map modelCache = new HashMap();
56
57 /*** I18N support */
58 private static I18NHelper msg =
59 I18NHelper.getInstance(AbstractJavaModelFactory.class);
60
61 /***
62 * Creates a new empty JavaModel instance. A factory implementation may
63 * use the specified key when caching the new JavaModel instance.
64 * <p>
65 * Each JavaModelFactory imposes its own restrictions for the keys to
66 * cache JavaModel instances. Some implementation will allow only keys
67 * of a certain type. Some implementations will prohibit
68 * <code>null</code> keys. Attempting to use an ineligible key will
69 * result in a {@link org.apache.jdo.model.ModelException}. This means
70 * the specified key is of an inappropriate type for this
71 * JavaModelFactory or if the key is <code>null</code> and this
72 * JavaModelFactory does not support <code>null</code> keys.
73 * @param key the key that may be used to cache the returned JavaModel instance.
74 * @return a new JavaModel instance.
75 * @exception ModelException if impossible; the key is of an
76 * inappropriate type or the key is <code>null</code> and this
77 * JavaModelFactory does not support <code>null</code> keys.
78 */
79 abstract public JavaModel createJavaModel(Object key)
80 throws ModelException;
81
82 /***
83 * Returns the JavaModel instance for the specified key.
84 * <p>
85 * The method throws a {@link org.apache.jdo.model.ModelFatalException},
86 * if the specified key is of an inappropriate type for this
87 * JavaModelFactory or if the key is <code>null</code> and this
88 * JavaModelFactory does not support <code>null</code> keys.
89 * @param key the key used to cache the returned JavaModel instance.
90 * @return a JavaModel instance for the specified key.
91 * @exception ModelFatalException the key is of an inappropriate type
92 * or the key is <code>null</code> and this JavaModelFactory does not
93 * support <code>null</code> keys.
94 */
95 public JavaModel getJavaModel(Object key)
96 {
97 synchronized (modelCache) {
98 JavaModel javaModel = (JavaModel)modelCache.get(key);
99 if (javaModel == null) {
100
101 try {
102 javaModel = createJavaModel(key);
103 modelCache.put(key, javaModel);
104 }
105 catch (ModelException ex) {
106 throw new ModelFatalException(
107 msg.msg("EXC_CannotCreateJavaModel"), ex);
108 }
109 }
110 return javaModel;
111 }
112 }
113
114 /***
115 * Removes the specified javaModel from the JavaModel cache. Note, if
116 * there are multiple entries in the cache with the specified javaModel
117 * as value, then all of them get removed. The method does not have an
118 * effect, if this factory does not have the specified javaModel.
119 * @param javaModel the JavaModel to be removed.
120 * @since 2.0
121 */
122 public void removeJavaModel(JavaModel javaModel) {
123 if (javaModel == null) {
124
125 return;
126 }
127
128 synchronized (modelCache) {
129 for (Iterator i = modelCache.entrySet().iterator(); i.hasNext();) {
130 Map.Entry entry = (Map.Entry) i.next();
131 Object value = entry.getValue();
132 if ((javaModel == value) || javaModel.equals(value)) {
133
134 i.remove();
135 }
136 }
137 }
138 }
139
140 /***
141 * Removes the JavaModel for the specified key from the JavaModel
142 * cache. The method does not have an effect, if this factory does not
143 * have a JavaModel for the the specified key.
144 * @param key the key used to find the JavaModel instance to be removed.
145 * @since 2.0
146 */
147 public void removeJavaModel(Object key) {
148 synchronized (modelCache) {
149 modelCache.remove(key);
150 }
151 }
152
153 /***
154 * Returns a JavaType instance for the specified type description
155 * (optional operation). This method is a convenience method and a
156 * short cut for <code>getJavaModel(key).getJavaType(typeName)</code>.
157 * If the factory supports this method, it needs to be able to get the
158 * key for the JavaModel lookup and the type name for the JavaType
159 * lookup from the specified typeDesc. An example for such a type
160 * description is the java.lang.Class instance in the runtime
161 * environment.
162 * <p>
163 * The method throws a {@link org.apache.jdo.model.ModelFatalException},
164 * if this factory does not support this short cut or if it does not
165 * support the specified type description.
166 * <p>
167 * This implementation always throws a ModelFatalException.
168 * @param typeDesc the type description.
169 * @return a JavaType instance for the specified type.
170 * @exception ModelFatalException this factory does not support this
171 * short cut or does not support the specified type description.
172 */
173 public JavaType getJavaType(Object typeDesc)
174 {
175 throw new ModelFatalException(msg.msg(
176 "EXC_MethodNotSupported", this.getClass().getName(),
177 "getJavaType"));
178 }
179
180 }
181