View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
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  
17  package org.apache.jdo.impl.model.jdo.caching;
18  
19  import java.util.HashMap;
20  import java.util.HashSet;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import org.apache.jdo.model.java.JavaModel;
25  import org.apache.jdo.model.jdo.JDOClass;
26  import org.apache.jdo.impl.model.jdo.JDOModelImplDynamic;
27  import org.apache.jdo.model.java.JavaType;
28  
29  import org.apache.jdo.util.StringHelper;
30  
31  /***
32   * A JDOModel instance bundles a number of JDOClass instances used by an 
33   * application. It provides factory methods to create and retrieve JDOClass 
34   * instances. A fully qualified class name must be unique within a JDOModel 
35   * instance. The model supports multiple classes having the same fully qualified 
36   * name by different JDOModel instances.
37   * <p>
38   * The caching JDOModel implementation caches any caclulated value to
39   * avoid re-calculating it if it is requested again. It is intended to
40   * be used in an environment where JDO metadata does NOT change
41   * (e.g. at runtime).
42   *
43   * @author Michael Bouschen
44   * @since 1.1
45   * @version 2.0
46   */
47  public class JDOModelImplCaching extends JDOModelImplDynamic {
48  
49      /***
50       * This is a mapping from short names to JDOClass instances. Key is the
51       * JDOClass short name, value is the corresponding JDOClass instance.  
52       */
53      private Map jdoClassesForShortNames = new HashMap();
54  
55      /*** 
56       * This is a mapping from ObjectId classes to its JDOClass instances.
57       * Key is the type representation of the ObjectId class, value is the 
58       * corresponding JDOClass instance. Note, in the case of inheritance
59       * the top most persistence-capable class is stored.
60       */
61      private Map jdoClassesForObjectIdClasses = new HashMap();
62  
63      /*** 
64       * Set of fully qualified names of classes known to be 
65       * non persistence-capable. 
66       */
67      private Set nonPCClasses = new HashSet();
68  
69      /*** 
70       * Constructor. 
71       * JDOModel instances are created using the JDOModelFactory only.
72       */
73      protected JDOModelImplCaching(JavaModel javaModel, 
74                                    boolean loadXMLMetadataDefault) {
75          super(javaModel, loadXMLMetadataDefault);
76      }
77  
78      /***
79       * The method returns the JDOClass instance for the specified short name
80       * (see {@link JDOClass#getShortName()}) or <code>null</code> if it cannot
81       * find a JDOClass instance with the specified short name. 
82       * <p>
83       * The method searches the list of JDOClasses currently managed by this
84       * JDOModel instance. It does not attempt to load any metadata if it
85       * cannot find a JDOClass instance with the specified short name. The
86       * metadata for a JDOClass returned by this method must have been loaded
87       * before by any of the methods
88       * {@link #createJDOClass(String className)},
89       * {@link #createJDOClass(String className, boolean loadXMLMetadataDefault)},
90       * {@link #getJDOClass(String className)}, or
91       * {@link #getJDOClass(String className, boolean loadXMLMetadataDefault)}.
92       * @param shortName the short name of the JDOClass instance to be returned
93       * @return a JDOClass instance for the specified short name 
94       * or <code>null</code> if not present
95       */
96      public synchronized JDOClass getJDOClassForShortName(String shortName) {
97          if (StringHelper.isEmpty(shortName))
98              return null;
99  
100         // First check the cache
101         JDOClass jdoClass = 
102             (JDOClass)jdoClassesForShortNames.get(shortName);
103         if (jdoClass == null) {
104             // not found in the cache => call super
105             jdoClass = super.getJDOClassForShortName(shortName);
106             if (jdoClass != null) {
107                 // found => update the cache
108                 jdoClassesForShortNames.put(shortName, jdoClass);
109             }
110         }
111         
112         return jdoClass;
113     }
114 
115     /***
116      * This method returns the JDOClass instance that defines the specified type
117      * as its objectId class. In the case of an inheritance hierarchy it returns 
118      * the top most persistence-capable class of the hierarchy (see 
119      * {@link JDOClass#getPersistenceCapableSuperclass}).
120      * @param objectIdClass the type representation of the ObjectId class
121      * @return the JDOClass defining the specified class as ObjectId class
122      */
123     public JDOClass getJDOClassForObjectIdClass(JavaType objectIdClass)
124     {
125         // Note, method getJDOClassForObjectIdClass is not synchronized to
126         // avoid a deadlock with PC class registration.
127         if (objectIdClass == null)
128             return null;
129 
130         synchronized (jdoClassesForObjectIdClasses) {
131             // First check the cache
132             JDOClass jdoClass = 
133                 (JDOClass)jdoClassesForObjectIdClasses.get(objectIdClass);
134             if (jdoClass == null) {
135                 // not found in the cache => call super
136                 jdoClass = super.getJDOClassForObjectIdClass(objectIdClass);
137                 if (jdoClass != null) {
138                     // found => update the cache
139                     jdoClassesForObjectIdClasses.put(objectIdClass, jdoClass);
140                 }
141             }
142             
143             return jdoClass;
144         }
145     }
146 
147     /*** Returns a new instance of the JDOClass implementation class. */
148     protected JDOClass newJDOClassInstance(String name) {
149         return new JDOClassImplCaching(name);
150     }
151 
152     /***
153      * Checks whether the type with the specified name does NOT denote a
154      * persistence-capable class.
155      * @param typeName name of the type to be checked
156      * @return <code>true</code> if types is a name of a primitive type; 
157      * <code>false</code> otherwise
158      */
159     protected boolean isKnownNonPC(String typeName) {
160         return super.isKnownNonPC(typeName) || nonPCClasses.contains(typeName);
161     }
162 
163     /*** 
164      * Hook called when a class is known to be non persistence
165      * capable.
166      * @param className the name of the non-pc class
167      */
168     protected void knownNonPC(String className) {
169         nonPCClasses.add(className);
170     }
171 }