db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r580056 [1/3] - in /db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet: ./ java/src/xdoclet/modules/ojb/ java/src/xdoclet/modules/ojb/constraints/ java/src/xdoclet/modules/ojb/model/ test/xdoclet/modules/ojb/tests/
Date Thu, 27 Sep 2007 15:08:41 GMT
Author: arminw
Date: Thu Sep 27 08:08:38 2007
New Revision: 580056

URL: http://svn.apache.org/viewvc?rev=580056&view=rev
Log:
- fix inheritance problems, now table per hierarchy and table per subclass created well
- fix problem with table per subclass inheritance and autoincrement, access attribute settings
- improve table per subclass declaration, now ojb.reference="super" declaration is allowed
- add new tests, modify tests (inheritance and autoincrement tests)

Added:
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/InheritanceTests.java
Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/OjbTagsHandler.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ClassDescriptorConstraints.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/FieldDescriptorConstraints.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ModelConstraints.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ReferenceDescriptorConstraints.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ClassDescriptorDef.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/FieldDescriptorDef.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ReferenceDescriptorDef.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/TorqueModelDef.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/ojb.xml
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/AnonymousReferenceTagTests.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/FieldTagAutoincrementAttributeTests.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/ModifyInheritedTagPrimarykeyAttributeTests.java
    db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/RunAllTests.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/OjbTagsHandler.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/OjbTagsHandler.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/OjbTagsHandler.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/OjbTagsHandler.java Thu Sep 27 08:08:38 2007
@@ -269,7 +269,7 @@
         }
         catch (ConstraintException ex)
         {
-            throw new XDocletException(ex.getMessage());
+            throw new XDocletException(ex, ex.getMessage());
         }
         return "";
     }
