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:55:54 UTC

svn commit: r171351 [13/16] - in /incubator/jdo/trunk/enhancer20: ./ src/ src/conf/ src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/jdo/ src/java/org/apache/jdo/enhancer/ src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/enhancer/ src/java/org/apache/jdo/impl/enhancer/classfile/ src/java/org/apache/jdo/impl/enhancer/core/ src/java/org/apache/jdo/impl/enhancer/generator/ src/java/org/apache/jdo/impl/enhancer/meta/ src/java/org/apache/jdo/impl/enhancer/meta/model/ src/java/org/apache/jdo/impl/enhancer/meta/prop/ src/java/org/apache/jdo/impl/enhancer/meta/util/ src/java/org/apache/jdo/impl/enhancer/util/ test/ test/sempdept/ test/sempdept/src/ test/sempdept/src/empdept/

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaData.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaData.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaData.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaData.java Sun May 22 10:55:51 2005
@@ -0,0 +1,434 @@
+/*
+ * 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.enhancer.meta;
+
+
+/**
+ * Provides the JDO meta information neccessary for byte-code enhancement.
+ * <p>
+ * <b>Please note: This interface deals with fully qualified names in the
+ * JVM notation, that is, with '/' as package separator character&nbsp;
+ * (instead of '.').</b>
+ */
+public interface EnhancerMetaData
+{
+    /**
+     * The JDO field flags.
+     */
+    int CHECK_READ    = 0x01;
+    int MEDIATE_READ  = 0x02;
+    int CHECK_WRITE   = 0x04;
+    int MEDIATE_WRITE = 0x08;
+    int SERIALIZABLE  = 0x10;
+
+    // ----------------------------------------------------------------------
+    // Class Metadata
+    // ----------------------------------------------------------------------
+
+    /**
+     * Returns whether a class is not to be modified by the enhancer.
+     * <P>
+     * It is an error if an unenhanceable class is persistence-capable
+     * (or persistence-aware).  The following holds:
+     *   isKnownUnenhancableClass(classPath)
+     *       ==> !isPersistenceCapableClass(classPath)
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is known to be unmodifiable; otherwise false
+     * @see #isPersistenceCapableClass(String)
+     */
+    boolean isKnownUnenhancableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a class is persistence-capable.
+     * <P>
+     * If a persistence-capable class is also known to be unenhancable,
+     * an exception is thrown.
+     * The following holds:
+     *   isPersistenceCapableClass(classPath)
+     *       ==> !isKnownUnenhancableClass(classPath)
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is persistence-capable; otherwise false
+     * @see #isKnownUnenhancableClass(String)
+     */
+    boolean isPersistenceCapableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a class implements java.io.Serializable.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is serializable; otherwise false
+     */
+    boolean isSerializableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the name of the persistence-capable superclass of a class.
+     * <P>
+     * The following holds:
+     *   (String s = getPersistenceCapableSuperClass(classPath)) != null
+     *       ==> isPersistenceCapableClass(classPath)
+     *           && !isPersistenceCapableRootClass(classPath)
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return the name of the PC superclass or null if there is none
+     * @see #isPersistenceCapableClass(String)
+     * @see #getPersistenceCapableRootClass(String)
+     */
+    String getPersistenceCapableSuperClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the name of the key class of a class.
+     * <P>
+     * The following holds:
+     *   (String s = getKeyClass(classPath)) != null
+     *       ==> !isPersistenceCapableClass(s)
+     *           && isPersistenceCapableClass(classPath)
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return the name of the key class or null if there is none
+     * @see #isPersistenceCapableClass(String)
+     */
+    String getKeyClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns an array of field names of all declared persistent and
+     * transactional fields of a class.
+     * <P>
+     * The position of the field names in the result array corresponds
+     * to their unique field index as returned by getFieldNumber such that
+     * these equations hold:
+     * <P> getFieldNumber(getManagedFields(classPath)[i]) == i
+     * <P> getManagedFields(classPath)[getFieldNumber(fieldName)] == fieldName
+     * <P>
+     * This method requires all fields having been declared by
+     * declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return an array of all declared persistent and transactional
+     *         fields of a class
+     * @see #getFieldNumber(String, String)
+     * @see #declareField(String, String, String)
+     */
+    String[] getManagedFields(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    // ----------------------------------------------------------------------
+    // Field Metadata
+    // ----------------------------------------------------------------------
+
+    /** 
+     * Returns the JVM-qualified name of the specified field's declaring
+     * class. The method first checks whether the class of the specified
+     * classPath (the JVM-qualified name) declares such a field. If yes,
+     * classPath is returned. Otherwise, it checks its superclasses. The
+     * method returns <code>null</code> for an unkown field.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return the JVM-qualified name of the declararing class of the
+     * field, or <code>null</code> if there is no such field.
+     */
+    String getDeclaringClass(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError; 
+
+    /**
+     * Declares a field to the JDO model passing its type information.
+     * <P>
+     * By the new JDO model, it's a requirement to declare fields to
+     * the model for their type information before any field information
+     * based on persistence-modifiers can be retrieved.  This method
+     * passes a field's type information to the underlying JDO model.
+     * <P>
+     * There's one important exception: The method isKnownNonManagedField()
+     * may be called at any time.
+     * <P>
+     * The class must be persistence-capable, otherwise an exception
+     * is thrown.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @param fieldSig the non-null JVM signature of the field
+     * @see #isPersistenceCapableClass(String)
+     */
+    void declareField(String classPath, String fieldName, String fieldSig)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is known to be non-managed.
+     * <P>
+     * This method differs from isManagedField() in that a field may or
+     * may not be managed if its not known as non-managed.
+     * The following holds (not vice versa!):
+     *   isKnownNonManagedField(classPath, fieldName, fieldSig)
+     *       ==> !isManagedField(classPath, fieldName)
+     * <P>
+     * This method doesn't require the field having been declared by
+     * declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @param fieldSig the non-null type signature of the field
+     * @return true if this field is known to be non-managed; otherwise false
+     * @see #isManagedField(String, String)
+     * @see #declareField(String, String, String)
+     */
+    boolean isKnownNonManagedField(String classPath,
+                                   String fieldName,
+                                   String fieldSig)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is transient transactional
+     * or persistent.
+     * <P>
+     * A managed field must not be known as non-managed and must be either
+     * transient transactional or persistent.  The following holds:
+     *   isManagedField(classPath, fieldName)
+     *       ==> !isKnownNonManagedField(classPath, fieldName, fieldSig)
+     *           && (isPersistentField(classPath, fieldName)
+     *               ^ isTransactionalField(classPath, fieldName))
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return true if this field is managed; otherwise false
+     * @see #isKnownNonManagedField(String, String, String)
+     * @see #isPersistentField(String, String)
+     * @see #isTransactionalField(String, String)
+     * @see #isPersistenceCapableClass(String)
+     */
+    boolean isManagedField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is transient
+     * transactional.
+     * <P>
+     * A transient transactional field cannot be persistent.
+     * The following holds:
+     *   isTransactionalField(classPath, fieldName)
+     *       ==> isManagedField(classPath, fieldName)
+     *           && !isPersistentField(classPath, fieldName)
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return true if this field is transactional; otherwise false
+     * @see #isManagedField(String, String)
+     * @see #declareField(String, String, String)
+     */
+    boolean isTransactionalField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is persistent.
+     * <P>
+     * A persistent field cannot be transient transactional.
+     * The following holds:
+     *   isPersistentField(classPath, fieldName)
+     *       ==> isManagedField(classPath, fieldName)
+     *           && !isTransactionalField(classPath, fieldName)
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return true if this field is persistent; otherwise false
+     * @see #isManagedField(String, String)
+     * @see #declareField(String, String, String)
+     */
+    boolean isPersistentField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is key.
+     * <P>
+     * A key field must be persistent.
+     * The following holds:
+     *   isKeyField(classPath, fieldName)
+     *       ==> isPersistentField(classPath, fieldName)
+     *           && !isDefaultFetchGroupField(classPath, fieldName)
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return true if this field is key; otherwise false
+     * @see #isPersistentField(String, String)
+     * @see #declareField(String, String, String)
+     */
+    boolean isKeyField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns whether a field of a class is part of the
+     * default fetch group.
+     * <P>
+     * A field in the default fetch group must be persistent.
+     * The following holds:
+     *   isDefaultFetchGroupField(classPath, fieldName)
+     *       ==> isPersistentField(classPath, fieldName)
+     *           && !isKeyField(classPath, fieldName)
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return true if this field is part of the
+     *         default fetch group; otherwise false
+     * @see #isPersistentField(String, String)
+     * @see #declareField(String, String, String)
+     */
+    boolean isDefaultFetchGroupField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the unique field index of a declared, managed field of a
+     * class.
+     * <P>
+     * The following holds:
+     *   int i = getFieldFlags(classPath, fieldName);
+     *   i > 0  ==>  getManagedFields(classPath)[i] == fieldName
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return the non-negative, unique field index or -1 if the field
+     *         is non-managed
+     * @see #getManagedFields(String)
+     * @see #declareField(String, String, String)
+     */
+    int getFieldNumber(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the field flags for a declared field of a class.
+     * <P>
+     * The following holds for the field flags:
+     *   int f = getFieldFlags(classPath, fieldName);
+     *
+     *   !isManagedField(classPath, fieldName)
+     *       ==> (f & CHECK_READ == 0) && (f & MEDIATE_READ == 0) &&
+     *           (f & CHECK_WRITE == 0) && (f & MEDIATE_WRITE == 0)
+     *
+     *   isTransactionalField(classPath, fieldName)
+     *       ==> (f & CHECK_READ == 0) && (f & MEDIATE_READ == 0) &&
+     *           (f & CHECK_WRITE != 0) && (f & MEDIATE_WRITE == 0)
+     *
+     *   isKeyField(classPath, fieldName)
+     *       ==> (f & CHECK_READ == 0) && (f & MEDIATE_READ == 0) &&
+     *           (f & CHECK_WRITE == 0) && (f & MEDIATE_WRITE != 0)
+     *
+     *   isDefaultFetchGroupField(classPath, fieldName)
+     *       ==> (f & CHECK_READ != 0) && (f & MEDIATE_READ != 0) &&
+     *           (f & CHECK_WRITE == 0) && (f & MEDIATE_WRITE == 0)
+     *
+     *   isPersistentField(classPath, fieldName)
+     *   && isKeyField(classPath, fieldName)
+     *   && isDefaultFetchGroupField(classPath, fieldName)
+     *       ==> (f & CHECK_READ == 0) && (f & MEDIATE_READ == 0) &&
+     *           (f & CHECK_WRITE != 0) && (f & MEDIATE_WRITE != 0)
+     * <P>
+     * This method requires the field having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return the field flags for this field
+     * @see #declareField(String, String, String)
+     */
+    int getFieldFlags(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    // ----------------------------------------------------------------------
+    // Convenience Methods
+    // ----------------------------------------------------------------------
+
+    /**
+     * Returns whether a class is persistence-capable root class.
+     * <P>
+     * The following holds:
+     *   isPersistenceCapableRootClass(classPath)
+     *     <==> isPersistenceCapableClass(classPath)
+     *          && getPersistenceCapableSuperClass(classPath) == null
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is persistence-capable and does not
+     *         derive from another persistence-capable class; otherwise false
+     */
+    boolean isPersistenceCapableRootClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the name of the persistence-capable root class of a class.
+     * <P>
+     * The following holds:
+     *   (String s = getPersistenceCapableRootClass(classPath)) != null
+     *       ==> isPersistenceCapableClass(classPath)
+     *           && getPersistenceCapableSuperClass(classPath) == null
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return the name of the least-derived persistence-capable class that
+     *         is equal to or a super class of the argument class; if the
+     *         argument class is not persistence-capable, null is returned.
+     */
+    String getPersistenceCapableRootClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the name of the key class of the next persistence-capable
+     * superclass that defines one.
+     * <P>
+     * The following holds:
+     *   (String s = getSuperKeyClass(classPath)) != null
+     *       ==> !isPersistenceCapableClass(s)
+     *           && isPersistenceCapableClass(classPath)
+     *           && !isPersistenceCapableRootClass(classPath)
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return the name of the key class or null if there is none
+     * @see #getKeyClass(String)
+     * @see #getPersistenceCapableSuperClass(String)
+     */
+    String getSuperKeyClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns an array of field names of all key fields of a class.
+     * <P>
+     * This method requires all fields having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return an array of all declared key fields of a class
+     * @see #declareField(String, String, String)
+     */
+    String[] getKeyFields(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the unique field index of some declared, managed fields of a
+     * class.
+     * <P>
+     * This method requires all fields having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldNames the non-null array of names of the declared fields
+     * @return the non-negative, unique field indices
+     * @see #declareField(String, String, String)
+     */
+    int[] getFieldNumber(String classPath, String[] fieldNames)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the field flags for some declared, managed fields of a class.
+     * <P>
+     * This method requires all fields having been declared by declareField().
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldNames the non-null array of names of the declared fields
+     * @return the field flags for the fields
+     * @see #declareField(String, String, String)
+     */
+    int[] getFieldFlags(String classPath, String[] fieldNames)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataFatalError.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataFatalError.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataFatalError.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataFatalError.java Sun May 22 10:55:51 2005
@@ -0,0 +1,72 @@
+/*
+ * 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.enhancer.meta;
+
+
+/**
+ * Thrown to indicate that an access to JDO meta-data failed due to a
+ * serious error, which might have left the meta-data component in an
+ * inconsistent state.
+ */
+public class EnhancerMetaDataFatalError
+    //^olsen: provisional, convert to a checked exception
+    extends RuntimeException
+{
+    /**
+     * An optional nested exception.
+     */
+    public final Throwable nested;
+
+    /**
+     * Constructs an <code>EnhancerMetaDataFatalError</code> with no detail message.
+     */
+    public EnhancerMetaDataFatalError()
+    {
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataFatalError</code> with the specified
+     * detail message.
+     */
+    public EnhancerMetaDataFatalError(String msg)
+    {
+        super(msg);
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataFatalError</code> with an optional
+     * nested exception.
+     */
+    public EnhancerMetaDataFatalError(Throwable nested)
+    {
+        super(nested.toString());
+        this.nested = nested;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataFatalError</code> with the specified
+     * detail message and an optional nested exception.
+     */
+    public EnhancerMetaDataFatalError(String msg, Throwable nested)
+    {
+        super(msg);
+        this.nested = nested;
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataUserException.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataUserException.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataUserException.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/EnhancerMetaDataUserException.java Sun May 22 10:55:51 2005
@@ -0,0 +1,72 @@
+/*
+ * 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.enhancer.meta;
+
+
+/**
+ * Thrown to indicate that an access to JDO meta-data failed; the
+ * meta-data component is assured to remain in consistent state.
+ */
+public class EnhancerMetaDataUserException
+    //^olsen: provisional, convert to a checked exception
+    extends RuntimeException
+{
+    /**
+     * An optional nested exception.
+     */
+    public final Throwable nested;
+
+    /**
+     * Constructs an <code>EnhancerMetaDataUserException</code> with no detail
+     * message.
+     */
+    public EnhancerMetaDataUserException()
+    {
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataUserException</code> with the specified
+     * detail message.
+     */
+    public EnhancerMetaDataUserException(String msg)
+    {
+        super(msg);
+        this.nested = null;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataUserException</code> with an optional
+     * nested exception.
+     */
+    public EnhancerMetaDataUserException(Throwable nested)
+    {
+        super("nested exception: " + nested);
+        this.nested = nested;
+    }
+
+    /**
+     * Constructs an <code>EnhancerMetaDataUserException</code> with the specified
+     * detail message and an optional nested exception.
+     */
+    public EnhancerMetaDataUserException(String msg, Throwable nested)
+    {
+        super(msg);
+        this.nested = nested;
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/ExtendedMetaData.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/ExtendedMetaData.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/ExtendedMetaData.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/ExtendedMetaData.java Sun May 22 10:55:51 2005
@@ -0,0 +1,111 @@
+/*
+ * 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.enhancer.meta;
+
+
+/**
+ * Provides extended JDO meta information for byte-code enhancement.
+ */
+public interface ExtendedMetaData
+       extends EnhancerMetaData
+{
+    /**
+     *  Gets all known classnames.
+     *
+     *  @return  All known classnames.
+     */
+    String[] getKnownClasses()
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;    
+
+    /**
+     *  Gets the modifiers of a class. The return value is a constant of the
+     *  <code>java.lang.reflect.Modifier</code> class.
+     *
+     *  @param  classname  The classname.
+     *  @return  The modifiers.
+     *  @see  java.lang.reflect.Modifier
+     */
+    int getClassModifiers(String classname)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     * Returns the name of the superclass of a class.
+     * <P>
+     * @param classPath the JVM-qualified name of the class 
+     * @return the name of the superclass or null if there is none
+     */
+    String getSuperClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     *  Gets all known fieldnames of a class.
+     *
+     *  @param  classname  The classname.
+     *  @return  All known fieldnames.
+     */
+    String[] getKnownFields(String classname)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     *  Gets the type of a field.
+     *
+     *  @param  classname  The classname.
+     *  @param  fieldname  The fieldname.
+     *  @return  The type of the field.
+     */
+    String getFieldType(String classname,
+                        String fieldname)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     *  Gets the modifiers of a field. The return value is a constant of the
+     *  <code>java.lang.reflect.Modifier</code> class.
+     *
+     *  @param  classname  The classname.
+     *  @param  fieldname  The fieldname.
+     *  @return  The modifiers.
+     *  @see  java.lang.reflect.Modifier
+     */
+    int getFieldModifiers(String classname,
+                          String fieldname)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    // convenience methods
+
+    /**
+     *  Gets the type of some fields.
+     *
+     *  @param  classname  The classname.
+     *  @param  fieldnames  The fieldnames.
+     *  @return  The type of the fields.
+     */
+    String[] getFieldType(String classname,
+                          String[] fieldnames)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+
+    /**
+     *  Gets the modifiers of some fields.
+     *
+     *  @param  classname  The classname.
+     *  @param  fieldnames  The fieldnames.
+     *  @return  The modifiers.
+     *  @see  java.lang.reflect.Modifier
+     */
+    int[] getFieldModifiers(String classname,
+                            String[] fieldnames)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError;
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaModel.java Sun May 22 10:55:51 2005
@@ -0,0 +1,158 @@
+/*
+ * 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.enhancer.meta.model;
+
+import java.io.InputStream;
+
+import org.apache.jdo.impl.enhancer.util.ResourceLocator;
+import org.apache.jdo.impl.model.java.reflection.ReflectionJavaModel;
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.model.jdo.JDOModel;
+
+/**
+ * Provides some basic Java type information based on JVM descriptors.
+ * 
+ * @author Michael Bouschen
+ * @author Martin Zaun
+ */
+public class EnhancerJavaModel
+    extends ReflectionJavaModel
+{
+    /**
+     * The "package" jdo file.
+     */
+    final private ResourceLocator locator;
+
+    /**
+     * Creates an instance.
+     */
+    public EnhancerJavaModel(ClassLoader classLoader,
+                             ResourceLocator locator)
+    {
+        super(classLoader, false);
+        this.locator = locator;
+    }
+    
+    /**
+     * Finds a resource with a given name.  This method returns
+     * <code>null</code> if no resource with this name is found.
+     * The name of a resource is a "/"-separated path name.
+     */
+    public InputStream getInputStreamForResource(String resourceName)
+    {
+        // first try the locator
+        InputStream stream = locator.getInputStreamForResource(resourceName);
+        if (stream == null)
+            // if the locator cannot find the resource try the class loader
+            stream = super.getInputStreamForResource(resourceName);
+        return stream;
+    }
+
+    // ===== Methods not defined in JavaModel =====
+
+    /** 
+     * Creates a new JavaType instance for the specified Class object.
+     * <p>
+     * This implementation returns a EnhancerJavaType instance.
+     * @param clazz the Class instance representing the type
+     * @return a new JavaType instance
+     */
+    protected JavaType createJavaType(Class clazz)
+    {
+        return new EnhancerJavaType(clazz, getJDOModel(), this);
+    }
+
+    /** 
+     * Returns the fully qualified name of the specified type representation.
+     */
+    public String getTypeName(String sig)
+    {
+        // translates a VM type field signature into Java-format signature
+        final int n = sig.length();
+        affirm(n > 0, "invalid field signature: \"\"");
+
+        // handle arrays
+        if (sig.startsWith("["))
+            return sig.replace('/','.');
+
+        // parse rest of signature
+        final String name;
+        final char c = sig.charAt(0);
+        switch (c) {
+        case 'Z':
+            name = "boolean";
+            break;
+        case 'C':
+            name = "char";
+            break;
+        case 'B':
+            name = "byte";
+            break;
+        case 'S':
+            name = "short";
+            break;
+        case 'I':
+            name = "int";
+            break;
+        case 'F':
+            name = "float";
+            break;
+        case 'J':
+            name = "long";
+            break;
+        case 'D':
+            name = "double";
+            break;
+        case 'L':
+            // return reference type with array dimensions
+            affirm(sig.indexOf(';') == n - 1,
+                   "invalid field signature: " + sig);
+            name = sig.substring(1, n - 1);
+            affirm(isValidName(name, '/'),
+                   "invalid field signature: " + sig);
+            return name.replace('/','.');
+        default:
+            name = "";
+            affirm(false, "invalid field signature: " + sig);
+        }
+        return name;
+    }
+
+    static private boolean isValidName(String name, char separator) 
+    {
+        final int n = name.length();
+        if (n == 0) {
+            return false;
+        }
+        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+            return false;
+        }
+        for (int i = 1; i < n; i++) {
+            final char c = name.charAt(i);
+            if (!Character.isJavaIdentifierPart(c) && c != separator) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static protected final void affirm(boolean condition, String msg) {
+        if (!condition)
+            throw new InternalError("assertion failed: " + msg);
+    }
+
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaType.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaType.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaType.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerJavaType.java Sun May 22 10:55:51 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.enhancer.meta.model;
+
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError;
+import org.apache.jdo.impl.model.java.reflection.ReflectionJavaType;
+import org.apache.jdo.model.java.JavaModel;
+import org.apache.jdo.model.java.JavaType;
+import org.apache.jdo.model.jdo.JDOModel;
+
+
+
+/**
+ * Provides some basic Java type information based on JVM descriptors.
+ * 
+ * @author Michael Bouschen
+ * @since JDO 1.0.1
+ */
+public class EnhancerJavaType
+    extends ReflectionJavaType
+{
+    /** The declaring EnhancerJavaModel instance. */
+    private JavaModel javaModel = null;
+
+    /**
+     * Creates an instance.
+     */
+    public EnhancerJavaType(Class clazz, JDOModel jdoModel, JavaModel javaModel)
+    {
+        super(clazz, jdoModel);
+        this.javaModel = javaModel;
+    }
+    
+    // ===== Methods not defined in JavaType =====
+
+    /** 
+     * Returns a JavaType instance for the specified Class object. 
+     * <p>
+     * This implementation delegates the call to the javaModel.
+     * @param clazz the Class instance representing the type
+     * @return a JavaType instance for the name of the specified class
+     * object or <code>null</code> if not present in this model instance.
+     */
+    protected JavaType getJavaTypeInternal(Class clazz)
+    {
+        return javaModel.getJavaType(clazz);
+    }
+    
+    
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerMetaDataJDOModelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerMetaDataJDOModelImpl.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerMetaDataJDOModelImpl.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/model/EnhancerMetaDataJDOModelImpl.java Sun May 22 10:55:51 2005
@@ -0,0 +1,551 @@
+/*
+ * 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.enhancer.meta.model;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.File;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaData;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataUserException;
+import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataBaseModel;
+import org.apache.jdo.impl.enhancer.util.CombinedResourceLocator;
+import org.apache.jdo.impl.enhancer.util.ListResourceLocator;
+import org.apache.jdo.impl.enhancer.util.PathResourceLocator;
+import org.apache.jdo.impl.enhancer.util.ResourceLocator;
+import org.apache.jdo.impl.model.jdo.caching.JDOModelFactoryImplCaching;
+import org.apache.jdo.impl.model.jdo.util.TypeSupport;
+import org.apache.jdo.model.ModelException;
+import org.apache.jdo.model.ModelFatalException;
+import org.apache.jdo.model.java.JavaField;
+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.JDOField;
+import org.apache.jdo.model.jdo.JDOModel;
+import org.apache.jdo.model.jdo.JDOModelFactory;
+import org.apache.jdo.model.jdo.PersistenceModifier;
+
+/**
+ * Provides the JDO meta information based on a JDO meta model.
+ */
+public class EnhancerMetaDataJDOModelImpl
+    extends EnhancerMetaDataBaseModel
+    implements EnhancerMetaData
+{
+    /**
+     * The jdoModel instance.
+     */
+    private final JDOModel jdoModel;
+
+    /**
+     * The model instance.
+     */
+    private final EnhancerJavaModel javaModel;
+
+    /**
+     * The JavaType representation for java.io.Serializable.
+     */
+    private final JavaType serializableJavaType;
+    
+    /**
+     * Creates an instance.
+     */
+    public EnhancerMetaDataJDOModelImpl(PrintWriter out,
+                                        boolean verbose,
+                                        List jdoFileNames,
+                                        List jarFileNames,
+                                        String sourcePath)
+        throws EnhancerMetaDataFatalError
+    {
+        super(out, verbose);
+
+        try {
+            final List locators = new ArrayList();
+            ClassLoader classLoader = null;
+
+            // create resource locator for specified jdo files
+            if (jdoFileNames != null && !jdoFileNames.isEmpty()) {
+                final StringBuffer s = new StringBuffer();
+                for (Iterator i = jdoFileNames.iterator(); i.hasNext();) {
+                    s.append(" " + i.next());
+                }
+                final ResourceLocator jdos
+                    = new ListResourceLocator(out, verbose, jdoFileNames);
+                //printMessage(getI18N("enhancer.metadata.using_jdo_files",
+                //                     s.toString()));
+                locators.add(jdos);
+            }
+
+            // create resource locator for specified jar files
+            if (jarFileNames != null && !jarFileNames.isEmpty()) {
+                final StringBuffer s = new StringBuffer();
+                final Iterator i = jarFileNames.iterator();
+                s.append(i.next());
+                while (i.hasNext()) {
+                    s.append(File.pathSeparator + i.next());
+                }
+                final PathResourceLocator jars
+                    = new PathResourceLocator(out, verbose, s.toString());
+                //printMessage(getI18N("enhancer.metadata.using_jar_files",
+                //                     s.toString()));
+                locators.add(jars);
+                classLoader = jars.getClassLoader();
+            }
+
+            // create resource locator for specified source path
+            if (sourcePath != null && sourcePath.length() > 0) {
+                final PathResourceLocator path
+                    = new PathResourceLocator(out, verbose, sourcePath);
+                //printMessage(getI18N("enhancer.metadata.using_source_path",
+                //                     sourcePath));
+                locators.add(path);
+                classLoader = path.getClassLoader();
+            }
+
+            if (classLoader == null) {
+                // use the current class loader as the default, if there is
+                // no -s option and no archives specified.
+                classLoader = EnhancerMetaDataJDOModelImpl.class.getClassLoader();
+            }
+
+            // print warning if no meta-data source specified
+            if (locators.isEmpty()) {
+                printWarning(getI18N("enhancer.metadata.using_no_metadata"));
+            }
+
+            // create JavaModel with combined resource locators
+            final ResourceLocator locator
+                = new CombinedResourceLocator(out, verbose, locators);
+            //^olsen: wrap with timing jdo file locator
+            //if (options.doTiming.value) {
+            //    classLocator = new ResourceLocatorTimer(classLocator);
+            //}
+            javaModel = new EnhancerJavaModel(classLoader, locator);
+            final JDOModelFactory factory = JDOModelFactoryImplCaching.getInstance();
+            affirm(factory != null);
+            jdoModel = factory.getJDOModel(javaModel);
+            affirm(jdoModel != null);
+            javaModel.setJDOModel(jdoModel);
+            serializableJavaType = javaModel.getJavaType("java.io.Serializable");
+        } catch (IOException ex) {
+            final String msg
+                = getI18N("enhancer.metadata.io_error", ex.getMessage());
+            throw new EnhancerMetaDataFatalError(msg, ex);
+        } catch (ModelFatalException ex) {
+            final String msg
+                = getI18N("enhancer.metadata.jdomodel_error", ex.getMessage());
+            throw new EnhancerMetaDataFatalError(msg, ex);
+        } catch (ModelException ex) {
+            final String msg
+                = getI18N("enhancer.metadata.jdomodel_error", ex.getMessage());
+            throw new EnhancerMetaDataFatalError(msg, ex);
+        }        
+    }
+
+    // ----------------------------------------------------------------------
+    
+    private JDOClass getJDOClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final String className = classPath.replace('/', '.');
+        final JDOClass clazz = jdoModel.getJDOClass(className);
+        return clazz;
+    }
+    
+    private JDOField getJDOField(String classPath,
+                                 String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return null;
+        }
+        final JDOField field = clazz.getDeclaredField(fieldName);
+        affirm(field == null || field.getDeclaringClass() == clazz,
+               "field not declared in class: " + classPath + "." + fieldName);
+        return field;
+    }
+    
+    private boolean hasFieldModifier(String classPath,
+                                     String fieldName,
+                                     int fieldModifier)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        if (field == null) {
+            return false;
+        }
+        final int pm = field.getPersistenceModifier();
+        affirm(pm != PersistenceModifier.UNSPECIFIED,
+               "field modifier 'UNSPECIFIED': " + classPath + "." + fieldName);
+        return (pm & fieldModifier) != 0;
+    }
+
+    // ----------------------------------------------------------------------
+    
+
+    /** 
+     * Returns the JVM-qualified name of the specified field's declaring
+     * class. The method first checks whether the class of the specified
+     * classPath (the JVM-qualified name) declares such a field. If yes,
+     * classPath is returned. Otherwise, it checks its superclasses. The
+     * method returns <code>null</code> for an unkown field.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return the JVM-qualified name of the declararing class of the
+     * field, or <code>null</code> if there is no such field.
+     */
+    public String getDeclaringClass(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        affirm(classPath);
+        affirm(fieldName);
+        final String className = classPath.replace('/', '.');
+        try {
+            final JavaType javaType = javaModel.getJavaType(className);
+            final JavaField javaField = javaType.getJavaField(fieldName);
+            final JavaType declaringClass = javaField.getDeclaringClass();
+            return declaringClass.getName().replace('.', '/');
+        } catch (ModelFatalException ex) {
+            throw new EnhancerMetaDataUserException(ex);
+        }
+    }
+
+    /**
+     * Declares a field to the JDO model passing its type information.
+     * @see declareField(String, String, String)
+     */
+/*
+    public void declareField(String classPath,
+                             String fieldName,
+                             String fieldSig)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {        
+        affirm(classPath);
+        affirm(fieldName);
+        affirm(fieldSig);
+        final JDOClass clazz = getJDOClass(classPath);
+        affirm(clazz != null,
+               "class is not persistence-capable: " + classPath);
+        try {
+            final JDOField field = clazz.createJDOField(fieldName);
+            affirm(field != null,
+                   "cannot create JDO field: " + classPath + "." + fieldName);
+            field.setType(fieldSig);
+            affirm(fieldSig == field.getType());    
+
+            //^olsen: cleanup debugging code
+            String s0 = model.getJavaModel().getTypeName(fieldSig);
+            String s1 = (String)model.getJavaModel().getTypeForName(s0);
+            //out.println("s0 = " + s0);
+            //out.println("s1 = " + s1);
+            affirm(fieldSig.equals(s1));
+        } catch (JDOModelException ex) {
+            throw new EnhancerMetaDataUserException(ex);
+        }
+    }
+*/
+    
+    /**
+     * Declares a field to the JDO model passing its type information.
+     */
+    public void declareField(String classPath,
+                             String fieldName,
+                             String fieldSig)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {        
+        affirm(classPath);
+        affirm(fieldName);
+        try {
+            final JDOClass clazz = getJDOClass(classPath);
+            JavaType javaClass = clazz.getJavaType();
+            affirm(javaClass != null,
+                   "cannot find class file for class: " + classPath);
+            JavaField javaField = javaClass.getJavaField(fieldName);
+            affirm(javaField != null,
+                   "cannot find java field " + classPath + "." + fieldName);
+            JavaType fieldType = javaField.getType();
+            JDOField field = clazz.getField(fieldName);
+            // if field not known by JDOClass (not specified in JDO XML),
+            // create the field only if the model's method of default
+            // calculation would yield a persistent field.  We must not
+            // change the models state by newly created fields with
+            // a persistence-modifier "none", because this would lead to
+            // in a different annotation by isKnownNonManagedField().
+            if (field == null
+                && TypeSupport.isPersistenceFieldType(fieldType)) {
+                field = clazz.createJDOField(fieldName);
+                affirm(field != null,
+                       "cannot create JDO field: "
+                       + classPath + "." + fieldName);
+            }
+            field.setJavaField(javaField);
+            affirm(fieldType == field.getType());
+            affirm(field.getPersistenceModifier()
+                   != PersistenceModifier.UNSPECIFIED,
+                   "known, unspecified JDO field: " + classPath + "." + fieldName);
+        } catch (ModelFatalException ex) {
+            throw new EnhancerMetaDataUserException(ex);
+        } catch (ModelException ex) {
+            throw new EnhancerMetaDataUserException(ex);
+        }
+    }
+    
+    /**
+     * Tests whether a class is known to be persistence-capable.
+     */
+    public boolean isPersistenceCapableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        return (clazz != null);
+    }
+
+    /**
+     * Returns whether a class implements java.io.Serializable
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is serializable; otherwise false
+     */
+    public boolean isSerializableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final String className = classPath.replace('/', '.');
+        final JavaType javaType = javaModel.getJavaType(className);
+        return javaType.isCompatibleWith(serializableJavaType);
+    }
+
+    /**
+     * Returns the name of the persistence-capable root class of a class.
+     */
+/*
+    public String getPersistenceCapableRootClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return null;
+        }
+        final JDOClass root = clazz.getPersistenceCapableRootClass();
+        if (root == null) {
+            return null;
+        }
+        final String name = root.getName();
+        affirm(name != null);
+        return name.replace('.', '/');
+    }
+*/
+
+    /**
+     * Returns the name of the persistence-capable superclass of a class.
+     */
+    public String getPersistenceCapableSuperClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return null;
+        }
+        final String name = clazz.getPersistenceCapableSuperclassName();
+        return (name != null ? name.replace('.', '/') : null);
+    }
+
+    /**
+     * Returns the name of the key class of a persistence-capable class.
+     */
+    public String getKeyClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return null;
+        }
+        final String name = clazz.getDeclaredObjectIdClassName();
+        return (name != null ? name.replace('.', '/') : null);
+    }
+
+    /**
+     * Returns an array of field names of all declared persistent and
+     * transactional fields of a class.
+     */
+    public String[] getManagedFields(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return new String[]{};
+        }
+
+        final JDOField[] fields = clazz.getDeclaredManagedFields();
+        if (fields == null) {
+            return new String[]{};
+        }
+        affirm(fields.length == clazz.getDeclaredManagedFieldCount());
+        
+        final int n = fields.length;
+        final String[] names = new String[n];
+        for (int i = 0; i < n; i++) {
+            affirm(fields[i] != null);
+            affirm(fields[i].getRelativeFieldNumber() == i);
+            affirm(fields[i].isManaged());
+            names[i] = fields[i].getName();
+            affirm(names[i] != null);
+        }
+        return names;
+    }
+
+    /**
+     * Returns whether a field of a class is known to be non-managed.
+     */
+    //^olsen: cleanup old code
+/*
+    public boolean isKnownNonManagedField(String classPath, String fieldName)
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            // class not known to be persistence-capable
+            return true;
+        }
+        final JDOField field = clazz.getField(fieldName);
+        if (field == null) {
+            // field not known by JDOClass (thus, not specified in JDO XML)
+            return false;
+        }
+        return field.isKnownNonManaged();
+    }
+*/
+
+    /**
+     * Returns whether a field of a class is known to be non-managed.
+     */
+    public boolean isKnownNonManagedField(String classPath,
+                                          String fieldName,
+                                          String fieldSig)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        affirm(classPath);
+        affirm(fieldName);
+        affirm(fieldSig);
+        try {
+            final JDOClass clazz = getJDOClass(classPath);
+            if (clazz == null) {
+                // class not known to be persistence-capable
+                return true;
+            }
+            
+            // check whether field is managed only if field's
+            // persistence-modifier is known by the JDO model
+            final JDOField field = clazz.getField(fieldName);
+            if (field != null && (field.getPersistenceModifier()
+                                  != PersistenceModifier.UNSPECIFIED)) {
+                // only field's persistence-modifier known by model
+                return !field.isManaged();
+            }
+
+            // field not known by JDOClass (not specified in JDO XML)
+            // apply model's method of default calculation without
+            // changing the model's state
+            JavaType fieldType = javaModel.getJavaType(javaModel.getTypeName(fieldSig));
+            affirm(fieldType != null, 
+                   "cannot get java type for: " + fieldSig);
+            return !TypeSupport.isPersistenceFieldType(fieldType);
+        } catch (ModelFatalException ex) {
+            throw new EnhancerMetaDataUserException(ex);
+        }
+    }
+
+    /**
+     * Tests whether a field of a class is transient transactional or
+     * persistent.
+     */
+    public boolean isManagedField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        return hasFieldModifier(classPath, fieldName,
+                                (PersistenceModifier.PERSISTENT
+                                 | PersistenceModifier.POSSIBLY_PERSISTENT
+                                 | PersistenceModifier.TRANSACTIONAL));
+    }
+
+    /**
+     * Tests whether a field of a class is persistent.
+     */
+    public boolean isPersistentField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        return hasFieldModifier(classPath, fieldName,
+                                (PersistenceModifier.PERSISTENT
+                                 | PersistenceModifier.POSSIBLY_PERSISTENT));
+    }
+
+    /**
+     * Tests whether a field of a class is transient transactional.
+     */
+    public boolean isTransactionalField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        return hasFieldModifier(classPath, fieldName,
+                                PersistenceModifier.TRANSACTIONAL);
+    }
+
+    /**
+     * Tests whether a field of a class is known to be Key.
+     */
+    public boolean isKeyField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        if (field == null) {
+            return false;
+        }
+        return field.isPrimaryKey();
+    }
+
+    /**
+     * Tests whether a field of a class is known to be part of the
+     * Default Fetch Group.
+     */
+    public boolean isDefaultFetchGroupField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        if (field == null) {
+            return false;
+        }
+        return field.isDefaultFetchGroup();
+    }
+
+    /**
+     * Returns the unique field index of a declared, persistent field of a
+     * class.
+     */
+    public int getFieldNumber(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        if (field == null) {
+            return -1;
+        }
+        return field.getRelativeFieldNumber();
+    }
+
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/EnhancerMetaDataPropertyImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/EnhancerMetaDataPropertyImpl.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/EnhancerMetaDataPropertyImpl.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/EnhancerMetaDataPropertyImpl.java Sun May 22 10:55:51 2005
@@ -0,0 +1,482 @@
+/*
+ * 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.enhancer.meta.prop;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.InputStream;
+import java.io.FileInputStream;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataFatalError;
+import org.apache.jdo.impl.enhancer.meta.EnhancerMetaDataUserException;
+import org.apache.jdo.impl.enhancer.meta.ExtendedMetaData;
+import org.apache.jdo.impl.enhancer.meta.util.EnhancerMetaDataBaseModel;
+
+
+
+
+/**
+ * Provides the JDO meta information based on properties.
+ */
+public class EnhancerMetaDataPropertyImpl
+    extends EnhancerMetaDataBaseModel
+    implements ExtendedMetaData
+{
+    /**
+     * The model instance.
+     */
+    final private MetaDataProperties model;
+    
+    /**
+     * Creates an instance.
+     */
+    public EnhancerMetaDataPropertyImpl(PrintWriter out,
+                                        boolean verbose,
+                                        Properties properties)
+       throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        super(out, verbose);
+        affirm(properties != null);
+        model = new MetaDataProperties(properties);
+        initModel();
+        affirm(model != null);
+        printMessage(getI18N("enhancer.metadata.using_properties",
+                             "<unnamed>"));
+    }
+
+    /**
+     *  Creates an instance.
+     */
+    public EnhancerMetaDataPropertyImpl(PrintWriter out,
+                                        boolean verbose,
+                                        String fileName)
+       throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        super(out, verbose);
+        affirm(fileName != null);
+
+        InputStream stream = null;
+        try {
+            stream = new FileInputStream(fileName);
+            final Properties properties = new Properties();
+            properties.load(stream);
+            model = new MetaDataProperties(properties);
+            initModel();
+        } catch (IOException ex) {
+            final String msg
+                = getI18N("enhancer.metadata.io_error", ex.getMessage());
+            throw new EnhancerMetaDataFatalError(msg, ex);
+        } finally {
+            if (stream != null) {
+                try {
+                    stream.close();
+                } catch (IOException ex) {
+                    final String msg
+                        = getI18N("enhancer.metadata.io_error",
+                                  ex.getMessage());
+                    throw new EnhancerMetaDataFatalError(msg, ex);
+                }
+            }
+        }
+        affirm(model != null);
+        printMessage(getI18N("enhancer.metadata.using_properties", fileName));
+    }
+
+    // ----------------------------------------------------------------------
+    
+    /**
+     * Initializes the model.
+     */
+    private void initModel()
+    {
+        // we'd like to have all classes (and fields) parsed and
+        // cached in order to early report errors with the properties
+        final String[] classNames = model.getKnownClassNames();
+        affirm(classNames != null);
+        for (int i = classNames.length - 1; i >= 0; i--) {
+            final JDOClass clazz = getJDOClass(classNames[i]);
+            affirm(clazz != null);
+        }
+    }
+
+    /** 
+     * Returns the JVM-qualified name of the specified field's declaring
+     * class. The method first checks whether the class of the specified
+     * classPath (the JVM-qualified name) declares such a field. If yes,
+     * classPath is returned. Otherwise, it checks its superclasses. The
+     * method returns <code>null</code> for an unkown field.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @param fieldName the non-null name of the field
+     * @return the JVM-qualified name of the declararing class of the
+     * field, or <code>null</code> if there is no such field.
+     */
+    public String getDeclaringClass(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        String declaringClass = null;
+        JDOField field = getJDOField(classPath, fieldName);
+        if (field != null) {
+            // this class declares the filed => return classPath
+            declaringClass = classPath;
+        } else {
+            String superclass = getSuperClass(classPath);
+            if (superclass != null) {
+                declaringClass = getDeclaringClass(superclass, fieldName);
+            }
+        }
+        return declaringClass;
+    }
+
+    /**
+     * Declares a field to the JDO model passing its type information.
+     */
+    public void declareField(String classPath,
+                             String fieldName,
+                             String signature)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        affirm(isPersistenceCapableClass(classPath));
+        // nothing to be done: the properties-based model doesn't
+        // support default calculation of persistence modifiers
+    }
+    
+    /**
+     * Returns whether a class is known to be persistence-capable.
+     */
+    public boolean isPersistenceCapableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        return (clazz != null ? clazz.isPersistent() : false);
+    }
+
+    /**
+     * Returns whether a class implements java.io.Serializable.
+     * @param classPath the non-null JVM-qualified name of the class
+     * @return true if this class is serializable; otherwise false
+     */
+    public boolean isSerializableClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        return (clazz != null ? clazz.isSerializable() : false);
+    }
+    
+    /**
+     * Returns the name of the persistence-capable root class of a class.
+     */
+//@olsen: use the inherited method
+/*
+    public String getPersistenceCapableRootClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        String pcRootClass = null;
+        for (String clazz = classPath;
+             clazz != null;
+             clazz = getSuperClass(clazz))  {
+            if (isPersistenceCapableClass(clazz)) {
+                pcRootClass = clazz;
+            }
+        }
+        return pcRootClass;
+    }
+*/
+
+    /**
+     * Returns the name of the persistence-capable superclass of a class.
+     */
+    public String getPersistenceCapableSuperClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        for (String clazz = getSuperClass(classPath);
+             clazz != null;
+             clazz = getSuperClass(clazz))  {
+            if (isPersistenceCapableClass(clazz)) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
+    /**
+     *  Returns the superclass of a class.
+     */
+    public final String getSuperClass(String classname)
+    {
+        final JDOClass clazz = getJDOClass(classname);
+        return (clazz != null ? clazz.getSuperClassName() : null);
+    }
+
+    /**
+     * Returns the name of the key class of a persistence-capable class.
+     */
+    public String getKeyClass(String classPath)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        return (clazz != null ? clazz.getOidClassName() : null);
+    }
+
+    /**
+     * Returns whether a field of a class is known to be non-managed.
+     */
+    public boolean isKnownNonManagedField(String classPath,
+                                          String fieldName,
+                                          String fieldSig)
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        if (clazz == null) {
+            return true;
+        }
+        final JDOField field = getJDOField(clazz, fieldName);
+        return (field != null ? field.isKnownTransient() : false);
+    }    
+
+    /**
+     * Returns whether a field of a class is transient transactional
+     * or persistent.
+     */
+    public boolean isManagedField(String classPath, String fieldName)
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        return (field != null
+                ? (field.isPersistent() | field.isTransactional()) : false);
+    }
+
+    /**
+     * Returns whether a field of a class is known to be persistent.
+     */
+    public boolean isPersistentField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        return (field != null ? field.isPersistent() : false);
+    }
+
+    /**
+     * Returns whether a field of a class is known to be transactional.
+     */
+    public boolean isTransactionalField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        return (field != null ? field.isTransactional() : false);
+    }
+
+    /**
+     * Returns whether a field of a class is known to be Primary Key.
+     */
+    public boolean isKeyField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        return (field != null ? field.isKey() : false);
+    }
+
+    /**
+     * Returns whether a field of a class is known to be part of the
+     * Default Fetch Group.
+     */
+    public boolean isDefaultFetchGroupField(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOField field = getJDOField(classPath, fieldName);
+        return (field != null ? field.isInDefaultFetchGroup() : false);
+    }
+
+    /**
+     * Returns the unique field index of a declared, persistent field of a
+     * class.
+     */
+    public int getFieldNumber(String classPath, String fieldName)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final JDOClass clazz = getJDOClass(classPath);
+        return (clazz != null ? clazz.getIndexOfField(fieldName) : -1);
+    }
+
+    /**
+     * Returns an array of field names of all declared, persistent fields
+     * of a class.
+     */
+    public String[] getManagedFields(String classname)
+    {
+        final JDOClass clazz = getJDOClass(classname);
+        return (clazz != null ? clazz.getManagedFieldNames() : new String[]{});
+    }
+
+    /**
+     *  Not member of EnhancerMetaData Interface.
+     */
+    public final String[] getKnownClasses()
+    {
+        return model.getKnownClassNames();
+    }
+
+    /**
+     *  Gets all known fields of a class.
+     */
+    public final String[] getKnownFields(String classname)
+    {
+        final JDOClass clazz = getJDOClass(classname);
+        return (clazz != null ? clazz.getFieldNames() : new String[]{});
+    }
+
+
+    /**
+     *  Gets the access modifier of a class.
+     */
+    public final int getClassModifiers(String classname)
+    {
+        final JDOClass clazz = getJDOClass(classname);
+        return (clazz != null ? clazz.getModifiers() : 0);
+    }
+
+    /**
+     *  Gets the access modifier of a field.
+     */
+    public final int getFieldModifiers(String classname,
+                                       String fieldname)
+    {
+        final JDOField field = getJDOField(classname, fieldname);
+        return (field != null ? field.getModifiers() : 0);
+    }
+
+    public final String getFieldType(String classname,
+                                     String fieldname)
+    {
+        final JDOField field = getJDOField(classname, fieldname);
+        return (field != null ? field.getType() : null);
+    }
+
+    public final String[] getFieldType(String classname,
+                                        String[] fieldnames)
+    {
+        final int n = (fieldnames != null ? fieldnames.length : 0);
+        final String[] types = new String[n];
+        for (int i = 0; i < n; i++) {
+            types[i] = getFieldType(classname, fieldnames[i]);
+        }
+        return types;
+    }
+
+    public final int[] getFieldModifiers(String classname,
+                                          String[] fieldnames)
+        throws EnhancerMetaDataUserException, EnhancerMetaDataFatalError
+    {
+        final int n = (fieldnames != null ? fieldnames.length : 0);
+        final int[] mods = new int[n];
+        for (int i = 0; i < n; i++) {
+            mods[i] = getFieldModifiers(classname, fieldnames[i]);
+        }
+        return mods;
+    }
+
+    private final JDOClass getJDOClass(String classname)
+        throws EnhancerMetaDataUserException
+    {
+        return model.getJDOClass(classname);
+    }
+
+    private final JDOField getJDOField(JDOClass clazz,
+                                       String fieldname)
+    {
+        return (clazz != null ? clazz.getField(fieldname) : null);
+    }
+
+    private final JDOField getJDOField(String classname,
+                                       String fieldname)
+    {
+        final JDOClass clazz = getJDOClass(classname);
+        return getJDOField(clazz, fieldname);
+    }
+
+    // ----------------------------------------------------------------------
+    
+    public static void main(String[] argv)
+    {
+        final PrintWriter out = new PrintWriter(System.out, true);
+        
+        if (argv.length != 1) {
+            System.err.println("No property file specified.");
+            return;
+        }
+
+        final Properties p = new Properties();
+        try {
+            java.io.InputStream in =
+                new java.io.FileInputStream(new java.io.File(argv[0]));
+            p.load(in);
+            in.close();
+            out.println("PROPERTIES: " + p);
+            out.println("############");
+            MetaDataProperties props = new MetaDataProperties(p);
+        } catch (Throwable ex) {
+            ex.printStackTrace(System.err);
+        }
+
+        final EnhancerMetaDataPropertyImpl jdo
+            = new EnhancerMetaDataPropertyImpl(out, true, p);
+        final String[] classes = jdo.getKnownClasses();
+        for (int k = 0; k < classes.length; k++) {
+            final String clazz = classes[k];
+            out.println("CLAZZ: " + clazz);
+            out.println("\tpersistent: "
+                        + jdo.isPersistenceCapableClass(clazz));
+            out.println("\tpersistent root: "
+                        + jdo.isPersistenceCapableRootClass(clazz));
+            out.println("\tpersistent root class: "
+                        + jdo.getPersistenceCapableRootClass(clazz));
+            out.println("\tpersistent super class: "
+                        + jdo.getPersistenceCapableSuperClass(clazz));
+            out.println("\tkey class: "
+                        + jdo.getKeyClass(clazz));
+
+            final String[] fields = jdo.getKnownFields(clazz);
+            for (int j = 0; j < fields.length; j++) {
+                final String field = fields[j];
+                out.println("FIELD: " + field);
+                out.println("\tpersistent field: "
+                            + jdo.isPersistentField(clazz, field));
+                out.println("\tpk field: "
+                            + jdo.isKeyField(clazz, field));
+                out.println("\tdfg field: "
+                            + jdo.isDefaultFetchGroupField(clazz, field));
+                out.println("\tnumber: "
+                            + jdo.getFieldNumber(clazz, field));
+
+                final String[] names = jdo.getManagedFields(clazz);
+                final int n = (fields != null ? names.length : 0);
+                out.println("managed fields: number: " + n);
+                for (int i = 0; i < n; i++) {
+                    final String name = names[i];
+                    out.println(i + ": " + name +
+                                " number: "
+                                + jdo.getFieldNumber(clazz, name) +
+                                " pk: "
+                                + jdo.isKeyField(clazz, name) +
+                                " dfg: "
+                                + jdo.isDefaultFetchGroupField(clazz, name));
+                }
+            }
+        }
+    }
+}

