You are viewing a plain text version of this content. The canonical link for it is here.
Posted to graffito-commits@incubator.apache.org by ap...@apache.org on 2006/02/15 01:45:56 UTC

svn commit: r377917 - in /incubator/graffito/trunk/jcr/jcr-mapping: ./ src/java/org/apache/portals/graffito/jcr/mapper/impl/ src/java/org/apache/portals/graffito/jcr/mapper/model/ src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/

Author: apopescu
Date: Tue Feb 14 17:45:54 2006
New Revision: 377917

URL: http://svn.apache.org/viewcvs?rev=377917&view=rev
Log:
+ inheritance persistence/fetching
+ node type verification against updates/fetching

Modified:
    incubator/graffito/trunk/jcr/jcr-mapping/CHANGES
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterDescriptorReader.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterMapperImpl.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/ClassDescriptor.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/MappingDescriptor.java
    incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/ObjectConverterImpl.java

Modified: incubator/graffito/trunk/jcr/jcr-mapping/CHANGES
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/CHANGES?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/CHANGES (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/CHANGES Tue Feb 14 17:45:54 2006
@@ -1,7 +1,11 @@
+20060215
+support for persisting/fetching inheritance
+
 20060214
 basic support for inheritance
 
 = TODO =
++ Add tests for persistence/fetching of inheritting objects
 + Add exception tests
 + Review query/filters
 

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterDescriptorReader.java
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterDescriptorReader.java?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterDescriptorReader.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterDescriptorReader.java Tue Feb 14 17:45:54 2006
@@ -70,7 +70,7 @@
 			digester.addSetProperties("graffito-jcr/class-descriptor", "className", "className");
 			digester.addSetProperties("graffito-jcr/class-descriptor", "jcrNodeType", "jcrNodeType");
             digester.addSetProperties("graffito-jcr/class-descriptor", "jcrSuperTypes", "jcrSuperTypes");
-            digester.addSetProperties("graffito-jcr/class-descriptor", "jcrMixinTypes", "jcrMixinTypesList");
+            digester.addSetProperties("graffito-jcr/class-descriptor", "jcrMixinTypes", "jcrMixinTypes");
             digester.addSetProperties("graffito-jcr/class-descriptor", "extends", "superClass");
             digester.addSetProperties("graffito-jcr/class-descriptor", "abstract", "abstract");
             digester.addSetProperties("graffito-jcr/class-descriptor", "discriminatorValue", "discriminatorValue");

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterMapperImpl.java
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterMapperImpl.java?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterMapperImpl.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/impl/DigesterMapperImpl.java Tue Feb 14 17:45:54 2006
@@ -18,9 +18,10 @@
 
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.portals.graffito.jcr.exception.InitMapperException;
@@ -146,7 +147,14 @@
             }
         }
         if (null != this.mappingDescriptor) {
-            solveReferences();
+            List errors = new ArrayList();
+            solveReferences(errors);
+            validateDescriptors(errors);
+
+            if (!errors.isEmpty()) {
+                throw new InitMapperException("Mapping files contain errors."
+                        + getErrorMessage(errors));
+            }
         }
         else {
             throw new InitMapperException("No mappings were provided");
@@ -155,17 +163,43 @@
         return this;
     }
 