@@ -377,7 +377,6 @@
     /**
      * Processes an index descriptor tag.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -480,7 +479,6 @@
     /**
      * Processes an object cache tag.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -525,7 +523,6 @@
     /**
      * Processes a procedure tag.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -583,7 +580,6 @@
     /**
      * Processes a runtime procedure argument tag.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -851,22 +847,21 @@
      */
     public void processAnonymousReference(Properties attributes) throws XDocletException
     {
-        ReferenceDescriptorDef refDef = _curClassDef.getReference("super");
+        ReferenceDescriptorDef refDef = _curClassDef.getSuperReference();
         String                 attrName;
-
         if (refDef == null)
         {
             refDef = new ReferenceDescriptorDef("super");
             _curClassDef.addReference(refDef);
         }
-        refDef.setAnonymous();
-        LogHelper.debug(false, OjbTagsHandler.class, "processAnonymousReference", "  Processing anonymous reference");
-
         for (Enumeration attrNames = attributes.propertyNames(); attrNames.hasMoreElements(); )
         {
             attrName = (String)attrNames.nextElement();
             refDef.setProperty(attrName, attributes.getProperty(attrName));
         }
+        refDef.setAnonymous();
+        refDef.setTablePerSubclassInheritance();
+        LogHelper.debug(false, OjbTagsHandler.class, "processAnonymousReference", "  Processing anonymous reference");
     }
 
     /**
@@ -1081,7 +1076,6 @@
     /**
      * Addes the current member as a nested object.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -1136,7 +1130,6 @@
     /**
      * Processes a modification tag containing changes to properties of an inherited field/reference/collection.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"
@@ -1220,7 +1213,6 @@
     /**
      * Processes a modification tag containing changes to properties of an nested field/reference/collection.
      *
-     * @param template              The template
      * @param attributes            The attributes of the tag
      * @exception XDocletException  If an error occurs
      * @doc.tag                     type="content"

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ClassDescriptorConstraints.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ClassDescriptorConstraints.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ClassDescriptorConstraints.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ClassDescriptorConstraints.java Thu Sep 27 08:08:38 2007
@@ -27,6 +27,7 @@
 import xdoclet.modules.ojb.CommaListIterator;
 import xdoclet.modules.ojb.LogHelper;
 import xdoclet.modules.ojb.model.*;
+import org.apache.commons.lang.SystemUtils;
 
 /**
  * Checks constraints for class descriptors. Note that constraints may modify the class descriptor.
@@ -168,6 +169,16 @@
             }
             else if (processedClasses.containsKey(curExtent))
             {
+                canBeRemoved = true;
+            }
+            else if(curExtent.hasSuperReference())
+            {
+                String eol = SystemUtils.LINE_SEPARATOR;
+                String msg = new StringBuffer().append("Sub-class ").append(curExtent.getName())
+                        .append(" declare a 'super-reference' to class ").append(classDef.getName())
+                        .append(eol).append("If table per sub-class inheritance is used, it's not allowed to use the 'extent' attribute in class ")
+                        .append(classDef.getName()).append(eol).append("Automatic remove of the 'extent' is performed.").toString();
+                LogHelper.warn(true, ClassDescriptorConstraints.class, "checkExtents", msg);
                 canBeRemoved = true;
             }
             else

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/FieldDescriptorConstraints.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/FieldDescriptorConstraints.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/FieldDescriptorConstraints.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/FieldDescriptorConstraints.java Thu Sep 27 08:08:38 2007
@@ -5,6 +5,8 @@
 import xdoclet.modules.ojb.LogHelper;
 import xdoclet.modules.ojb.model.FieldDescriptorDef;
 import xdoclet.modules.ojb.model.PropertyHelper;
+import xdoclet.modules.ojb.model.ClassDescriptorDef;
+import org.apache.commons.lang.SystemUtils;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one 
@@ -96,6 +98,7 @@
         {
             checkReadonlyAccessForNativePKs(fieldDef, checkLevel);
         }
+        checkTablePerSubclassInheritance(fieldDef, checkLevel);
     }
 
     /**
@@ -410,8 +413,28 @@
             LogHelper.warn(true,
                            FieldDescriptorConstraints.class,
                            "checkAccess",
-                           "The field "+fieldDef.getName()+" in class "+fieldDef.getOwner().getName()+" is set to database auto-increment. Therefore the field's access is set to 'readonly'.");
+                           "The field '"+fieldDef.getName()+"' in class "+fieldDef.getOwner().getName() +
+                                   " is set to database auto-increment. Therefore the field's access is set to 'readonly'.");
             fieldDef.setProperty(PropertyHelper.OJB_PROPERTY_ACCESS, "readonly");
+        }
+    }
+
+
+    private void checkTablePerSubclassInheritance(FieldDescriptorDef fieldDef, String checkLevel)
+    {
+        ClassDescriptorDef cld = (ClassDescriptorDef) fieldDef.getOwner();
+        if(fieldDef.isPrimaryKey() && cld.hasSuperReference() && !cld.hasSuperReferenceViaForeignKey())
+        {
+            String eol = SystemUtils.LINE_SEPARATOR;
+            LogHelper.warn(true,
+                       FieldDescriptorConstraints.class,
+                       "checkTablePerSubclass",
+                       "The field '"+fieldDef.getName()+"' in class "+fieldDef.getOwner().getName()+
+                               " is a primary key field AND the foreign key to the super class." + eol +
+                               "If table per subclass inheritance is used with PK==FK the field's 'autoincrement' " +
+                               "attribute is set to 'false' and 'access' to 'readwrite'.");
+            fieldDef.setProperty(PropertyHelper.OJB_PROPERTY_AUTOINCREMENT, "none");
+            fieldDef.setProperty(PropertyHelper.OJB_PROPERTY_ACCESS, "readwrite");
         }
     }
 

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ModelConstraints.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ModelConstraints.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ModelConstraints.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ModelConstraints.java Thu Sep 27 08:08:38 2007
@@ -300,7 +300,7 @@
      * connected by super-references over the primary key fields does not change from 'ojb' to some
      * other value.
      * 
-     * @param classDef The root of the hierarchy
+     * @param modelDef The root of the hierarchy
      * @throws ConstraintException If there is autoincrement change in a hierarchy 
      */
     private void checkAutoIncrementedPKs(ModelDef modelDef) throws ConstraintException
@@ -343,7 +343,7 @@
                 ClassDescriptorDef subTypeDef = (ClassDescriptorDef)queue.get(0);
 
                 queue.remove(0);