Added: incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/JDOClass.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/JDOClass.java?rev=171351&view=auto
==============================================================================
--- incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/JDOClass.java (added)
+++ incubator/jdo/trunk/enhancer20/src/java/org/apache/jdo/impl/enhancer/meta/prop/JDOClass.java Sun May 22 10:55:51 2005
@@ -0,0 +1,349 @@
+/*
+ * 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.enhancer.meta.prop;
+
+import java.lang.reflect.Modifier;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Collections;
+import java.util.ArrayList;
+
+
+/**
+ * A class to hold all parsed attributes of a class.
+ */
+final class JDOClass
+{
+    /**
+     * The name of the class.
+     */
+    private final String name;
+    
+    /**
+     * The name of the superclass.
+     */
+    private String superClassName = null;
+    
+    /**
+     * The name of the oid class.
+     */
+    private String oidClassName = null;
+    
+    /**
+     * The access modifier of the class.
+     */
+    private int modifiers = Modifier.PUBLIC;
+    
+    /**
+     * The persistence modifier of the class.
+     */
+    private boolean isPersistent = true;
+    
+    /**
+     * Flag indicating whether this class is serializable.
+     */
+    private boolean isSerializable = true;
+    
+    /**
+     * A list of all parsed fields.
+     */
+    private final List fields = new ArrayList();
+    
+    /**
+     * The names of all managed fields this class.
+     */
+    private String[] managedFieldNames = null;
+    
+    /**
+     * The names of all fields this class.
+     */
+    private String[] fieldNames = null;
+    
+    /**
+     * Constructs a new object with the given name.
+     *
+     * @param  name  The name of the class.
+     */
+    JDOClass(String name)
+    {
+        this.name = name;
+    }
+    
+    /**
+     * Returns the name of the class.
+     *
+     * @return  The name of the class.
+     */
+    public String getName()
+    {
+        return name;
+    }
+    
+    /**
+     * Returns the modifiers of the class.
+     *
+     * @param modifiers  The modifiers of the class.
+     */
+    public void setModifiers(int modifiers)
+    {
+        this.modifiers = modifiers;
+    }
+    
+    /**
+     * Returns the modifiers of the class.
+     *
+     * @return  The modifiers of the class.
+     */
+    public int getModifiers()
+    {
+        return modifiers;
+    }
+    
+    /**
+     * Sets the superclassname. The given classname should have a canonical
+     * form (with dots). It is converted to the CM-similar notation
+     * (with slashes).
+     *
+     * @param  classname  The superclassname.
+     */
+    public void setSuperClassName(String classname)
+    {
+        superClassName = NameHelper.fromCanonicalClassName(classname);
+    }
+    
+    /**
+     * Returns the superclassname.
+     *
+     * @return  The superclassname.
+     */
+    public String getSuperClassName()
+    {
+        return superClassName;
+    }
+    
+    /**
+     * Sets the oid classname. The given classname should have a canonical
+     * form (with dots). It is converted to the CM-similar notation
+     * (with slashes).
+     *
+     * @param  classname  The oid classname
+     */
+    public void setOidClassName(String classname)
+    {
+        oidClassName = NameHelper.fromCanonicalClassName(classname);
+    }
+    
+    /**
+     * Returns the oid classname.
+     *
+     * @return  The oid classname
+     */
+    public String getOidClassName()
+    {
+        return oidClassName;
+    }
+    
+    /**
+     * Sets the persistence modifier of the class.
+     *
+     * @param persistent  the persistence modifer
+     * @see  #isPersistent
+     */
+    public void setPersistent(boolean persistent)
+    {
+        this.isPersistent = persistent;
+    }
+    
+    /**
+     * Returns whether the class is persistent.
+     *
+     * @return  true if persistent class.
+     * @see  #isPersistent
+     */
+    public boolean isPersistent()
+    {
+        return isPersistent;
+    }
+    
+    /**
+     * Returns whether the class is transient.
+     *
+     * @return  true if transient class.
+     * @see  #isPersistent
+     */
+    public boolean isTransient()
+    {
+        return !isPersistent();
+    }
+    
+    /**
+     * Returns whether the class is serializable.
+     *
+     * @return  true if serializable class.
+     * @see  #isSerializable
+     */
+    public boolean isSerializable()
+    {
+        return isSerializable;
+    }
+    
+    /**
+     * Sets the serializable flag of the class.
+     *
+     * @param serializable  the serializable flag
+     * @see  #isSerializable
+     */
+    public void setSerializable(boolean serializable)
+    {
+        this.isSerializable = serializable;
+    }
+    /**
+     * Adds a new field.
+     *
+     * @param  field  The new field.
+     */
+    public void addField(JDOField field)
+    {
+        fields.add(field);
+    }
+    
+    /**
+     * Returns the field with the given name.
+     *
+     * @param  name  The name of the requested field.
+     * @return  The field or <code>null</code> if not found.
+     */
+    public JDOField getField(String name)
+    {
+        int idx = getIndexOfField(name);
+        return (idx > -1  ? (JDOField) fields.get(idx)  :  null);
+    }
+    
+    /**
+     * Returns the index of the field with the given name.
+     *
+     * @param  name  The name of the field.
+     * @return  The index or <code>-1</code> if the field was not found.
+     */
+    public int getIndexOfField(String name)
+    {
+        for (int i = 0; i < fields.size(); i++) {
+            JDOField field = (JDOField)fields.get(i);
+            if (field.getName().equals(name)) {
+                return i;
+            }
+        }
+        
+        return -1;
+    }
+    
+    /**
+     * Returns all fields of the class.
+     *
+     * @return  The fields
+     */
+    public List getFields()
+    {
+        return fields;
+    }
+    
+    /**
+     * Returns the names of all fields of the class.
+     *
+     * @return  The field names
+     */
+    public String[] getFieldNames()
+    {
+        if (fieldNames == null) {
+            final int n = fields.size();
+            String[] fields = new String[n];
+            for (int i = 0; i < n; i++) {
+                fields[i] = ((JDOField)this.fields.get(i)).getName();
+            }
+            fieldNames = fields;
+        }
+        
+        return fieldNames;
+    }
+    
+    /**
+     * Sorts the fields of this class according to the names. This method
+     * should be called if all fields are added. It is necessary to
+     * establish an order on the fields.
+     *
+     */
+    final void sortFields()
+    {
+        Collections.sort(
+            fields,
+            new Comparator() {
+                    public int compare(Object f1, Object f2)
+                    {
+                        JDOField field1 = (JDOField)f1;
+                        JDOField field2 = (JDOField)f2;
+                        //if we dont have managed fields we dont care
+                        if (!(field1.isManaged() && field2.isManaged()))
+                        {
+                            return (field1.isManaged() ? -1 : 1);
+                        }
+                        return field1.getName().compareTo(field2.getName());
+                    }
+                });
+    }
+    
+    /**
+     * Returns the names of all managed fields this class.
+     *
+     * @return  The persistent fieldnames.
+     */
+    public String[] getManagedFieldNames()
+    {
+        if (managedFieldNames == null) {
+            final int n = fields.size();
+            List tmp = new ArrayList(n);
+            for (int i = 0; i < n; i++) {
+                JDOField field = (JDOField)fields.get(i);
+                if (field.isManaged()) {
+                    tmp.add(field.getName());
+                }
+            }
+            managedFieldNames
+                = (String[])tmp.toArray(new String[tmp.size()]);
+        }
+        
+        return managedFieldNames;
+    }
+    
+    /**
+     * Creates a string-representation for this object.
+     *
+     * @return  The string-representation of this object.
+     */
+    public String toString()
+    {
+        return ('<' + MetaDataProperties.PROPERTY_SUPER_CLASSNAME
+                + ':' + superClassName
+                + MetaDataProperties.PROPERTY_OID_CLASSNAME
+                + ':' + oidClassName
+                + ',' + MetaDataProperties.PROPERTY_ACCESS_MODIFIER
+                + ':' + Modifier.toString(modifiers)
+                + ',' + MetaDataProperties.PROPERTY_JDO_MODIFIER
+                + ':' + isPersistent
+                + ',' + "fields:" + fields + '>');
+    }
+}