-    private void solveReferences() {
-        for(Iterator it = this.mappingDescriptor.getClassDescriptors().keySet().iterator(); it.hasNext(); ) {
+    private String getErrorMessage(List errors) {
+        final String lineSep = System.getProperty("line.separator");
+        StringBuffer buf = new StringBuffer();
+        for(Iterator it = errors.iterator(); it.hasNext();) {
+            buf.append(lineSep).append(it.next());
+        }
+
+        return buf.toString();
+    }
+
+    private void validateDescriptors(List errors) {
+        for(Iterator it = this.mappingDescriptor.getClassDescriptors().entrySet().iterator(); it.hasNext(); ) {
             Map.Entry entry = (Map.Entry) it.next();
             ClassDescriptor cd = (ClassDescriptor) entry.getValue();
-            
+
+            try {
+                cd.afterPropertiesSet();
+            }
+            catch(JcrMappingException jme) {
+                log.warn("Mapping of class " + cd.getClassName() + " is invalid", jme);
+                errors.add(jme.getMessage());
+            }
+        }
+    }
+
+    private List solveReferences(List errors) {
+        for(Iterator it = this.mappingDescriptor.getClassDescriptors().entrySet().iterator(); it.hasNext(); ) {
+            Map.Entry entry = (Map.Entry) it.next();
+            ClassDescriptor cd = (ClassDescriptor) entry.getValue();
+
             if (null != cd.getSuperClass() && !"".equals(cd.getSuperClass())) {
                 ClassDescriptor superClassDescriptor = this.mappingDescriptor.getClassDescriptor(cd.getSuperClass());
-                
+
                 if (null == superClassDescriptor) {
-                    throw new JcrMappingException("Cannot find mapping for class "
-                            + cd.getSuperClass() + " references as extends from "
+                    errors.add("Cannot find mapping for class "
+                            + cd.getSuperClass()
+                            + " referenced as extends from "
                             + cd.getClassName());
                 }
                 else {
@@ -173,6 +207,8 @@
                 }
             }
         }
+
+        return errors;
     }
     
     /**

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/ClassDescriptor.java
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/ClassDescriptor.java?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/ClassDescriptor.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/ClassDescriptor.java Tue Feb 14 17:45:54 2006
@@ -20,6 +20,7 @@
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import org.apache.portals.graffito.jcr.exception.JcrMappingException;
 
 /**
  *
@@ -29,8 +30,8 @@
  * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
  */
 public class ClassDescriptor {
-    public static final String NODETYPE_PER_HIERARCHY = "nodetypeperhierarchy";
-    public static final String NODETYPE_PER_CONCRETECLASS = "nodetypeperconcreteclass";
+    private static final String NODETYPE_PER_HIERARCHY = "nodetypeperhierarchy";
+    private static final String NODETYPE_PER_CONCRETECLASS = "nodetypeperconcreteclass";
 
     private MappingDescriptor mappingDescriptor;
     private ClassDescriptor superClassDescriptor;
@@ -71,7 +72,7 @@
     /**
      * @return Returns the descriminatorValue.
      */
-    public String getDescriminatorValue() {
+    public String getDiscriminatorValue() {
         return descriminatorValue;
     }
 
@@ -83,7 +84,7 @@
      * 
      * @param descriminatorValue The descriminatorValue to set.
      */
-    public void setDescriminatorValue(String descriminatorValue) {
+    public void setDiscriminatorValue(String descriminatorValue) {
         this.descriminatorValue= descriminatorValue;
     }
 
@@ -95,10 +96,19 @@
      * @return Returns {@link #NODETYPE_PER_HIERARCHY} or {@link #NODETYPE_PER_CONCRETECLASS} or
      * <tt>null</tt>
      */
+/*
     public String getExtendsStrategy() {
         return extendsStrategy;
     }
+*/
 
+    public boolean usesNodeTypePerHierarchyStrategy() {
+        return NODETYPE_PER_HIERARCHY.equals(this.extendsStrategy);
+    }
+
+    public boolean usesNodeTypePerConcreteClassStrategy() {
+        return NODETYPE_PER_CONCRETECLASS.equals(this.extendsStrategy);
+    }
     /**
      * @return Returns the className.
      */
@@ -162,7 +172,7 @@
      * @return all {@link FieldDescriptor} defined in this ClassDescriptor
      */
     public Collection getFieldDescriptors() {
-        return this.fieldDescriptors.values();
+        return this.allFields.values();
     }
 
     /**
@@ -242,7 +252,7 @@
     public boolean hasDiscriminatorField() {
         return this.discriminatorFieldDescriptor != null;
     }
-    
+
     /**
      * Check if this class has an ID
      * @return true if the class has an ID
@@ -290,14 +300,16 @@
      *
      * @param mixinTypes command separated list of mixins
      */
-    public void setJcrMixinTypesList(String mixinTypes) {
-        if (null != mixinTypes) {
-            setJcrMixinTypes(mixinTypes.split(","));
-        }
-    }
+//    public void setJcrMixinTypesList(String[] mixinTypes) {
+//        if (null != mixinTypes) {
+//            setJcrMixinTypes(mixinTypes[0].split(","));
+//        }
+//    }
 
     public void setJcrMixinTypes(String[] mixinTypes) {
-        jcrMixinTypes = mixinTypes;
+        if (null != mixinTypes && mixinTypes.length == 1) {
+            jcrMixinTypes = mixinTypes[0].split(" *, *");
+        }
     }
 
     /**
@@ -315,33 +327,67 @@
     }
 
     /**
-     * @return <tt>true</tt> if the class descriptor is correct;
-     * <tt>false</tt> otherwise
+     * Revisit information in this descriptor and fills in more.
      */
-    public boolean validate() {
-        if (null == this.superClassDescriptor) {
-            this.allFields = this.fieldDescriptors;
-            this.allBeans = this.beanDescriptors;
-            this.allCollections = this.collectionDescriptors;
+    public void afterPropertiesSet() {
+        lookupSuperDescriptor();
+
+        lookupInheritanceSettings();
+
+        validateInheritanceSettings();
+    }
+
+    private void validateInheritanceSettings() {
+        if (NODETYPE_PER_CONCRETECLASS.equals(this.extendsStrategy)) {
+            this.discriminatorFieldDescriptor = findDiscriminatorField();
+
+            if (null != this.discriminatorFieldDescriptor) {
+                throw new JcrMappingException("");
+            }
         }
-        else {
-            this.allFields = merge(this.fieldDescriptors, this.superClassDescriptor.getFieldDescriptors());
-            this.allBeans = merge(this.beanDescriptors, this.superClassDescriptor.getBeanDescriptors());
-            this.allCollections = merge(this.collectionDescriptors, this.superClassDescriptor.getCollectionDescriptors());
+        else if (NODETYPE_PER_HIERARCHY.equals(this.extendsStrategy)) {
+            this.discriminatorFieldDescriptor = findDiscriminatorField();
 
             if (null == this.discriminatorFieldDescriptor) {
-                this.discriminatorFieldDescriptor = this.superClassDescriptor.getDiscriminatorFieldDescriptor();
+                throw new JcrMappingException("");
             }
+        }
+    }
 
-            if (null == this.discriminatorFieldDescriptor) {
+    private FieldDescriptor findDiscriminatorField() {
+        if (null != this.discriminatorFieldDescriptor) {
+            return this.discriminatorFieldDescriptor;
+        }
+
+        if (null != this.superClassDescriptor) {
+            return this.superClassDescriptor.findDiscriminatorField();
+        }
+
+        return null;
+    }
+
+    private void lookupInheritanceSettings() {
+        if (null != this.superClassDescriptor) {
+            if (this.jcrNodeType.equals(this.superClassDescriptor.jcrNodeType)) {
                 this.extendsStrategy = NODETYPE_PER_HIERARCHY;
             }
             else {
                 this.extendsStrategy = NODETYPE_PER_CONCRETECLASS;
             }
         }
+    }
 
-        return true;
+    private void lookupSuperDescriptor() {
+        if (null == this.superClassDescriptor) {
+            this.allFields = this.fieldDescriptors;
+            this.allBeans = this.beanDescriptors;
+            this.allCollections = this.collectionDescriptors;
+        }
+        else {
+            this.allFields = merge(this.fieldDescriptors, this.superClassDescriptor.getFieldDescriptors());
+            this.allBeans = merge(this.beanDescriptors, this.superClassDescriptor.getBeanDescriptors());
+            this.allCollections = merge(this.collectionDescriptors, this.superClassDescriptor.getCollectionDescriptors());
+        }
     }
 
     /**

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/MappingDescriptor.java
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/MappingDescriptor.java?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/MappingDescriptor.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/mapper/model/MappingDescriptor.java Tue Feb 14 17:45:54 2006
@@ -53,10 +53,6 @@
             }
         }
 
-        if (!classDescriptor.validate()) {
-            return;
-        }
-
         classDescriptors.put(classDescriptor.getClassName(), classDescriptor);
         classDescriptor.setMappingDescriptor(this);
     }

Modified: incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/ObjectConverterImpl.java
URL: http://svn.apache.org/viewcvs/incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/ObjectConverterImpl.java?rev=377917&r1=377916&r2=377917&view=diff
==============================================================================
--- incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/ObjectConverterImpl.java (original)
+++ incubator/graffito/trunk/jcr/jcr-mapping/src/java/org/apache/portals/graffito/jcr/persistence/objectconverter/impl/ObjectConverterImpl.java Tue Feb 14 17:45:54 2006
@@ -159,6 +159,10 @@
             }
         }
 
+        if (classDescriptor.usesNodeTypePerHierarchyStrategy()) {
+
+        }
+
         storeSimpleFields(session, object, classDescriptor, objectNode);
         insertBeanFields(session, object, classDescriptor, objectNode);
         insertCollectionFields(session, object, classDescriptor, objectNode);
@@ -195,7 +199,17 @@
         try {
             ClassDescriptor classDescriptor = getClassDescriptor(object.getClass());
             Node objectNode = parentNode.getNode(nodeName);
-            
+
+            if (!objectNode.getPrimaryNodeType().getName().equals(classDescriptor.getJcrNodeType())) {
+                throw new PersistenceException("Cannot update object of type "
+                        + object.getClass().getName()
+                        + ". Node type '"
+                        + objectNode.getPrimaryNodeType().getName()
+                        + "' doesn't match mapping node type '"
+                        + classDescriptor.getJcrNodeType()
+                        + "'.");
+            }
+
             storeSimpleFields(session, object, classDescriptor, objectNode);
             updateBeanFields(session, object, classDescriptor, objectNode);
             updateCollectionFields(session, object, classDescriptor, objectNode);
@@ -222,7 +236,35 @@
             }
 
             ClassDescriptor classDescriptor = getClassDescriptor(clazz);
+
+            if (classDescriptor.isAbstract()) {
+                throw new PersistenceException("Cannot fetch declared abstract object of type "
+                + clazz.getName());
+            }
+
             Node node = (Node) session.getItem(path);
+
+            if (!node.getPrimaryNodeType().getName().equals(classDescriptor.getJcrNodeType())
+                && 
+                !("nt:frozenNode".equals(node.getPrimaryNodeType().getName()) 
+                 && node.getProperty("jcr:frozenPrimaryType").getString().equals(classDescriptor.getJcrNodeType()))) {
+                throw new PersistenceException("Cannot fetch object of type '"
+                    + clazz.getName()
+                    + "'. Node type '"
+                    + node.getPrimaryNodeType().getName()
+                    + "' does not match descriptor node type '"
+                    + classDescriptor.getJcrNodeType()
+                    + "'");
+            }
+            if (classDescriptor.usesNodeTypePerHierarchyStrategy()) {
+                String discriminatorProperty = classDescriptor.getDiscriminatorFieldDescriptor().getJcrName();
+
+                if (!node.hasProperty(discriminatorProperty)) {
+                     throw new PersistenceException("Cannot fetch object of type '"
+                        + clazz.getName()
+                        + "' using NODETYPE_PER_HIERARCHY. Discriminator property is not present.");
+                }
+            }
             Object object = ReflectionUtils.newInstance(clazz);
 
             retrieveSimpleFields(session, classDescriptor, node, object);
@@ -286,7 +328,20 @@
                     }
                     
                     ReflectionUtils.setNestedProperty(initializedBean, fieldName, node.getPath());
-                } else {
+                }
+                else if (classDescriptor.usesNodeTypePerHierarchyStrategy() && fieldDescriptor.isDiscriminator()) {
+                    if (null != classDescriptor.getDiscriminatorValue()) {
+                        if (null == initializedBean) {
+                            initializedBean = ReflectionUtils.newInstance(classDescriptor.getClassName());
+                        }
+
+                        ReflectionUtils.setNestedProperty(initializedBean, fieldName, classDescriptor.getDiscriminatorValue());
+                    }
+                    else {
+                        throw new PersistenceException("Class '" + classDescriptor.getClassName() + "' does not declare a valid discriminator value.");
+                    }
+                }
+                else {
                     if (node.hasProperty(propertyName)) {
                         Value propValue = node.getProperty(propertyName).getValue();
                         if (null != propValue && null == initializedBean) { // HINT: lazy initialize target bean
@@ -531,6 +586,19 @@
                 if (fieldDescriptor.isPath()) {
                     continue;
                 }
+
+                // Discriminator is already written
+                if (classDescriptor.usesNodeTypePerHierarchyStrategy() && fieldDescriptor.isDiscriminator()) {
+                    if (null != classDescriptor.getDiscriminatorValue() && !"".equals(classDescriptor.getDiscriminatorValue())) {
+                        objectNode.setProperty(fieldDescriptor.getJcrName(), classDescriptor.getDiscriminatorValue());
+                    }
+                    else {
+                        throw new PersistenceException("Cannot persist object of type " + object.getClass().getName()
+                            + " Missing discriminator value from class descriptor.");
+                    }
+
+                    continue;
+                }
     
                 String fieldName = fieldDescriptor.getFieldName();
                 String jcrName = fieldDescriptor.getJcrName();
@@ -651,7 +719,11 @@
             throw new JcrMappingException("Class of type: " + beanClass.getName()
                     + " is not JCR persistable. Maybe element 'class-descriptor' for this type in mapping file is missing");
         }
-  
+
+        if(classDescriptor.isAbstract()) {
+            throw new PersistenceException("Cannot persist/retrieve abstract class " + beanClass.getName());
+        }
+
         return classDescriptor;
     }
 }