You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 19:44:23 UTC

svn commit: r171348 [4/7] - in /incubator/jdo/trunk/core20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/model/ src/java/org/apache/jdo/impl/model/java/ src/java/org/apache/jdo/impl/model/java/reflection/ src/java/org/apache/jdo/impl/model/jdo/ src/java/org/apache/jdo/impl/model/jdo/caching/ src/java/org/apache/jdo/impl/model/jdo/util/ src/java/org/apache/jdo/impl/model/jdo/xml/ src/java/org/apache/jdo/model/ src/java/org/apache/jdo/model/java/ src/java/org/apache/jdo/model/jdo/ src/java/org/apache/jdo/util/

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOMemberImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOMemberImpl.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOMemberImpl.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOMemberImpl.java Sun May 22 10:44:19 2005
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import java.text.Collator;
+
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOMember;
+
+/**
+ * This is the super interface for named JDO metadata elements, 
+ * such as JDOClass and JDOField.
+ *
+ * @author Michael Bouschen
+ */
+public class JDOMemberImpl
+    extends JDOElementImpl
+    implements JDOMember
+{
+    /** Property name.*/
+    private String name;
+
+    /** Relationship JDOClass<->JDOMember. */
+    private JDOClass declaringClass;
+
+    /**
+     * Returns the name of this JDOMember.
+     * @return the name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Sets the name of this JDOMember.
+     * @param name the name
+     */
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    /** 
+     * Get the declaring class of this JDOMember.
+     * @return the class that owns this JDOMember, or <code>null</code>
+     * if the element is not attached to any class
+     */
+    public JDOClass getDeclaringClass()
+    {
+        return declaringClass;
+    }
+
+    /** 
+     * Set the declaring class of this JDOMember.
+     * @param declaringClass the declaring class of this member element
+     */
+    public void setDeclaringClass(JDOClass declaringClass)
+    {
+        this.declaringClass = declaringClass;
+    }
+
+    //================= redefinition of java.lang.Object methods ================
+    
+    /** 
+     * Overrides Object's <code>toString</code> method to return the name
+     * of this persistence element.
+     * @return a string representation of the object
+     */
+    public String toString () 
+    { 
+        return getName(); 
+    }
+    
+    /** 
+     * Overrides Object's <code>equals</code> method by comparing the name 
+     * of this member with the name of the argument obj. The method returns 
+     * <code>false</code> if obj does not have the same dynamic type as this 
+     * member.
+     * @return <code>true</code> if this object is the same as the obj argument;
+     * <code>false</code> otherwise.
+     * @param obj the reference object with which to compare.
+     */
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+            return false;
+        if (obj == this)
+            return true;
+        
+        // check for the right class and then do the name check by 
+        // calling compareTo.
+        return (getClass() == obj.getClass()) && (compareTo(obj) == 0);
+    }
+    
+    /** Overrides Object's <code>hashCode</code> method to return the hashCode 
+     * of this name.
+     * @return a hash code value for this object.
+     */
+    public int hashCode()
+    {
+        return (getName()==null) ? 0 : getName().hashCode();
+    }
+    
+    //================= implementation of Comparable ================
+    
+    /** 
+     * Compares this object with the specified object for order. Returns a 
+     * negative integer, zero, or a positive integer as this object is less than, 
+     * equal to, or greater than the specified object. The specified object must 
+     * be a an instance of JDOMember, if not a ClassCastException is thrown.
+     * The order of JDOMember instances is defined by the order of their names.
+     * JDOMember instances without name are considered to be less than any named 
+     * member.
+     * @param o the Object to be compared.
+     * @return a negative integer, zero, or a positive integer as this object is
+     * less than, equal to, or greater than the specified object.
+     * @exception ClassCastException - if the specified object is null or is not 
+     * an instance of JDOMember
+     */
+    public int compareTo(Object o)
+    {
+        // null is not allowed
+        if (o == null)
+            throw new ClassCastException();
+        if (o == this)
+            return 0;
+        
+        String thisName = getName();
+        // the following throws a ClassCastException if o is not a JDOMember
+        String otherName = ((JDOMember)o).getName();
+        // if this does not have a name it should compare less than any named
+        if (thisName == null) {
+            return (otherName == null) ? 0 : -1;
+        }
+        
+        // if this is named and o does not have a name it should compare greater
+        if (otherName == null) {
+            return 1;
+        }
+        
+        // now we know that this and o are named JDOMembers => compare the names
+        int ret = thisName.compareTo(otherName);
+        // If both names are equal, both objects might have different types.
+        // If so order both objects by their type names 
+        // (necessary to be consistent with equals)
+        if ((ret == 0) && (getClass() != o.getClass()))
+            ret = getClass().getName().compareTo(o.getClass().getName());
+        return ret;
+    }
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelFactoryImplDynamic.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelFactoryImplDynamic.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelFactoryImplDynamic.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelFactoryImplDynamic.java Sun May 22 10:44:19 2005
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.jdo.model.java.JavaModel;
+import org.apache.jdo.model.jdo.JDOModel;
+import org.apache.jdo.model.jdo.JDOModelFactory;
+
+/**
+ * Factory for dynamic JDOModel instances. The factory provides a
+ * mechanism to cache JDOModel instances per JavaModel instances. 
+ * <p>
+ * TBD:
+ * <ul>
+ * <li> Check synchronization.
+ * </ul>
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOModelFactoryImplDynamic implements JDOModelFactory {
+
+    /**
+     * Map of JDOModel instances, key is the JavaModel
+     * {@link #getJDOModel(JavaModel javaModel)} 
+     */
+    private Map modelCache = new HashMap();
+
+    /** The singleton JDOModelFactory instance. */    
+    private static JDOModelFactory jdoModelFactory = 
+        new JDOModelFactoryImplDynamic();
+
+    /**
+     * Creates new JDOModelFactory. This constructor should not be
+     * called directly; instead, the singleton access method  
+     * {@link #getInstance} should be used.
+     */
+    protected JDOModelFactoryImplDynamic() {}
+
+    /** 
+     * Get an instance of JDOModelFactory.
+     * @return an instance of JDOModelFactory
+     */    
+    public static JDOModelFactory getInstance() {
+        return jdoModelFactory;
+    }
+    
+    /**
+     * Creates a new empty JDOModel instance.
+     * The returned JDOModel instance uses the specified flag
+     * <code>loadXMLMetadataDefault</code> to set the default behavior 
+     * for the creation of new JDOClass instances  using methods 
+     * {@link JDOModel#createJDOClass(String)} and 
+     * {@link JDOModel#getJDOClass(String)} for which the caller doesn't 
+     * explicitly specify whether to read XML metatdata or not.
+     * @param loadXMLMetadataDefault the default setting for whether to 
+     * read XML metatdata in JDOModel's methods for JDOClass creation.
+     */
+    public JDOModel createJDOModel(JavaModel javaModel,
+                                   boolean loadXMLMetadataDefault) {
+        return new JDOModelImplDynamic(javaModel, loadXMLMetadataDefault);
+    }
+    
+    /**
+     * Returns the JDOModel instance for the specified JavaModel.
+     * @param javaModel the javaModel used to cache the returned JDOModel
+     * instance.
+     */
+    public JDOModel getJDOModel(JavaModel javaModel) {
+        return getJDOModel(javaModel, true);
+    }
+
+    /**
+     * Returns the JDOModel instance for the specified JavaModel.  
+     * The returned JDOModel instance uses the specified flag
+     * <code>loadXMLMetadataDefault</code> to set the default behavior 
+     * for the creation of new JDOClass instances  using methods 
+     * {@link JDOModel#createJDOClass(String)} and 
+     * {@link JDOModel#getJDOClass(String)} for which the caller doesn't 
+     * explicitly specify whether to read XML metatdata or not.
+     * @param loadXMLMetadataDefault the default setting for whether to 
+     * read XML metatdata in JDOModel's methods for JDOClass creation.
+     */
+    public JDOModel getJDOModel(JavaModel javaModel,
+                                boolean loadXMLMetadataDefault) {
+        synchronized (this.modelCache) {
+            JDOModel jdoModel = (JDOModel)modelCache.get(javaModel);
+            if (jdoModel == null) {
+                // create new model and store it using the specified javaModel
+                jdoModel = createJDOModel(javaModel, loadXMLMetadataDefault);
+                modelCache.put(javaModel, jdoModel);
+            }
+            return jdoModel;
+        }
+    }
+
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelImplDynamic.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelImplDynamic.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelImplDynamic.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOModelImplDynamic.java Sun May 22 10:44:19 2005
@@ -0,0 +1,717 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.impl.model.jdo.xml.JDOHandler;
+import org.apache.jdo.impl.model.jdo.xml.JDOHandlerImpl;
+import org.apache.jdo.impl.model.jdo.xml.JDOParser;
+import org.apache.jdo.model.ModelException;
+import org.apache.jdo.model.ModelFatalException;
+import org.apache.jdo.model.java.JavaModel;
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOModel;
+import org.apache.jdo.model.jdo.JDOModelFactory;
+import org.apache.jdo.model.jdo.JDOPackage;
+import org.apache.jdo.util.I18NHelper;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.InputSource;
+
+/**
+ * A JDOModel instance bundles a number of JDOClass instances used by an 
+ * application. It provides factory methods to create and retrieve JDOClass 
+ * instances. A fully qualified class name must be unique within a JDOModel 
+ * instance. The model supports multiple classes having the same fully qualified 
+ * name by different JDOModel instances.
+ * <p>
+ * The dynamic JDOModel implementation does not store any internally
+ * calculated values. It is intended to be used in an environment
+ * where JDO metatdata are likely to be changed (e.g. at development
+ * time).
+ * <br> 
+ * There are two exceptions:
+ * <ul>
+ * <li>JDOModelImplDynamic caches JDOClass instances. This means a
+ * second lookup of the same class will return the same JDOClass
+ * instance.
+ * <li>JDOModelImplDynamic manages a list of xml resources (.jdo
+ * files) that are processed already, to avoid reading the same
+ * resource again.
+ * <p>
+ * TBD:
+ * <ul>
+ * <li> Other implementations of JavaModel interface: Development
+ * <li> Check synchronization.
+ * <li> Check non validating XML parsing
+ * <li> Open issue: a .jdo file might contain XML for multiple classes. 
+ * Today all the metadata is stored in the same jdoModel instance, but at runtime
+ * class loading determines the correct jdoModel instance. 
+ * Either we need to be able to change the declaringModel of a JDOClass instance. 
+ * Or reading a .jdo only load metadata for the requested class, so all the other 
+ * metadata is ignored.
+ * </ul>
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOModelImplDynamic extends JDOElementImpl implements JDOModel {
+
+    /** 
+     * Map of JDOPackage managed by this JDOModel instance,
+     * key is the package name.
+     */
+    private Map jdoPackages = new HashMap();
+
+    /** 
+     * Map of JDOClass objects managed by this JDOModel instance, 
+     * key is the fully qualified class name. 
+     */
+    private Map jdoClasses = new HashMap();
+
+    /**
+     * Set of names of XML resources that are processed already 
+     * (see {link #lookupXMLMetadata(String className)}.
+     */
+    private Set processedResources = new HashSet();
+
+    /** The JavaModel used to get type info. */
+    private JavaModel javaModel;
+
+    /** The default for loadXMLMetadata. */ 
+    private final boolean loadXMLMetadataDefault;
+    
+    /** I18N support */
+    protected final static I18NHelper msg =
+        I18NHelper.getInstance(JDOModelImplDynamic.class);
+
+    /** XML Logger */
+    protected static Log xmlLogger = 
+        LogFactory.getFactory().getInstance("org.apache.jdo.impl.model.jdo.xml"); // NOI18N
+
+    /** Logger */
+    protected static Log logger =
+        LogFactory.getFactory().getInstance("org.apache.jdo.impl.model.jdo"); // NOI18N
+
+    /** 
+     * Constructor. 
+     * JDOModel instances are created using the JDOModelFactory only.
+     */
+    protected JDOModelImplDynamic(
+        JavaModel javaModel, boolean loadXMLMetadataDefault) {
+        super();
+        setJavaModel(javaModel);
+        this.loadXMLMetadataDefault = loadXMLMetadataDefault;
+    }
+
+    /** 
+     * The method returns a JDOClass instance for the specified package name.
+     * If this JDOModel contains the corresponding JDOPackage instance,
+     * the existing instance is returned. Otherwise, it creates a new JDOPackage
+     * instance and returns the new instance.
+     * @param packageName the name of the JDOPackage instance 
+     * to be returned
+     * @return a JDOPackage instance for the specified package name
+     * @exception ModelException if impossible
+     */
+    public JDOPackage createJDOPackage(String packageName) 
+        throws ModelException {
+        JDOPackage jdoPackage = getJDOPackage(packageName);
+        if (jdoPackage == null) {
+            jdoPackage = new JDOPackageImpl();
+            jdoPackage.setName(packageName);
+            jdoPackage.setDeclaringModel(this);
+            jdoPackages.put(packageName, jdoPackage);
+        }
+        return jdoPackage;
+    }
+    
+    /** 
+     * The method returns the JDOPackage instance for the specified package 
+     * name, if present. The method returns <code>null</code> if it cannot 
+     * find a JDOPackage instance for the specified name. 
+     * @param packageName the name of the JDOPackage instance 
+     * to be returned
+     * @return a JDOPackage instance for the specified package name 
+     * or <code>null</code> if not present
+     */
+    public JDOPackage getJDOPackage(String packageName) {
+        return (JDOPackage)jdoPackages.get(packageName);
+    }
+
+    /**
+     * Returns the collection of JDOPackage instances declared by this JDOModel 
+     * in the format of an array.
+     * @return the packages declared by this JDOModel
+     */
+    public JDOPackage[] getDeclaredPackages() {
+        return (JDOPackage[])jdoPackages.values().toArray(
+            new JDOPackage[jdoPackages.size()]);
+    }
+
+    /**
+     * The method returns a JDOClass instance for the specified fully qualified
+     * class name. If this JDOModel contains the corresponding JDOClass instance,
+     * the existing instance is returned. Otherwise, it creates a new JDOClass 
+     * instance, sets its declaringModel and returns the new instance.
+     * <p>
+     * Whether this method reads XML metatdata or not is deteremined at
+     * JDOModel creation time (see flag <code>loadXMLMetadataDefault</code> 
+     * in {@link JDOModelFactory#getJDOModel(JavaModel javaModel, boolean
+     * loadXMLMetadataDefault)}). Invoking this method is method is equivalent
+     * to <code>createJDOClass(className, loadXMLMetadataDefault)</code>.
+     * @param className the fully qualified class name of the JDOClass
+     * instance to be returned
+     * @return a JDOClass instance for the specified class name
+     * @exception ModelException if impossible
+     */
+    public JDOClass createJDOClass(String className) throws ModelException {
+        return createJDOClass(className, loadXMLMetadataDefault);
+    }
+
+    /**
+     * The method returns a JDOClass instance for the specified fully qualified
+     * class name. If this JDOModel contains the corresponding JDOClass instance,
+     * the existing instance is returned. Otherwise, if the flag loadXMLMetadata
+     * is set to <code>true</code> the method tries to find the JDOClass 
+     * instance by reading the XML metadata. If it could not be found the method
+     * creates a new JDOClass instance, sets its declaringModel and returns the 
+     * instance.
+     * @param className the fully qualified class name of the JDOClass instance 
+     * to be returned
+     * @param loadXMLMetadata indicated whether to read XML metadata or not
+     * @return a JDOClass instance for the specified class name
+     * @exception ModelException if impossible
+     */
+    public synchronized JDOClass createJDOClass(String className, 
+                                                boolean loadXMLMetadata)
+        throws ModelException {
+        JDOClass jdoClass = getJDOClass(className, loadXMLMetadata);
+        if (jdoClass == null) {
+            if (logger.isDebugEnabled())
+                logger.debug("JDOModel.createJDOClass: " + //NOI18N
+                             "create new JDOClass instance " + className); //NOI18N
+            jdoClass = newJDOClassInstance();
+            jdoClass.setName(className);
+            jdoClass.setDeclaringModel(this);
+            jdoClasses.put(className, jdoClass);
+            // create the corresponding JDOPackage
+            jdoClass.setJDOPackage(createJDOPackage(getPackageName(className)));
+        }
+        return jdoClass;
+    }
+
+    /**
+     * The method returns the JDOClass instance for the specified fully 
+     * qualified class name if present. The method returns <code>null</code> 
+     * if it cannot find a JDOClass instance for the specified name. 
+     * <p>
+     * Whether this method reads XML metatdata or not is deteremined at
+     * JDOModel creation time (see flag <code>loadXMLMetadataDefault</code> 
+     * in {@link JDOModelFactory#getJDOModel(JavaModel javaModel, boolean
+     * loadXMLMetadataDefault)}). Invoking this method is method is equivalent
+     * to <code>createJDOClass(className, loadXMLMetadataDefault)</code>.
+     * @param className the fully qualified class name of the JDOClass
+     * instance to be returned
+     * @return a JDOClass instance for the specified class name 
+     * or <code>null</code> if not present
+     */
+    public JDOClass getJDOClass(String className) {
+        return getJDOClass(className, loadXMLMetadataDefault);
+    }
+    
+    /**
+     * The method returns the JDOClass instance for the specified fully 
+     * qualified class name if present. If the flag loadXMLMetadata is set 
+     * to <code>true</code> the method tries to find the JDOClass instance by 
+     * reading the XML metadata. The method returns null if it cannot find a 
+     * JDOClass instance for the specified name.
+     * @param className the fully qualified class name of the JDOClass instance 
+     * to be returned
+     * @param loadXMLMetadata indicate whether to read XML metatdata or not
+     * @return a JDOClass instance for the specified class name
+     * or <code>null</code> if not present
+     * @exception ModelException if impossible
+     */
+    public synchronized JDOClass getJDOClass(String className, 
+                                             boolean loadXMLMetadata) {
+
+        boolean trace = logger.isTraceEnabled();
+
+        // check whether the class is known to be non PC
+        if (isKnownNonPC(className)) {
+            if (trace)
+                logger.trace("JDOModel.getJDOClass: " + className + //NOI18N
+                             " known to be non-persistence-capable"); //NOI18N
+            return null;
+        }
+
+        JDOClass jdoClass = (JDOClass)jdoClasses.get(className);
+        if (trace)
+            logger.trace("JDOModel.getJDOClass: " + className + //NOI18N
+                         ((jdoClass != null) ? " cached" : " not cached")); //NOI18N
+
+        // check for XML metatdata
+        if (loadXMLMetadata) {
+            if (jdoClass == null)
+                jdoClass = lookupXMLMetadata(className);
+            else if (!jdoClass.isXMLMetadataLoaded())
+                jdoClass = lookupXMLMetadata(jdoClass);
+
+            if (jdoClass == null) {
+                // we loaded XML metadata, but there is no metadata
+                // for this class => known to be non persistence-capable
+                knownNonPC(className);
+            }
+        }
+
+        return jdoClass;
+    }
+
+    /**
+     * Returns the collection of JDOClass instances declared by this JDOModel 
+     * in the format of an array.
+     * @return the classes declared by this JDOModel
+     */
+    public synchronized JDOClass[] getDeclaredClasses()  {
+        return (JDOClass[])jdoClasses.values().toArray(
+            new JDOClass[jdoClasses.size()]);
+    }
+
+    /**
+     * Returns the JavaModel bound to this JDOModel instance.
+     * @return the JavaModel
+     */
+    public JavaModel getJavaModel() {
+        return javaModel;
+    }
+    
+    /**
+     * Sets the JavaModel for this JDOModel instance.
+     * @param javaModel the JavaModel
+     */
+    public void setJavaModel(JavaModel javaModel) {
+        this.javaModel = javaModel;
+    }
+    
+    /**
+     * Returns the parent JDOModel instance of this JDOModel.
+     * @return the parent JDOModel
+     */
+    public JDOModel getParent() {
+        if (javaModel != null) {
+            JavaModel parentJavaModel = javaModel.getParent();
+            if (parentJavaModel != null)
+                return parentJavaModel.getJDOModel();
+        }
+        return null; 
+    }
+
+    /**
+     * This method returns the JDOClass instance that defines the specified type
+     * as its objectId class. In the case of an inheritance hierarchy it returns 
+     * the top most persistence-capable class of the hierarchy (see 
+     * {@link JDOClass#getPersistenceCapableSuperclass}).
+     * @param objectIdClass the type representation of the ObjectId class
+     * @return the JDOClass defining the specified class as ObjectId class
+     */
+    public JDOClass getJDOClassForObjectIdClass(JavaType objectIdClass) {
+        // Note, method getJDOClassForObjectIdClass is not synchronized to
+        // avoid a deadlock with PC class registration.
+        if (logger.isTraceEnabled())
+            logger.trace("JDOModel.getJDOClassForObjectIdClass: " + //NOI18N
+                         "check objectIdClass " +objectIdClass); //NOI18N
+                        
+        if (objectIdClass == null)
+            return null;
+
+        JDOClass jdoClass = null;
+        String objectIdClassName = objectIdClass.getName();
+        // check all JDOClasses for this JDOModel instance
+        List classesToActivate = new ArrayList();
+        while (true) {
+            try {
+                for (Iterator i = jdoClasses.values().iterator(); i.hasNext();) {
+                    JDOClass next = (JDOClass)i.next();
+                    if (next.isXMLMetadataLoaded()) {
+                        // XML metadata is loaded => check the objectIdClass
+                        if (objectIdClassName.equals(
+                                next.getDeclaredObjectIdClassName())) {
+                            // found => return
+                            return next;
+                        }
+                    }
+                    else {
+                        // XML metadata is NOT loaded => 
+                        // store the class for later processing.
+                        // Do not load the XML metadata here. This might create
+                        // new JDOClass instances in this model for other pc
+                        // classes listed in the same .jdo file. This would
+                        // change the jdoClasses map while its values are
+                        // iterated => ConcurrentModificationException
+                        classesToActivate.add(next);
+                    }
+                }
+                // No ConcurrentModificationException => break the loop 
+                break;
+            }
+            catch (ConcurrentModificationException ex) {
+                // ConcurrentModificationException means a JDOClass was
+                // added to the JDOModel in parallel => 
+                // start the loop again.
+            }
+        }
+                
+        // None of the activated JDOClasses knows the objectIdClass =>
+        // activate the classes that were registered but not activated 
+        // and check these classes
+        for (Iterator i = classesToActivate.iterator(); i.hasNext();) {
+            JDOClass next = (JDOClass)i.next();
+            lookupXMLMetadata(next);
+
+            if (objectIdClass.equals(next.getDeclaredObjectIdClassName())) {
+                // found => return
+                return next;
+            }
+        }
+
+        // objectIdClass not found in this model => return null
+        return null;
+    }
+
+    //========= Internal helper methods ==========
+    
+    /** Returns a new instance of the JDOClass implementation class. */
+    protected JDOClass newJDOClassInstance() {
+        return new JDOClassImplDynamic();
+    }
+
+    /**
+     * Checks whether the type with the specified name does NOT denote a
+     * persistence-capable class.
+     * @param typeName name of the type to be checked
+     * @return <code>true</code> if types is a name of a primitive type; 
+     * <code>false</code> otherwise
+     */
+    protected boolean isKnownNonPC(String typeName) {
+        // Any class from packages java and javax are supposed to be non-pc.
+        return typeName.startsWith("java.") || //NOI18N
+               typeName.startsWith("javax."); //NOI18N
+    }
+
+    /** 
+     * Hook called when a class is known to be non persistence
+     * capable. Subclasses might want to keep track of classes marked
+     * as non pc classes and use this in the implementation of
+     * {link #isKnownNonPC(String typeName)}.
+     * @param className the name of the non-pc class
+     */
+    protected void knownNonPC(String className) {
+    }
+
+    /**
+     * The method seaches JDO metadata for the class with the specified
+     * class name. Chapter 18 of the JDO specification defines the search
+     * order. The method skips resources that have been tried to load
+     * before, no matter whether the resource currently exist. 
+     * The method returns the populated JDOClass instance, if there is XML
+     * metadata available for the specified class name. Otherwise it
+     * returns <code>null</code>. 
+     * <p>
+     * The purpose of this method is to populate an existing JDOClass
+     * instance with the JDO metadata. It throws an exception if there is
+     * no jdo file for this class. The specified jdoClass must not be
+     * <code>null</code>; otherwise a NullPointerException is thrown.
+     * @param jdoClass the non-activated JDOClass instance.
+     * @return the JDOClass instance for the specified class name or
+     * <code>null</code> if there is no XML metadata.
+     * @exception ModelFatalException indicates a problem while parsing the
+     * XML file or a missing XML file.
+     * @exception NullPointerException the specified jdoClass is
+     * <code>null</code>.
+     */
+    private JDOClass lookupXMLMetadata(JDOClass jdoClass)
+        throws ModelFatalException, NullPointerException {
+        String className = jdoClass.getName();
+        JDOClass activated = lookupXMLMetadata(className);
+        if (activated == null) {
+            throw new ModelFatalException(msg.msg(
+                "EXC_MissingJDOMetadata", className)); //NOI18N
+        }
+        else if (activated != jdoClass) {
+            throw new ModelFatalException(msg.msg(
+                "ERR_MultipleJDOClassInstances", className)); //NOI18N
+        }
+        return jdoClass;
+    }
+
+    /**
+     * The method seaches JDO metadata for the class with the specified
+     * class name. Chapter 18 of the JDO specification defines the search
+     * order. The method skips resources that have been tried to load
+     * before, no matter whether the resource currently exist. 
+     * The method returns the populated JDOClass instance, if there is XML
+     * metadata available for the specified class name. Otherwise it
+     * returns <code>null</code>. 
+     * @param className the name of the class to check for XML metadata.
+     * @return the JDOClass instance for the specified class name or
+     * <code>null</code> if there is no XML metadata.
+     */
+    private JDOClass lookupXMLMetadata(String className) {
+        boolean debug = xmlLogger.isDebugEnabled();
+        JDOClass jdoClass = null;
+        
+        if (debug)
+            xmlLogger.debug("JDOModel.lookupXMLMetadata:" + // NOI18N
+                            " lookup XML for class " + className); // NOI18N
+        // Iterate possible resources to find JDO metadata for className
+        Iterator i = new MetadataResourceNameIterator(className);
+        while((jdoClass == null) && i.hasNext()) {
+            String resource = (String)i.next();
+            if (processedResources.contains(resource)) {
+                if (debug)
+                    xmlLogger.debug("  XML " + resource + //NOI18N
+                                    " processed already"); //NOI18N
+                // processed already => skip
+                continue;
+            }
+            else {
+                // add resource to the list of processed resources
+                // Note, this adds the resource no matter whether the
+                // resource existst or not. This implies this JDOModel 
+                // instance will not check this resource again, 
+                // even if it exists, again.
+                processedResources.add(resource);
+                // load resource
+                jdoClass = loadXMLResource(resource, className);
+            }
+        }
+        if (debug)
+            xmlLogger.debug("JDOModel.lookupXMLMetadata: " +  //NOI18N
+                            ((jdoClass!=null)?"found":"no") + //NOI18N
+                            " JDO metadata for class " + className); //NOI18N
+        return jdoClass;
+    }
+
+    /**
+     * Load the specified resource assuming it contains JDO metadata for
+     * one or more persistence capable classes. 
+     * The method returns the populated JDOClass instance, if the specified
+     * resource has XML metadata for the specified class name. Otherwise it
+     * returns <code>null</code>. 
+     * @param resource resource to load
+     * @param className the name of the class to check for XML metadata.
+     * @return the JDOClass instance for the specified class name or
+     * <code>null</code> if the specified resource has no XML metadata.
+     */
+    private JDOClass loadXMLResource(String resource, String className) {
+        boolean debug = xmlLogger.isDebugEnabled();
+        JDOClass jdoClass = null;
+        InputStream stream = javaModel.getInputStreamForResource(resource);
+        if (stream == null) {
+            if (debug)
+                xmlLogger.debug("  XML " + resource + " not available"); //NOI18N
+        }
+        else {
+            // resource exists => parse it
+            // Store all pc classes specified in this resource in this
+            // JDOModel instance => pass this to the handler
+            JDOHandler handler = new JDOHandlerImpl(this);
+            JDOParser parser = new JDOParser(handler);
+            try {
+                if (debug)
+                    xmlLogger.debug("  XML " + resource +  //NOI18N
+                                    " found, start parsing ..."); //NOI18N
+                parser.parse(new InputSource(new InputStreamReader(stream)));
+            }
+            catch (SAXException ex) {
+                throw new ModelFatalException(
+                    msg.msg("EXC_XMLError", resource), ex); //NOI18N
+            }
+            catch (ParserConfigurationException ex) {
+                throw new ModelFatalException(
+                    msg.msg("EXC_XMLError", resource), ex); //NOI18N
+            }
+            catch (IOException ex) {
+                throw new ModelFatalException(
+                    msg.msg("EXC_XMLError", resource), ex); //NOI18N
+            }
+            finally {
+                try { stream.close(); }
+                catch (IOException ex) { 
+                    // ignore close exception, stream will be nullified anyway 
+                }
+            }
+            stream = null;
+            
+            // post process loaded JDOClasses
+            Collection newJDOClasses = handler.handledJDOClasses();
+            if (debug)
+                xmlLogger.debug("  XML " + resource + //NOI18N
+                                " has JDO metadata for class(es) " + //NOI18N
+                                newJDOClasses);
+            for (Iterator i = newJDOClasses.iterator(); i.hasNext();) {
+                JDOClass next = (JDOClass)i.next();
+                if (className.equals(next.getName())) {
+                    jdoClass = next;
+                }
+                checkSuperclass(next);
+            }
+            if (jdoClass == null)
+                if (debug)
+                    xmlLogger.debug("  XML " + resource + //NOI18N
+                                    " does not have JDO metadata for class " + //NOI18N
+                                    className); 
+        }
+        return jdoClass;
+    }
+
+    /**
+     * Updates the pcSuperclass property of the specified JDOClass and all its 
+     * superclasses. 
+     * @param jdoClass the class to be checked
+     */
+    private void checkSuperclass(JDOClass jdoClass) {
+        if (jdoClass != null) {
+            JDOClass superclass = jdoClass.getPersistenceCapableSuperclass();
+            checkSuperclass(superclass);
+        }
+    }
+
+    /** Returns the package name of a class name */
+    private String getPackageName(String className) {
+        int index = className.lastIndexOf('.');
+        return (index == -1) ? "" : className.substring(0, index); //NOI18N
+    }
+    
+    /**
+     * This Iterator implementation iterates resource names of possible JDO
+     * metadata files for the specified class name. Chapter 18 of the JDO
+     * specification defines the search order as follows: 
+     * META-INF/package.jdo, WEB-INF/package.jdo, package.jdo, 
+     * <package>/.../<package>/package.jdo, and <package>/<class>.jdo.
+     */
+    private static class MetadataResourceNameIterator 
+        implements Iterator {
+        /** Suffix of a JDO metadata file. */
+        private static final String JDO_SUFFIX = ".jdo"; //NOI18N
+
+        /** The name of a package JDO metadata file. */
+        private static final String PACKAGE_JDO = "package" + JDO_SUFFIX; //NOI18N
+
+        /** List of constant package JDO metadata file names. */
+        private static final String[] constantResources = { 
+            "META-INF/" + PACKAGE_JDO, //NOI18N
+            "WEB-INF/" + PACKAGE_JDO,  //NOI18N
+            PACKAGE_JDO 
+        };
+
+        /** Indicates whether this iterator has more elements. */
+        private boolean hasNext = true;
+
+        /** The class name as resource name. */
+        private final String prefix;
+
+        /** Current index in the list of constant package JDO metadata file names. */
+        private int constantResourcesIndex = 0;
+
+        /** Current index in the prefix. */
+        private int fromIndex = 0;
+
+        /** Constructor. */
+        public MetadataResourceNameIterator(String className) {
+            this.prefix = className.replace('.', '/');
+        }
+        
+        /**
+         * Returns <code>true</code> if the iteration has more elements.
+         * @return <code>true</code> if the iterator has more elements.
+         */
+        public boolean hasNext() {
+            return hasNext;
+        }
+        
+        /**
+         * Returns the next resource name.
+         * @return the next resource name.
+         * @exception NoSuchElementException iteration has no more elements. 
+         */
+        public Object next() {
+            String resource = null;
+            if (!hasNext) {
+                throw new NoSuchElementException();
+            }
+            else if (constantResourcesIndex < constantResources.length) {
+                // Use a constant resource name, if there is one left in
+                // the iteration.
+                resource = constantResources[constantResourcesIndex];
+                constantResourcesIndex++;
+            }
+            else {
+                // No constant resource name left
+                // build resource names from the package of the class name
+                // Check for the next package, fromIndex is the index of
+                // the '/' used in the previous iteration.
+                int index = prefix.indexOf('/', fromIndex);
+                if (index != -1) {
+                    // string needs to include '/' => use index+1
+                    resource = prefix.substring(0, index + 1) + PACKAGE_JDO;
+                    fromIndex = index + 1;
+                }
+                else {
+                    // no more package jdo files left => use class .jdo file 
+                    resource = prefix + JDO_SUFFIX;
+                    // the class jdo file is the last resource to be checked 
+                    hasNext = false;
+                }
+            }
+            return resource;
+        }
+
+        /**
+         * This Iterator does not implement this method.
+         * @exception UnsupportedOperationException if the
+         * <code>remove</code> operation is not supported by this
+         * Iterator. 
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+        
+    }
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOPackageImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOPackageImpl.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOPackageImpl.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOPackageImpl.java Sun May 22 10:44:19 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import java.util.*;
+
+import org.apache.jdo.model.jdo.JDOModel;
+import org.apache.jdo.model.jdo.JDOPackage;
+
+/**
+ * A JDOPackage instance represents the JDO package metadata.
+ *
+ * @author Michael Bouschen
+ */
+public class JDOPackageImpl 
+    extends JDOElementImpl
+    implements JDOPackage
+{
+    /** The package name. */
+    private String name;
+
+    /** Relationship JDOModel<->JDOPackage. Initialized during creation.*/
+    private JDOModel declaringModel;
+
+    /**
+     * Returns the name of this JDOPackage.
+     * @return the name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Sets the name of this JDOPackage.
+     * @param name the name
+     */
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * Returns the declaring JDOModel of this JDOPackage.
+     * @return the JDOModel that owns this JDOPackage.
+     */
+    public JDOModel getDeclaringModel()
+    {
+        return declaringModel;
+    }
+
+    /**
+     * Set the declaring JDOModel for this JDOPackage.
+     * @param model the declaring JDOModel of this JDOPackage.
+     */
+    public void setDeclaringModel(JDOModel model)
+    {
+        this.declaringModel = model;
+    }
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOReferenceImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOReferenceImpl.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOReferenceImpl.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDOReferenceImpl.java Sun May 22 10:44:19 2005
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import org.apache.jdo.model.jdo.JDOReference;
+
+/**
+ * An instance of this class represents the JDO relationship metadata 
+ * of a reference relationship field.
+ *
+ * @author Michael Bouschen
+ */
+public class JDOReferenceImpl extends JDORelationshipImpl 
+    implements JDOReference
+{
+    // empty implementation
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDORelationshipImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDORelationshipImpl.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDORelationshipImpl.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/JDORelationshipImpl.java Sun May 22 10:44:19 2005
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo;
+
+import org.apache.jdo.model.jdo.JDOField;
+import org.apache.jdo.model.jdo.JDORelationship;
+
+/**
+ * JDORelationship is the super interface for all interfaces representing 
+ * JDO relationship metadata of a managed field of a persistence capable class.
+ * 
+ * @author Michael Bouschen
+ */
+public abstract class JDORelationshipImpl extends JDOElementImpl
+    implements JDORelationship {
+    
+    /** Property lowerBound. No default. */
+    private int lowerBound;
+
+    /** Property upperBound. No default. */
+    private int upperBound;
+
+    /** Relationship JDOField<->JDORelationship. */
+    private JDOField declaringField;
+
+    /** Relationship JDORelationship<->JDORelationship. */
+    private JDORelationship inverse;
+
+    /** 
+     * Get the lower cardinality bound for this relationship element.
+     * @return the lower cardinality bound
+     */
+    public int getLowerBound() {
+        return lowerBound;
+    }
+
+    /** 
+     * Set the lower cardinality bound for this relationship element.
+     * @param lowerBound an integer indicating the lower cardinality bound
+     */
+    public void setLowerBound(int lowerBound) {
+        this.lowerBound = lowerBound;
+    }
+    
+    /** 
+     * Get the upper cardinality bound for this relationship element.
+     * @return the upper cardinality bound
+     */
+    public int getUpperBound() {
+        return upperBound;
+    }
+
+    /** 
+     * Set the upper cardinality bound for this relationship element.
+     * @param upperBound an integer indicating the upper cardinality bound
+     */
+    public void setUpperBound(int upperBound)
+    {
+        this.upperBound = upperBound;
+    }
+
+    /** 
+     * Get the declaring field of this JDORelationship.
+     * @return the field that owns this JDORelationship, or <code>null</code>
+     * if the element is not attached to any field
+     */
+    public JDOField getDeclaringField() {
+        return declaringField;
+    }
+
+    /** 
+     * Set the declaring field of this JDORelationship.
+     * @param declaringField the declaring field of this relationship element
+     */
+    public void setDeclaringField(JDOField declaringField) {
+        this.declaringField = declaringField;
+    }
+    
+    /**
+     * Get the inverse JDORelationship in the case of a managed relationship.
+     * @return the inverse relationship
+     */
+    public JDORelationship getInverseRelationship() {
+        return inverse;
+    }
+
+    /**
+     * Set the inverse JDORelationship in the case of a managed relationship.
+     * @param inverseRelationship the inverse relationship
+     */
+    public void setInverseRelationship(JDORelationship inverseRelationship) {
+        this.inverse = inverseRelationship;
+    }
+
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOArrayImplCaching.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOArrayImplCaching.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOArrayImplCaching.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOArrayImplCaching.java Sun May 22 10:44:19 2005
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo.caching;
+
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.impl.model.jdo.JDOArrayImplDynamic;
+
+/**
+ * An instance of this class represents the JDO relationship metadata 
+ * of a array relationship field. This caching implementation
+ * caches any calulated value to avoid re-calculating it if it is
+ * requested again. 
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOArrayImplCaching extends JDOArrayImplDynamic {
+    
+    /** Type of the array element. */
+    private transient JavaType elementType;
+    
+    /**
+     * Determines whether the values of the elements should be stored 
+     * if possible as part of the instance instead of as their own instances 
+     * in the datastore.
+     * @return <code>true</code> if the elements should be stored as part of 
+     * the instance; <code>false</code> otherwise
+     */
+    public boolean isEmbeddedElement() {
+        if (embeddedElement == null) {
+            embeddedElement = 
+                super.isEmbeddedElement() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return embeddedElement.booleanValue();
+    }
+    
+    /** 
+     * Get the type representation of the array component type. 
+     * @return the array component type
+     */
+    public JavaType getElementType() {
+        if (elementType == null) {
+            elementType = super.getElementType();
+        }
+        return elementType;
+    }
+
+}
+

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOClassImplCaching.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOClassImplCaching.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOClassImplCaching.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOClassImplCaching.java Sun May 22 10:44:19 2005
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo.caching;
+
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.model.ModelException;
+import org.apache.jdo.model.jdo.JDOClass;
+import org.apache.jdo.model.jdo.JDOField;
+import org.apache.jdo.model.jdo.JDOIdentityType;
+import org.apache.jdo.model.jdo.JDOMember;
+
+import org.apache.jdo.impl.model.jdo.JDOClassImplDynamic;
+
+/**
+ * An instance of this class represents the JDO metadata of a persistence 
+ * capable class. This caching implementation caches any calulated
+ * value to avoid re-calculating it if it is requested again.
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOClassImplCaching extends JDOClassImplDynamic
+{
+
+    /** Flag indicating whether the objectIdClass is resolved already. */
+    private boolean objectIdClassResolved = false;
+
+    /** Flag indicating whether the pcSuperclass is resolved already. */
+    private boolean pcSuperclassResolved = false;
+
+    /** Array of declared managed fields, sorted by name (see JDO spec).  */
+    private JDOField[] declaredManagedFields;
+
+    /** 
+     * Array of managed fields, incluing inherited fields. The fields are 
+     * sorted by name (see JDO Spec) per class in the inheritance hierarchy.
+     */
+    private JDOField[] managedFields;
+
+    /** 
+     * Array of persistent fields, incluing inherited fields. The fields are 
+     * sorted by name (see JDO Spec) per class in the inheritance hierarchy.
+     */
+    private JDOField[] persistentFields;
+
+    /** Primary key fields. */
+    private JDOField[] primaryKeyFields;
+
+    /** Persistent relationship fields. */
+    private JDOField[] persistentRelationshipFields;
+    
+    /** Default fetch group fields. */
+    private JDOField[] defaultFetchGroupFields;
+    
+    /** Number of inherited fields. */
+    private int inheritedManagedFieldCount = -1;
+    
+    /** Field numbers of managed fields. */
+    private int[] managedFieldNumbers;
+
+    /** Field numbers of PERSISTENT fields. */
+    private int[] persistentFieldNumbers;
+
+    /** Field numbers of primaryKey fields. */
+    private int[] primaryKeyFieldNumbers;
+
+    /** Field numbers of managed non primaryKey fields. */
+    private int[] nonPrimaryKeyFieldNumbers;
+
+    /** Field numbers of persistent non primaryKey fields. */
+    private int[] persistentNonPrimaryKeyFieldNumbers;
+
+    /** Field numbers of persistent relationship fields. */
+    private int[] persistentRelationshipFieldNumbers;
+
+    /** Field numbers of persistent, serializable fields. */
+    private int[] persistentSerializableFieldNumbers;
+
+    /** Flag indicating wthere field numbers are calculated already. */
+    private boolean fieldNumbersCalculated = false;
+
+    /** 
+     * Get the JDO identity type of this JDOClass.
+     * The identity type of the least-derived persistence-capable class defines
+     * the identity type for all persistence-capable classes that extend it.
+     * The identity type of the least-derived persistence-capable class is
+     * defaulted to {@link JDOIdentityType#APPLICATION} if objectid-class is 
+     * specified, and {@link JDOIdentityType#DATASTORE}, if not. 
+     * @return the JDO identity type, one of 
+     * {@link JDOIdentityType#APPLICATION}, 
+     * {@link JDOIdentityType#DATASTORE}, or 
+     * {@link JDOIdentityType#NONDURABLE}
+     */
+    public int getIdentityType() {
+        if (identityType == JDOIdentityType.UNSPECIFIED) {
+            identityType = super.getIdentityType();
+        }
+        return identityType;
+    }
+
+    /** 
+     * Get the JavaType representation of the object identity class 
+     * (primary key class) for this JDOClass. 
+     * @return the JavaType representation of the object identity class.
+     */
+    public JavaType getObjectIdClass() {
+        if (!objectIdClassResolved) {
+            objectIdClassResolved = true;
+            objectIdClass = super.getObjectIdClass();
+        }
+        return objectIdClass;
+    }
+
+    /**
+     * Returns the JDOClass instance for the persistence-capable superclass 
+     * of this JDOClass. If this class does not have a persistence-capable 
+     * superclass then <code>null</code> is returned.
+     * @return the JDClass instance of the persistence-capable superclass
+     * or <code>null</code> if there is no persistence-capable superclass 
+     */
+    public JDOClass getPersistenceCapableSuperclass() {
+        if(!pcSuperclassResolved) {
+            pcSuperclass = super.getPersistenceCapableSuperclass();
+        }
+        return pcSuperclass;
+    }
+
+    /**
+     * Provides the JavaType representaion corresponding to this JDOClass.
+     * <p>
+     * Note the difference between Object.getClass() and this method. The
+     * former returns the class of the object in hand, this returns the class
+     * of the object represented by this meta data.
+     * @return the JavaType object corresponding to this JDOClass.
+     */
+    public JavaType getJavaType() {
+        if (javaType == null) {
+            javaType = super.getJavaType();
+        }
+        return javaType;
+    }
+
+    /** 
+     * Remove the supplied member from the collection of members maintained by
+     * this JDOClass.
+     * @param member the member to be removed
+     * @exception ModelException if impossible
+     */
+    public void removeDeclaredMember(JDOMember member) throws ModelException {
+        if ((member instanceof JDOField) && fieldNumbersCalculated) {
+            throw new ModelException(
+                msg.msg("EXC_CannotRemoveJDOField")); //NOI18N
+        }
+        super.removeDeclaredMember(member);
+    }
+
+    /**
+     * This method returns a JDOField instance for the field with the specified 
+     * name. If this JDOClass already declares such a field, the existing 
+     * JDOField instance is returned. Otherwise, it creates a new JDOField 
+     * instance, sets its declaringClass and returns the new instance.
+     * <P> 
+     * Note, if the field numbers for the managed fields of this JDOClass are 
+     * calculated, this methid will fail to create a new JDOField. Any new field
+     * would possibly invalidate existing field number 
+     * @param name the name of the field
+     * @exception ModelException if impossible
+     */
+    public JDOField createJDOField(String name) throws ModelException {
+        if ((getDeclaredField(name) == null) && fieldNumbersCalculated) {
+            throw new ModelException(
+                msg.msg("EXC_CannotCreateJDOField")); //NOI18N
+        }
+        return super.createJDOField(name);
+    }
+
+    /**
+     * Returns the collection of managed JDOField instances declared by this
+     * JDOClass in the form of an array. The returned array does not include 
+     * inherited fields. A field is a managed field, if it has the 
+     * persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. 
+     * The position of the fields in the returned array equals their
+     * relative field number as returned by 
+     * {@link JDOField#getRelativeFieldNumber()}. The following holds
+     * true for any field in the returned array: 
+     * <ul>
+     * <li> <code>getDeclaredManagedFields()[i].getRelativeFieldNumber() 
+     * == i</code>
+     * <li> <code>getDeclaredManagedFields()[field.getRelativeFieldNumber()] 
+     * == field</code>
+     * </ul> 
+     * @return the managed fields declared by this JDOClass
+     */
+    public JDOField[] getDeclaredManagedFields() {
+        if (declaredManagedFields == null) {
+            declaredManagedFields = super.getDeclaredManagedFields();
+        }
+        return declaredManagedFields;
+    }
+            
+    /**
+     * Returns the collection of managed JDOField instances of this JDOClass 
+     * in the form of an array. The returned array includes inherited fields.
+     * A field is a managed field, if it has the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. 
+     * The position of the fields in the returned array equals their
+     * absolute field number as returned by 
+     * {@link JDOField#getFieldNumber()}. The following holds true for
+     * any field in the returned array: 
+     * <ul>
+     * <li> <code>getManagedFields()[i].getFieldNumber() == i</code>
+     * <li> <code>getManagedFields()[field.getFieldNumber()] == field</code>
+     * </ul> 
+     * @return the managed fields of this JDOClass
+     */
+    public JDOField[] getManagedFields() {
+        if (managedFields == null) {
+            managedFields = super.getManagedFields();
+        }
+        return managedFields;
+    }
+    
+    /**
+     * Returns the collection of persistent JDOField instances of this JDOClass 
+     * in the form of an array. The returned array includes inherited fields.
+     * A field is a persistent field, if it has the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
+     * Please note, the position of the fields in the returned array might not 
+     * equal their absolute field number as returned by 
+     * {@link JDOField#getFieldNumber()}.
+     * @return the persistent fields of this JDOClass
+     */
+    public JDOField[] getPersistentFields() {
+        if (persistentFields == null) {
+            persistentFields = super.getPersistentFields();
+        }
+        return persistentFields;
+    }
+
+    /**
+     * Returns the collection of identifying fields of this JDOClass in the form
+     * of an array. The method returns the JDOField instances defined as 
+     * primary key fields (see {@link JDOField#isPrimaryKey}).
+     * @return the identifying fields of this JDOClass
+     */
+    public JDOField[] getPrimaryKeyFields() {
+        if (primaryKeyFields == null) {
+            primaryKeyFields = super.getPrimaryKeyFields();
+        }
+        return primaryKeyFields;
+    }
+
+    /**
+     * Returns the collection of persistent relationship fields of this JDOClass
+     * in the form of an array. The method returns the JDOField instances 
+     * defined as relationship (method {@link JDOField#getRelationship} returns
+     * a non null value) and having the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
+     * @return the persistent relationship fields of this JDOClass
+     */
+    public JDOField[] getPersistentRelationshipFields() {
+        if (persistentRelationshipFields == null) {
+            persistentRelationshipFields = 
+                super.getPersistentRelationshipFields();
+        }
+        return persistentRelationshipFields;
+    }
+
+    /**
+     * Returns the collection of default fetch group fields of this JDOClass
+     * in the form of an array. The method returns the JDOField instances 
+     * defined as part of the default fetch group 
+     * (method {@link JDOField#isDefaultFetchGroup} returns <code>true</code>.
+     * @return the default fetch group fields of this JDOClass
+     * @since 1.1
+     */
+    public JDOField[] getDefaultFetchGroupFields() {
+        if (defaultFetchGroupFields == null) {
+            defaultFetchGroupFields = super.getDefaultFetchGroupFields();
+        }
+        return defaultFetchGroupFields;
+    }
+
+    /**
+     * Returns an array of absolute field numbers of the managed fields of this
+     * JDOClass. The returned array includes field numbers of inherited fields.
+     * A field is a managed field, if it has the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. 
+     * Only managed fields have a valid field number, thus the field number in 
+     * the returned array equals its index:
+     * <br>
+     *  <code>getManagedFields()[i] == i</code>
+     */
+    public int[] getManagedFieldNumbers() {
+        if (managedFieldNumbers == null) {
+            managedFieldNumbers = super.getManagedFieldNumbers();
+        }
+        return managedFieldNumbers;
+    }
+
+    /**
+     * Returns an array of absolute field numbers of the persistent fields of 
+     * this JDOClass. The returned array includes field numbers of inherited 
+     * fields. A persistent field has the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
+     */
+    public int[] getPersistentFieldNumbers()
+    {
+        if (persistentFieldNumbers == null) {
+            persistentFieldNumbers = super.getPersistentFieldNumbers();
+        }
+        return persistentFieldNumbers;
+    }
+    
+    /**
+     * Returns an array of absolute field numbers of the identifying fields 
+     * of this JDOClass. A field number is included in the returned array, 
+     * iff the corresponding JDOField instance is defined as primary  key field
+     * (see {@link JDOField#isPrimaryKey}).
+     * @return array of numbers of the identifying fields
+     */
+    public int[] getPrimaryKeyFieldNumbers() {
+        if (primaryKeyFieldNumbers == null) {
+            primaryKeyFieldNumbers = super.getPrimaryKeyFieldNumbers();
+        }
+        return primaryKeyFieldNumbers;
+    }
+
+    /**
+     * Returns an array of absolute field numbers of the non identifying, 
+     * persistent fields of this JDOClass. A field number is included in the 
+     * returned array, iff the corresponding JDOField instance is persistent and 
+     * not a not a primary key field (see {@link JDOField#isPrimaryKey}).
+     * A field is a persistent field, if it has the persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or 
+     * (see {@link JDOField#getPersistenceModifier}). 
+     * @return array of numbers of the non identifying, persistent fields
+     */
+    public int[] getPersistentNonPrimaryKeyFieldNumbers() {
+        if (persistentNonPrimaryKeyFieldNumbers == null) {
+            persistentNonPrimaryKeyFieldNumbers = 
+                super.getPersistentNonPrimaryKeyFieldNumbers();
+        }
+        return persistentNonPrimaryKeyFieldNumbers;
+    }
+    
+    /**
+     * Returns an array of absolute field numbers of persistent relationship 
+     * fields of this JDOClass. A field number is included in the returned 
+     * array, iff the corresponding JDOField instance is a relationship (method 
+     * {@link JDOField#getRelationship} returns a non null value) and has the 
+     * persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
+     * @return the field numbers of the persistent relationship fields
+     */
+    public int[] getPersistentRelationshipFieldNumbers() {
+        if (persistentRelationshipFieldNumbers == null) {
+            persistentRelationshipFieldNumbers = 
+                super.getPersistentRelationshipFieldNumbers();
+        }
+        return persistentRelationshipFieldNumbers;
+    }
+
+    /**
+     * Returns an array of absolute field numbers of persistent, serializable 
+     * fields of this JDOClass. A field number is included in the returned 
+     * array, iff the corresponding JDOField instance is serializable (method 
+     * {@link JDOField#isSerializable} returns <code>true</code>) and has the 
+     * persistence-modifier 
+     * {@link org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}.
+     * @return the field numbers of serializable fields
+     */
+    public int[] getPersistentSerializableFieldNumbers() {
+        if (persistentSerializableFieldNumbers == null) {
+            persistentSerializableFieldNumbers = 
+                super.getPersistentSerializableFieldNumbers();
+        }
+        return persistentSerializableFieldNumbers;
+    }
+
+    /**
+     * Returns the number of inherited managed fields for this class.  
+     * @return number of inherited fields
+     */
+    public synchronized int getInheritedManagedFieldCount() {
+        // inheritedManagedFieldCount < 0 indicates check is not done yet.
+        if (inheritedManagedFieldCount < 0) {
+            inheritedManagedFieldCount = super.getInheritedManagedFieldCount();
+        }
+        return inheritedManagedFieldCount;
+    }    
+
+    //========= Internal helper methods ==========
+
+    /**
+     * This method calculates the relative field number of the
+     * declared managed fields of this JDOClass and uddates the
+     * relativeFieldNumber property of the JDOField instance.
+     */
+    protected void calculateFieldNumbers() {
+        if (!fieldNumbersCalculated) {
+            fieldNumbersCalculated = true;
+            JDOField[] fields = getDeclaredManagedFields();
+            // now set the relativeFieldNumber of the JDOField
+            for (int i = 0; i < fields.length; i++) {
+                ((JDOFieldImplCaching)fields[i]).setRelativeFieldNumber(i);
+            }
+        }
+    }
+
+    /**
+     * Returns a new instance of the JDOClass implementation class.
+     */
+    protected JDOClass newJDOClassInstance() {
+        return new JDOClassImplCaching();
+    }
+
+    /**
+     * Returns a new instance of the JDOField implementation class.
+     */
+    protected JDOField newJDOFieldInstance() {
+        return new JDOFieldImplCaching();
+    }
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOCollectionImplCaching.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOCollectionImplCaching.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOCollectionImplCaching.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOCollectionImplCaching.java Sun May 22 10:44:19 2005
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo.caching;
+
+import org.apache.jdo.impl.model.jdo.JDOCollectionImplDynamic;
+import org.apache.jdo.model.java.JavaType;
+
+/**
+ * An instance of this class represents the JDO relationship metadata 
+ * of a collection relationship field. This caching implementation
+ * caches any calulated value to avoid re-calculating it if it is
+ * requested again. 
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOCollectionImplCaching extends JDOCollectionImplDynamic {
+    
+    /**
+     * Determines whether the values of the elements should be stored if 
+     * possible as part of the instance instead of as their own instances 
+     * in the datastore.
+     * @return <code>true</code> if the elements should be stored as part of 
+     * the instance; <code>false</code> otherwise
+     */
+    public boolean isEmbeddedElement() {
+        if (embeddedElement == null) {
+            embeddedElement = 
+                super.isEmbeddedElement() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return (embeddedElement == null) ? false : 
+            embeddedElement.booleanValue();
+    }
+    
+    /** 
+     * Get the type representation of the collection elements. 
+     * @return the element type
+     */
+    public JavaType getElementType()
+    {
+        if (elementType == null) {
+            elementType = super.getElementType();
+        }
+        return elementType;
+    }
+
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOFieldImplCaching.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOFieldImplCaching.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOFieldImplCaching.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOFieldImplCaching.java Sun May 22 10:44:19 2005
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo.caching;
+
+import org.apache.jdo.model.ModelException;
+import org.apache.jdo.model.jdo.JDOArray;
+import org.apache.jdo.model.jdo.JDOCollection;
+import org.apache.jdo.model.jdo.JDOMap;
+import org.apache.jdo.model.jdo.JDOReference;
+import org.apache.jdo.model.jdo.JDORelationship;
+import org.apache.jdo.model.jdo.PersistenceModifier;
+import org.apache.jdo.impl.model.jdo.JDOFieldImplDynamic;
+
+/**
+ * An instance of this class represents the JDO metadata of a managed
+ * field of a persistence capable class. This caching implementation
+ * caches any calulated value to avoid re-calculating it if it is
+ * requested again. 
+ * <p>
+ * Please note, this implementation does not support
+ * changing the relationship property once it is defined (either
+ * explicitly by the setter or internally calculated by the
+ * getter). The second attempt to define the relationship will result
+ * in an exception.
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOFieldImplCaching extends JDOFieldImplDynamic {
+
+    /** Relative field number. */
+    private int relativeFieldNumber = -1;
+
+    /**
+     * Get the persistence modifier of this JDOField.
+     * @return the persistence modifier, one of 
+     * {@link PersistenceModifier#NONE}, 
+     * {@link PersistenceModifier#PERSISTENT},
+     * {@link PersistenceModifier#TRANSACTIONAL}, or
+     * {@link PersistenceModifier#POSSIBLY_PERSISTENT}.
+     */
+    public int getPersistenceModifier() {
+        if (persistenceModifier == PersistenceModifier.UNSPECIFIED) {
+            persistenceModifier = super.getPersistenceModifier();
+        }
+        return persistenceModifier;
+    }
+
+    /**
+     * Returns the relative field number of this JDOField.
+     * @return the relative field number
+     */
+    public int getRelativeFieldNumber() {
+        ((JDOClassImplCaching)getDeclaringClass()).calculateFieldNumbers();
+        return relativeFieldNumber;
+    }
+
+    /**
+     * Determines whether this JDOField is part of the default fetch group or 
+     * not.
+     * @return <code>true</code> if the field is part of the default fetch 
+     * group, <code>false</code> otherwise
+     */
+    public boolean isDefaultFetchGroup() {
+        if (defaultFetchGroup == null) {
+            defaultFetchGroup = 
+                super.isDefaultFetchGroup() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return (defaultFetchGroup == null) ? 
+            false : defaultFetchGroup.booleanValue();
+    }
+
+    /**
+     * Determines whether the field should be stored if possible as part of
+     * the instance instead of as its own instance in the datastore.
+     * @return <code>true</code> if the field is stored as part of the instance;
+     * <code>false</code> otherwise
+     */
+    public boolean isEmbedded() {
+        if (embedded == null) {
+            embedded = super.isEmbedded() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return (embedded == null) ? false : embedded.booleanValue();
+    }
+    
+    /**
+     * Get the relationship information for this JDOField. The method 
+     * returns null if the field is not part of a relationship 
+     * (e.g. it is a primitive type field).
+     * @return relationship info of this JDOField or <code>null</code> if 
+     * this JDOField is not a relationship
+     */
+    public JDORelationship getRelationship() {
+        if (relationship == null) {
+            relationship = super.getRelationship();
+        }
+        return relationship;
+    }
+    
+    /**
+     * Creates and returns a new JDOReference instance. 
+     * This method automatically binds the new JDOReference to this JDOField. 
+     * It throws a ModelException, if this JDOField is already bound to 
+     * another JDORelationship instance. Otherwise the following holds true:
+     * <ul>
+     * <li> Method {@link #getRelationship} returns the new created instance
+     * <li> <code>this.getRelationship().getDeclaringField() == this</code>
+     * </ul> 
+     * @return a new JDOReference instance bound to this JDOField
+     * @exception ModelException if impossible
+     */
+    public JDOReference createJDOReference() throws ModelException {
+        if (relationship != null)
+            throw new ModelException(
+                msg.msg("EXC_RelationshipAlreadyDefined", //NOI18N
+                        getName(), relationship));
+        return super.createJDOReference();
+    }
+
+    /**
+     * Creates and returns a new JDOCollection instance. 
+     * This method automatically binds the new JDOCollection to this JDOField. 
+     * It throws a ModelException, if this JDOField is already bound to 
+     * another JDORelationship instance. Otherwise the following holds true:
+     * <ul>
+     * <li> Method {@link #getRelationship} returns the new created instance
+     * <li> <code>this.getRelationship().getDeclaringField() == this</code>
+     * </ul> 
+     * @return a new JDOCollection instance bound to this JDOField
+     * @exception ModelException if impossible
+     */
+    public JDOCollection createJDOCollection() throws ModelException {
+        if (relationship != null)
+            throw new ModelException(
+                msg.msg("EXC_RelationshipAlreadyDefined", //NOI18N
+                        getName(), relationship));
+        return super.createJDOCollection();
+    }
+
+    /**
+     * Creates and returns a new JDOArray instance. 
+     * This method automatically binds the new JDOArray to this JDOField. 
+     * It throws a ModelException, if this JDOField is already bound to 
+     * another JDORelationship instance. Otherwise the following holds true:
+     * <ul>
+     * <li> Method {@link #getRelationship} returns the new created instance
+     * <li> <code>this.getRelationship().getDeclaringField() == this</code>
+     * </ul> 
+     * @return a new JDOArray instance bound to this JDOField
+     * @exception ModelException if impossible
+     */
+    public JDOArray createJDOArray() throws ModelException {
+        if (relationship != null)
+            throw new ModelException(
+                msg.msg("EXC_RelationshipAlreadyDefined", //NOI18N
+                        getName(), relationship));
+        return super.createJDOArray();
+    }
+
+    /**
+     * Creates and returns a new JDOMap instance. 
+     * This method automatically binds the new JDOMap to this JDOField. 
+     * It throws a ModelException, if this JDOField is already bound to 
+     * another JDORelationship instance. Otherwise the following holds true:
+     * <ul>
+     * <li> Method {@link #getRelationship} returns the new created instance
+     * <li> <code>this.getRelationship().getDeclaringField() == this</code>
+     * </ul> 
+     * @return a new JDOMap instance bound to this JDOField
+     * @exception ModelException if impossible
+     */
+    public JDOMap createJDOMap() throws ModelException {
+        if (relationship != null)
+            throw new ModelException(
+                msg.msg("EXC_RelationshipAlreadyDefined", //NOI18N
+                        getName(), relationship));
+        return super.createJDOMap();
+    }
+
+    //========= Internal helper methods ==========
+
+    /**
+     * Creates and returns a new JDOCollection instance. 
+     * This method automatically this JDOField as the declarinmg field of 
+     * the returned instance.
+     * @return a new JDOCollection instance bound to this JDOField
+     */
+    protected JDOCollection createJDOCollectionInternal() {
+        JDOCollectionImplCaching collection = new JDOCollectionImplCaching();
+        // update relationship JDORelationship->JDOField
+        collection.setDeclaringField(this);
+        return collection;
+    }
+
+    /**
+     * Creates and returns a new JDOArray instance. 
+     * This method automatically this JDOField as the declarinmg field of 
+     * the returned instance.
+     * @return a new JDOArray instance bound to this JDOField
+     */
+    protected JDOArray createJDOArrayInternal() {
+        JDOArrayImplCaching array = new JDOArrayImplCaching();
+        // update relationship JDORelationship->JDOField
+        array.setDeclaringField(this);
+        return array;
+    }
+
+    /**
+     * Creates and returns a new JDOMap instance. 
+     * This method automatically this JDOField as the declarinmg field of 
+     * the returned instance.
+     * @return a new JDOMap instance bound to this JDOField
+     */
+    protected JDOMap createJDOMapInternal() {
+        JDOMapImplCaching map = new JDOMapImplCaching();
+        // update relationship JDORelationship->JDOField
+        map.setDeclaringField(this);
+        return map;
+    }
+
+    /**
+     * Sets the relative field number of this JDOField.
+     * @param number the relative field number
+     */
+    void setRelativeFieldNumber(int number) {
+        this.relativeFieldNumber = number;
+    }
+}

Added: incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOMapImplCaching.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOMapImplCaching.java?rev=171348&view=auto
==============================================================================
--- incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOMapImplCaching.java (added)
+++ incubator/jdo/trunk/core20/src/java/org/apache/jdo/impl/model/jdo/caching/JDOMapImplCaching.java Sun May 22 10:44:19 2005
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.impl.model.jdo.caching;
+
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.impl.model.jdo.JDOMapImplDynamic;
+
+/**
+ * An instance of this class represents the JDO relationship metadata 
+ * (the treatment of keys and values) of a map relationship field.  
+ * This caching implementation caches any calulated value to avoid
+ * re-calculating it if it is requested again. 
+ *
+ * @author Michael Bouschen
+ * @since 1.1
+ * @version 1.1
+ */
+public class JDOMapImplCaching extends JDOMapImplDynamic {
+    
+    /**
+     * Determines whether the keys of the map should be stored if possible as 
+     * part of the instance instead of as their own instances in the datastore.
+     * @return <code>true</code> if the keys are stored as part of this instance;
+     * <code>false</code> otherwise
+     */
+    public boolean isEmbeddedKey() {
+        if (embeddedKey == null) {
+            embeddedKey =
+                super.isEmbeddedKey() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return embeddedKey.booleanValue();
+    }
+    
+    /**
+     * Get the type representation of the keys for this JDOMap.
+     * @return the type of the keys of this JDOMap  
+     */
+    public JavaType getKeyType() {
+        if (keyType == null) {
+            keyType = super.getKeyType();
+        }
+        return keyType;
+    }
+
+    /**
+     * Determines whether the values of the map should be stored if possible as 
+     * part of the instance instead of as their own instances in the datastore.
+     * @return <code>true</code> if the values are stored as part of this 
+     * instance; <code>false</code> otherwise
+     */
+    public boolean isEmbeddedValue() {
+        if (embeddedValue == null) {
+            embeddedValue = 
+                super.isEmbeddedValue() ? Boolean.TRUE : Boolean.FALSE;
+        }
+        return embeddedValue.booleanValue();
+    }
+    
+    /**
+     * Get the type representation of the values for this JDOMap.
+     * @return the type of the values of this JDOMap  
+     */
+    public JavaType getValueType() {
+        if (valueType == null) {
+            valueType = super.getValueType();
+        }
+        return valueType;
+    }
+
+}