-                if (subTypeDef.getReference("super") != null)
+                if (subTypeDef.hasSuperReference())
                 {
                     if (subTypeDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_GENERATE_REPOSITORY_INFO, true))
                     {
@@ -714,8 +714,8 @@
     private void checkReferenceForeignkeys(ModelDef modelDef, ReferenceDescriptorDef refDef) throws ConstraintException
     {
         String foreignkey = refDef.getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY);
-
-        if ((foreignkey == null) || (foreignkey.length() == 0))
+        if ((foreignkey == null || foreignkey.length() == 0)
+                && !refDef.isTablePerSubclass())
         {
             throw new ConstraintException("The reference "+refDef.getName()+" in class "+refDef.getOwner().getName()+" has no foreignkeys");
         }
@@ -771,17 +771,27 @@
             primFields = referencedClass.getPrimaryKeys();
             if (primFields.size() != keyFields.size())
             {
+                if(refDef.isTablePerSubclass() && keyFields.isEmpty())
+                {
+                    // if table per subclass inheritance is used (name="super"), OJB can handle the
+                    // FK by it's own using the PK of the super class. So no FK declaration needed
+                    // in the reference mapping
+                    continue;
+                }
                 throw new ConstraintException("The number of foreignkeys ("+keyFields.size()+") of the reference "+refDef.getName()+" in class "+refDef.getOwner().getName()+" doesn't match the number of primarykeys ("+primFields.size()+") of the referenced class (or its subclass) "+referencedClass.getName());
             }
-            for (int idx = 0; idx < primFields.size(); idx++)
+            else
             {
-                keyField  = (FieldDescriptorDef)keyFields.get(idx);
-                primField = (FieldDescriptorDef)primFields.get(idx);
-                primType  = primField.getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
-                keyType   = keyField.getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
-                if (!primType.equals(keyType))
+                for (int idx = 0; idx < primFields.size(); idx++)
                 {
-                    throw new ConstraintException("The jdbc-type of foreignkey "+keyField.getName()+" of the reference "+refDef.getName()+" in class "+refDef.getOwner().getName()+" doesn't match the jdbc-type of the corresponding primarykey "+primField.getName()+" of the referenced class (or its subclass) "+referencedClass.getName());
+                    keyField  = (FieldDescriptorDef)keyFields.get(idx);
+                    primField = (FieldDescriptorDef)primFields.get(idx);
+                    primType  = primField.getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
+                    keyType   = keyField.getProperty(PropertyHelper.OJB_PROPERTY_JDBC_TYPE);
+                    if (!primType.equals(keyType))
+                    {
+                        throw new ConstraintException("The jdbc-type of foreignkey "+keyField.getName()+" of the reference "+refDef.getName()+" in class "+refDef.getOwner().getName()+" doesn't match the jdbc-type of the corresponding primarykey "+primField.getName()+" of the referenced class (or its subclass) "+referencedClass.getName());
+                    }
                 }
             }
         }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ReferenceDescriptorConstraints.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ReferenceDescriptorConstraints.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ReferenceDescriptorConstraints.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/constraints/ReferenceDescriptorConstraints.java Thu Sep 27 08:08:38 2007
