View Javadoc

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