@@ -82,7 +82,7 @@
 
         if (targetClassDef == null)
         {
-            throw new ConstraintException("The class "+targetClassName+" referenced by "+refDef.getName()+" in class "+ownerClassDef.getName()+" is unknown or not persistent");
+            throw new ConstraintException("The class '"+targetClassName+"' referenced by '"+refDef.getName()+"' in class "+ownerClassDef.getName()+" is unknown or not persistent");
         }
         if (!targetClassDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_OJB_PERSISTENT, false))
         {
@@ -94,7 +94,9 @@
             try
             {
                 InheritanceHelper helper = new InheritanceHelper();
-
+//System.out.println("## " + refDef);
+//System.out.println("## a: " + refDef.isAnonymous());
+//System.out.println("## t: " + refDef.isTablePerSubclass());
                 if (refDef.isAnonymous())
                 {
                     // anonymous reference: class must be a baseclass of the owner class

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ClassDescriptorDef.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ClassDescriptorDef.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ClassDescriptorDef.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ClassDescriptorDef.java Thu Sep 27 08:08:38 2007
@@ -26,6 +26,7 @@
 import xdoclet.modules.ojb.LogHelper;
 import xdoclet.modules.ojb.constraints.*;
 import xjavadoc.XClass;
+import org.apache.commons.lang.SystemUtils;
 
 /**
  * Definition of a class for the ojb repository file.
@@ -118,7 +119,7 @@
     }
     
     /**
-     * Processes theis class (ensures that all base types are processed, copies their features to this class, and applies
+     * Processes this class (ensures that all base types are processed, copies their features to this class, and applies
      * modifications (removes ignored features, changes declarations).
      * 
      * @throws ConstraintException If a constraint has been violated 
@@ -152,61 +153,57 @@
         CollectionDescriptorDef newCollDef;
         
         // adding base features
-        if (getBooleanProperty(PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED, true))
+        boolean includeInherited = getBooleanProperty(PropertyHelper.OJB_PROPERTY_INCLUDE_INHERITED, true);
+        if (includeInherited)
         {
             ArrayList baseTypes = new ArrayList();
             DefBase   featureDef;
-            
             addRelevantBaseTypes(this, baseTypes);
-            for (Iterator it = baseTypes.iterator(); it.hasNext();)
-            {
-                cloneInheritedFeatures((ClassDescriptorDef)it.next(), newFields, newReferences, newCollections);
-            }
 
-            for (Iterator it = newFields.iterator(); it.hasNext();)
+            if(hasSuperReference())
             {
-                newFieldDef = (FieldDescriptorDef)it.next();
-                featureDef  = getFeature(newFieldDef.getName());
-                if (featureDef != null)
-                {    
-                    if (!getBooleanProperty(PropertyHelper.OJB_PROPERTY_IGNORE, false))
-                    {
-                        // we have the implicit constraint that an anonymous field cannot redefine/be redefined
-                        // except if it is ignored
-                        if ("anonymous".equals(featureDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS)))
-                        {
-                            throw new ConstraintException("The anonymous field "+featureDef.getName()+" in class "+getName()+" overrides an inherited field");
-                        }
-                        if ("anonymous".equals(newFieldDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS)))
-                        {
-                            throw new ConstraintException("The inherited anonymous field "+newFieldDef.getName()+" is overriden in class "+getName());
-                        }
-                    }
-                    LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited field "+newFieldDef.getName());
-                    it.remove();
+                String eol = SystemUtils.LINE_SEPARATOR;
+                String msg = new StringBuffer().append("This class ").append(getName())
+                        .append(" is a sub-class and declare a 'super-reference' to its super class").append(eol)
+                        .append("If table per sub-class inheritance is used, it's not allowed to include non-primary key inherited fields in the sub-class.")
+                        .append(eol).append("Therefore inherited non-primary key fields will not be included/will be ignored.").toString();
+                LogHelper.warn(true, ClassDescriptorConstraints.class, "process", msg);
+                for (Iterator it = baseTypes.iterator(); it.hasNext();)
+                {
+                    cloneInheritedPrimaryKeyFields((ClassDescriptorDef)it.next(), newFields);
                 }
+                removeRedefinedFields(newFields);
             }
-            for (Iterator it = newReferences.iterator(); it.hasNext();)
+            else
             {
-                newRefDef = (ReferenceDescriptorDef)it.next();
-                if ("super".equals(newRefDef.getName()))
+                for (Iterator it = baseTypes.iterator(); it.hasNext();)
                 {
-                    // we don't inherit super-references
-                    it.remove();
+                    cloneInheritedFeatures((ClassDescriptorDef)it.next(), newFields, newReferences, newCollections);
                 }
-                else if (hasFeature(newRefDef.getName()))
+                removeRedefinedFields(newFields);
+
+                for (Iterator it = newReferences.iterator(); it.hasNext();)
                 {
-                    LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited reference "+newRefDef.getName());
-                    it.remove();
+                    newRefDef = (ReferenceDescriptorDef)it.next();
+                    if (newRefDef.isTablePerSubclass())
+                    {
+                        // we don't inherit super-references
+                        it.remove();
+                    }
+                    else if (hasFeature(newRefDef.getName()))
+                    {
+                        LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited reference "+newRefDef.getName());
+                        it.remove();
+                    }
                 }
-            }
-            for (Iterator it = newCollections.iterator(); it.hasNext();)
-            {
-                newCollDef = (CollectionDescriptorDef)it.next();
-                if (hasFeature(newCollDef.getName()))
+                for (Iterator it = newCollections.iterator(); it.hasNext();)
                 {
-                    LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited collection "+newCollDef.getName());
-                    it.remove();
+                    newCollDef = (CollectionDescriptorDef)it.next();
+                    if (hasFeature(newCollDef.getName()))
+                    {
+                        LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited collection "+newCollDef.getName());
+                        it.remove();
+                    }
                 }
             }
         }
@@ -215,13 +212,42 @@
         {
             cloneNestedFeatures((NestedDef)it.next(), newFields, newReferences, newCollections);
         }
-        _fields.addAll(0, newFields);
-        _references.addAll(0, newReferences);
-        _collections.addAll(0, newCollections);
+        if(!newFields.isEmpty()) _fields.addAll(0, newFields);
+        if(!newReferences.isEmpty()) _references.addAll(0, newReferences);
+        if(!newCollections.isEmpty())_collections.addAll(0, newCollections);
         sortFields();
         _hasBeenProcessed = true;
     }
 
+    private void removeRedefinedFields(List newFields) throws ConstraintException
+    {
+        FieldDescriptorDef newFieldDef;
+        DefBase featureDef;
+        for (Iterator it = newFields.iterator(); it.hasNext();)
+        {
+            newFieldDef = (FieldDescriptorDef)it.next();
+            featureDef  = getFeature(newFieldDef.getName());
+            if (featureDef != null)
+            {
+                if (!getBooleanProperty(PropertyHelper.OJB_PROPERTY_IGNORE, false))
+                {
+                    // we have the implicit constraint that an anonymous field cannot redefine/be redefined
+                    // except if it is ignored
+                    if ("anonymous".equals(featureDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS)))
+                    {
+                        throw new ConstraintException("The anonymous field "+featureDef.getName()+" in class "+getName()+" overrides an inherited field");
+                    }
+                    if ("anonymous".equals(newFieldDef.getProperty(PropertyHelper.OJB_PROPERTY_ACCESS)))
+                    {
+                        throw new ConstraintException("The inherited anonymous field "+newFieldDef.getName()+" is overriden in class "+getName());
+                    }
+                }
+                LogHelper.warn(true, ClassDescriptorDef.class, "process", "Class "+getName()+" redefines the inherited field "+newFieldDef.getName());
+                it.remove();
+            }
+        }
+    }
+
     /**
      * Sorts the fields.
      */
@@ -442,6 +468,34 @@
     }
 
     /**
+     * Clones the primary key fields of the given base class (using modifications if available)
+     * and puts them into the given lists.
+     *
+     * @param baseDef        The base class descriptor
+     * @param newFields      Recieves the field copies
+     */
+    private void cloneInheritedPrimaryKeyFields(ClassDescriptorDef baseDef, ArrayList newFields)
+    {
+        FieldDescriptorDef      copyFieldDef;
+
+        // note that we also copy features with the ignore-property set to true
+        // they will be ignored later on
+        for (Iterator fieldIt = baseDef.getFields(); fieldIt.hasNext();)
+        {
+            FieldDescriptorDef fld = (FieldDescriptorDef)fieldIt.next();
+            if(fld.isPrimaryKey())
+            {
+                copyFieldDef = cloneField(fld, null);
+                if (!contains(newFields, copyFieldDef))
+                {
+                    copyFieldDef.setInherited();
+                    newFields.add(copyFieldDef);
+                }
+            }
+        }
+    }
+
+    /**
      * Clones the given field.
      * 
      * @param fieldDef The field descriptor
@@ -596,9 +650,22 @@
      */
     public void addExtentClass(ClassDescriptorDef subType)
     {
-        if (!_extents.contains(subType))
+        ReferenceDescriptorDef subClassSuperRef = subType.getSuperReference();
+        if(subClassSuperRef != null && subClassSuperRef.isTablePerSubclass())
         {
-            _extents.add(subType);
+            String eol = SystemUtils.LINE_SEPARATOR;
+            String msg = new StringBuffer().append("Sub-class ").append(subType.getName())
+                    .append(" declare a 'super-reference' to class ").append(getName()).append(eol)
+                    .append("If table per sub-class inheritance is used, it's not allowed to declare an 'extent' attribute in class ")
+                    .append(getName()).append(".").append(eol).append("Add of the 'extent' class will be ignored.").toString();
+            LogHelper.warn(true, ClassDescriptorConstraints.class, "addExtentClass", msg);
+        }
+        else
+        {
+            if (!_extents.contains(subType))
+            {
+                _extents.add(subType);
+            }
         }
     }
 
@@ -1072,6 +1139,70 @@
     public Properties getModification(String name)
     {
         return (Properties)_modifications.get(name);
+    }
+
+
+    /**
+     * Returns the 'super'-reference descriptor (table per sub-class inheritance)
+     * or <em>null</em>.
+     * @return The 'super'-reference descriptor if declared.
+     */
+    public ReferenceDescriptorDef getSuperReference()
+    {
+        return getReference("super");
+    }
+
+    /**
+     * Returns <em>true</em> if this class has a 'super'-reference descriptor to
+     * its super-class (table per subclass inheritance is used).
+     * @return
+     */
+    public boolean hasSuperReference()
+    {
+        ReferenceDescriptorDef ref = getReference("super");
+        return ref != null;
+    }
+
+    /**
+     * Returns <em>true</em> if this class has a 'super'-reference descriptor (table per subclass
+     * inheritance is used) to its super-class AND use a separate foreign key field as reference
+     * to the super-class (instead of using the PK field as FK).
+     * @return whether or not table per subclass inheritance via separate FK field is used.
+     */
+    public boolean hasSuperReferenceViaForeignKey()
+    {
+        ReferenceDescriptorDef ref = getSuperReference();
+        boolean result = false;
+        if(ref != null)
+        {
+            CommaListIterator it = new CommaListIterator(ref.getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY));
+            while(it.hasNext())
+            {
+                String fk = (String) it.next();
+                if(!isPrimaryKey(fk))
+                {
+                    result = true;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    boolean isPrimaryKey(String fieldName)
+    {
+        boolean result = false;
+        List pks = getPrimaryKeys();
+        for(int i = 0; i < pks.size(); i++)
+        {
+            FieldDescriptorDef fld = (FieldDescriptorDef) pks.get(i);
+            if(fieldName.equals(fld.getName()))
+            {
+                result = true;
+                break;
+            }
+        }
+        return result;
     }
 
     /* (non-Javadoc)

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/FieldDescriptorDef.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/FieldDescriptorDef.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/FieldDescriptorDef.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/FieldDescriptorDef.java Thu Sep 27 08:08:38 2007
@@ -108,4 +108,9 @@
         }
         return constraint;
     }
+
+    public boolean isPrimaryKey()
+    {
+        return getBooleanProperty(PropertyHelper.OJB_PROPERTY_PRIMARYKEY, false);
+    }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ReferenceDescriptorDef.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ReferenceDescriptorDef.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ReferenceDescriptorDef.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/ReferenceDescriptorDef.java Thu Sep 27 08:08:38 2007
@@ -1,5 +1,11 @@
 package xdoclet.modules.ojb.model;
 
+import java.util.List;
+
+import xdoclet.modules.ojb.LogHelper;
+import org.apache.commons.lang.ClassUtils;
+import xjavadoc.XClass;
+
 /*
  * Licensed to the Apache Software Foundation (ASF) under one 
  * or more contributor license agreements.  See the NOTICE file 
@@ -30,6 +36,7 @@
 {
     /** Whether this is an anonymous reference */
     private boolean _isAnonymous = false;
+    private boolean _isTablePerSubclassInheritance = false;
 
     /**
      * Creates a new reference descriptor object.
@@ -50,6 +57,14 @@
     public ReferenceDescriptorDef(ReferenceDescriptorDef src, String prefix)
     {
         super(src, prefix);
+        if(src.isAnonymous())
+        {
+            this.setAnonymous();
+        }
+        if(src.isTablePerSubclass())
+        {
+            this.setTablePerSubclassInheritance();
+        }
     }
 
     /**
@@ -68,5 +83,80 @@
     public boolean isAnonymous()
     {
         return _isAnonymous;
+    }
+
+    /**
+     * Returns whether this reference mark table per subclass inheritance.
+     *
+     * @return <code>true</code> if it is table per subclass inheritance
+     */
+    public boolean isTablePerSubclass()
+    {
+        return _isTablePerSubclassInheritance;
+    }
+
+    /**
+     * Declares this reference to be a 'super'-reference using table per subclass inheritance.
+     */
+    public void setTablePerSubclassInheritance()
+    {
+        this._isTablePerSubclassInheritance = true;
+        String refClass = getProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF);
+        /*
+        If the super-reference descriptor doesn't specify the full qualified super-class
+        name, instead use the key word "super" resolve the full qualified name of the
+        super-class and the "class-ref" property
+        */
+        if("super".equals(refClass))
+        {
+            ClassDescriptorDef classDef = (ClassDescriptorDef) this.getOwner();
+            if(classDef == null)
+            {
+                LogHelper.warn(true, ReferenceDescriptorDef.class, "setTablePerSubclassInheritance()",
+                        "Can't resolve owner class to detect super-reference class");
+            }
+            else
+            {
+                try
+                {
+                    String superClassStr = null;
+                    ModelDef model = (ModelDef) classDef.getOwner();
+                    if(model != null)
+                    {
+                        XClass superXClass = classDef.getOriginalClass().getSuperclass();
+                        if(superXClass != null)
+                        {
+                            ClassDescriptorDef superDef = model.getClass(superXClass.getQualifiedName());
+                            superClassStr = superDef.getQualifiedName();
+                        }
+                    }
+                    if(superClassStr == null)
+                    {
+                        Class ownerClass = ClassUtils.getClass(classDef.getQualifiedName());
+                        List superClasses = ClassUtils.getAllSuperclasses(ownerClass);
+                        if(!superClasses.isEmpty())
+                        {
+                            Class superClass = (Class) superClasses.get(0);
+                            superClassStr = superClass.getName();
+                        }
+                    }
+                    if(superClassStr != null)
+                    {
+                        // now set the resolved class name of the super-class
+                        setProperty(PropertyHelper.OJB_PROPERTY_CLASS_REF, superClassStr);
+                        LogHelper.debug(true, ReferenceDescriptorDef.class, "setTablePerSubclassInheritance()",
+                        "Successfully resolved super-reference class '" + superClassStr
+                                + "' for class '" + classDef.getQualifiedName() + "'");
+                    }
+
+                }
+                catch(ClassNotFoundException e)
+                {
+                    LogHelper.warn(true, ReferenceDescriptorDef.class, "setTablePerSubclassInheritance()",
+                        "Can't resolve super class for super-reference defined in class '"
+                                + classDef.getQualifiedName() + "'");
+                }
+            }
+        }
     }
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/TorqueModelDef.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/TorqueModelDef.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/TorqueModelDef.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/java/src/xdoclet/modules/ojb/model/TorqueModelDef.java Thu Sep 27 08:08:38 2007
@@ -234,6 +234,14 @@
             String        name         = refDef.getName();
             ArrayList     localFields  = ownerClassDef.getFields(refDef.getProperty(PropertyHelper.OJB_PROPERTY_FOREIGNKEY));
             ArrayList     remoteFields = referencedClassDef.getPrimaryKeys();
+            /*
+            if table per subclass inheritance is used and the FK field in the super-reference is not specified
+            assume that the PK of the subclass is the FK to the super-class.
+             */
+            if(localFields.isEmpty() && ownerClassDef.hasSuperReference() && !ownerClassDef.hasSuperReferenceViaForeignKey())
+            {
+                localFields = ownerClassDef.getPrimaryKeys();
+            }
             ForeignkeyDef fkDef        = tableDef.addForeignkey(name, tableName, getColumns(localFields), getColumns(remoteFields));
 
             copyPropertyIfDefined(refDef,
@@ -503,7 +511,7 @@
             {
                 curClassDef = (ClassDescriptorDef)it.next();
 
-                if (curClassDef.getReference("super") == null)
+                if (!curClassDef.hasSuperReference())
                 {
                     queue.add(curClassDef);
                 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/ojb.xml
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/ojb.xml?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/ojb.xml (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/ojb.xml Thu Sep 27 08:08:38 2007
@@ -21,9 +21,12 @@
 */
 -->
 
+<!-- @version $Id$ -->
+<!-- OJB's Doclipse definition file. See http://beust.com/doclipse/ -->
 
 <doclipse>
     <description>Tags for the OJB XDoclet module</description>
+
     <tag name="@ojb.class"
          target="class"
          doc="Declares that this class is persistent via OJB">
@@ -50,8 +53,17 @@
         <attribute name="initialization-method"
                    doc="This method will be called whenever a new instance of this class has been created by OJB"/>
         <attribute name="isolation-level"
-                   allowed="read-uncommitted read-committed repeatable-read serializable optimistic"
+                   allowed="read-uncommitted read-committed repeatable-read serializable optimistic none"
                    doc="For ODMG: the transactional isolation level; default is 'read-uncommitted'"/>
+        <attribute name="state-detection"
+                   allowed="on off inherit"
+                   doc="The state-detection attribute is used by API's supporting automatic state detection of
+                   persistence capable objects (automatic detection of changed object fields - e.g. like
+                   the ODMG implementation). The attribute indicate whether or not the object state detection
+                   is enabled for this class or if it's inherited from a higher level entity."/>
+        <attribute name="field-class"
+                   doc="The field-class attribute can be used to override the PersistentField implementation class.
+                   OJB's shortcut name feature is supported."/>
         <attribute name="proxy"
                    doc="Determines whether proxies are used for instances of this class; can be 'dynamic' for automatic dynamic proxies, or the fully qualified class name of the proxy class to use"/>
         <attribute name="proxy-prefetching-limit"
@@ -64,12 +76,16 @@
         <attribute name="table"
                    doc="The database table onto which this class is mapped"/>
     </tag>
+
+
     <tag name="@ojb.extent-class"
          target="class"
          doc="Specifies an extent, a subclass with an @ojb.class tag. This tag is only evaluated if the value of the determine-extents attribute of this class is set to 'false'">
         <attribute name="class-ref"
                    doc="The fully qualified name of the subclass"/>
     </tag>
+
+
     <tag name="@ojb.modify-inherited"
          target="class"
          doc="Use this tag to modify attributes of inherited fields/references/collections">
@@ -158,6 +174,18 @@
         <attribute name="update-lock"
                    allowed="true false"
                    doc="For fields: modifies the 'update-lock' attribute of the inherited feature"/>
+        <attribute name="isolation-level"
+                   allowed="read-uncommitted read-committed repeatable-read serializable optimistic none"
+                   doc="For ODMG: the transactional isolation level; default is 'read-uncommitted'"/>
+        <attribute name="state-detection"
+                   allowed="on off inherit"
+                   doc="The state-detection attribute is used by API's supporting automatic state detection of
+                   persistence capable objects (automatic detection of changed object fields - e.g. like
+                   the ODMG implementation). The attribute indicate whether or not the object state detection
+                   is enabled for this class or if it's inherited from a higher level entity."/>
+        <attribute name="field-class"
+                   doc="The field-class attribute can be used to override the PersistentField implementation class.
+                   OJB's shortcut name feature is supported."/>
     </tag>
     <tag name="@ojb.object-cache"
          target="class"
@@ -317,6 +345,15 @@
         <attribute name="update-lock"
                    allowed="true false"
                    doc="If locking is set to 'true' then this attribute specifies whether OJB will update this locking field or the database. Default is 'true' meaning that OJB does the update"/>
+        <attribute name="state-detection"
+                   allowed="on off inherit"
+                   doc="The state-detection attribute is used by API's supporting automatic state detection of
+                   persistence capable objects (automatic detection of changed object fields - e.g. like
+                   the ODMG implementation). The attribute indicate whether or not the object state detection
+                   is enabled for this class or if it's inherited from a higher level entity."/>
+        <attribute name="field-class"
+                   doc="The field-class attribute can be used to override the PersistentField implementation class.
+                   OJB's shortcut name feature is supported."/>
     </tag>
     <tag name="@ojb.reference"
          target="class method field"
@@ -422,7 +459,7 @@
         <attribute name="class-ref"
                    doc="For references: modifies the 'class-ref' attribute of the nested feature"/>
         <attribute name="collection-class"
-                   doc="For collections: modifies the 'collection-class' attribute of the nestedfeature"/>
+                   doc="For collections: modifies the 'collection-class' attribute of the nested feature"/>
         <attribute name="column"
                    doc="For fields: modifies the 'column' attribute of the nested feature"/>
         <attribute name="conversion"
@@ -487,5 +524,16 @@
         <attribute name="update-lock"
                    allowed="true false"
                    doc="For fields: modifies the 'update-lock' attribute of the nested feature"/>
+        <attribute name="state-detection"
+                   allowed="on off inherit"
+                   doc="For fields: modifies the 'state-detection' attribute of the nested feature.
+                   The state-detection attribute is used by API's supporting automatic state detection of
+                   persistence capable objects (automatic detection of changed object fields - e.g. like
+                   the ODMG implementation). The attribute indicate whether or not the object state detection
+                   is enabled for this class or if it's inherited from a higher level entity."/>
+        <attribute name="field-class"
+                   doc="For fields: modifies the 'field-class' attribute of the nested feature.
+                   The field-class attribute can be used to override the PersistentField implementation class.
+                   OJB's shortcut name feature is supported."/>
     </tag>
 </doclipse>

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/AnonymousReferenceTagTests.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/AnonymousReferenceTagTests.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/AnonymousReferenceTagTests.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/AnonymousReferenceTagTests.java Thu Sep 27 08:08:38 2007
@@ -64,12 +64,13 @@
             "/** @ojb.class */\n"+
             "public class C extends B {}\n");
 
+        String result = runOjbXDoclet(OJB_DEST_FILE);
+        System.out.println("##" + result);
         assertEqualsOjbDescriptorFile(
             "<class-descriptor\n"+
             "    class=\"test.A\"\n"+
             "    table=\"A\"\n"+
             ">\n"+
-            "    <extent-class class-ref=\"test.B\"/>\n"+
             "    <field-descriptor\n"+
             "        name=\"id\"\n"+
             "        column=\"id\"\n"+
@@ -126,7 +127,7 @@
             "    >\n"+
             "    </field-descriptor>\n"+
             "</class-descriptor>",
-            runOjbXDoclet(OJB_DEST_FILE));
+            result);
         assertEqualsTorqueSchemaFile(
             "<database name=\"ojbtest\">\n"+
             "    <table name=\"A\">\n"+

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/FieldTagAutoincrementAttributeTests.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/FieldTagAutoincrementAttributeTests.java?rev=580056&r1=580055&r2=580056&view=diff
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/FieldTagAutoincrementAttributeTests.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/xdoclet/test/xdoclet/modules/ojb/tests/FieldTagAutoincrementAttributeTests.java Thu Sep 27 08:08:38 2007
@@ -189,6 +189,8 @@
             "public class A {\n"+
             "/** @ojb.field autoincrement=\"ojb\" */\n"+
             "  private int attr;\n"+
+            "  /** @ojb.field length=\"128\" */\n"+
+            "  private String name;\n"+
             "}\n");
         addClass(
             "test.B",
@@ -213,6 +215,13 @@
             "        autoincrement=\"true\"\n"+
             "    >\n"+
             "    </field-descriptor>\n"+
+            "    <field-descriptor\n"+
+            "        name=\"name\"\n"+
+            "        column=\"name\"\n"+
+            "        jdbc-type=\"VARCHAR\"\n"+
+            "        length=\"128\"\n"+
+            "    >\n"+
+            "    </field-descriptor>\n"+
             "</class-descriptor>\n"+
             "<class-descriptor\n"+
             "    class=\"test.C\"\n"+
@@ -225,6 +234,13 @@
             "        autoincrement=\"true\"\n"+
             "    >\n"+
             "    </field-descriptor>\n"+
+            "    <field-descriptor\n"+
+            "        name=\"name\"\n"+
+            "        column=\"name\"\n"+
+            "        jdbc-type=\"VARCHAR\"\n"+
+            "        length=\"128\"\n"+
+            "    >\n"+
+            "    </field-descriptor>\n"+
             "</class-descriptor>",
             runOjbXDoclet(OJB_DEST_FILE));
         assertEqualsTorqueSchemaFile(
@@ -234,11 +250,21 @@
             "                javaName=\"attr\"\n"+
             "                type=\"INTEGER\"\n"+
             "        />\n"+
+            "        <column name=\"name\"\n"+
+            "                javaName=\"name\"\n"+
+            "                type=\"VARCHAR\"\n"+
+            "                size=\"128\"\n"+
+            "        />\n"+
             "    </table>\n"+
             "    <table name=\"C\">\n"+
             "        <column name=\"attr\"\n"+
             "                javaName=\"attr\"\n"+
             "                type=\"INTEGER\"\n"+
+            "        />\n"+
+            "        <column name=\"name\"\n"+
+            "                javaName=\"name\"\n"+
+            "                type=\"VARCHAR\"\n"+
+            "                size=\"128\"\n"+
             "        />\n"+
             "    </table>\n"+
             "</database>",



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message