OCM-58 make OCM jackrabbit independent. Note that I did remove some methods from the NodeTypeManager interface, but the NodeTypeManagerImpl didn't implement many of them any way. Jackrabbit dependency is now only used as scope test

git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/commons/ocm/trunk@1354509 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/jackrabbit/ocm/mapper/model/PropertyDefDescriptor.java b/src/main/java/org/apache/jackrabbit/ocm/mapper/model/PropertyDefDescriptor.java
index a0977f4..f7cb8ca 100755
--- a/src/main/java/org/apache/jackrabbit/ocm/mapper/model/PropertyDefDescriptor.java
+++ b/src/main/java/org/apache/jackrabbit/ocm/mapper/model/PropertyDefDescriptor.java
@@ -29,6 +29,8 @@
      */

     String getJcrName();

 

+    String getFieldName();

+

     /**

      * @return Returns the property type name.

      */

diff --git a/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/NodeTypeManager.java b/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/NodeTypeManager.java
index 582da86..0e11145 100644
--- a/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/NodeTypeManager.java
+++ b/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/NodeTypeManager.java
@@ -80,109 +80,15 @@
     void createNodeTypes(Session session, ClassDescriptor[] classDescriptors)
     throws NodeTypeCreationException;
 
-    /** This method creates JCR node types based on jcr-mapping xml
-     * files.
-     *
-     * @param session Repository session
-     * @param mappingXmlFiles InputStreams to jcr-mapping xml files
-     * @throws NodeTypeCreationException NodeTypeCreationException
-     */
-    void createNodeTypesFromMappingFiles(Session session,
-            InputStream[] mappingXmlFiles)
-            throws NodeTypeCreationException;
-
     /** This method creates a single JCR node type identified by its ClassDescriptor
      * read from the jcr mapping file.
      *
      * @param session Repository session
      * @param classDescriptor ClassDescriptor object created by jcr-mapping
-     * @param jcrNodeType Name of the class that needs to be created identified
-     * by its jcrNodeType name
      * @throws NodeTypeCreationException NodeTypeCreationException
      */
     void createSingleNodeType(Session session, ClassDescriptor classDescriptor)
     throws NodeTypeCreationException;
 
-    /** This method creates a single JCR node type identified by its jcrNodeType
-     * name defined in a jcr-mapping xml file.
-     *
-     * @param session Repository session
-     * @param mappingXmlFile InputStream to a jcr-mapping xml file
-     * @param jcrNodeType Name of the class that needs to be created identified
-     * by its jcrNodeType name
-     * @throws NodeTypeCreationException NodeTypeCreationException
-     */
-    void createSingleNodeTypeFromMappingFile(Session session,
-            InputStream mappingXmlFile, String jcrNodeType)
-            throws NodeTypeCreationException;
 
-    /** This method creates a JCR node type from a given Java Bean class by using
-     * reflection. It creates required JCR property definitions from primitive
-     * Java class properties using the same property name. Non-primitive class
-     * properties are skipped.
-     *
-     * @param session Repository session
-     * @param clazz Java class
-     * @param jcrNodeType Name of JCR node type (including namespace)
-     * @param reflectSuperClasses If true, all base classes are also reflected
-     * @throws NodeTypeCreationException NodeTypeCreationException
-     */
-    void createNodeTypeFromClass(Session session, Class clazz,
-            String jcrNodeType, boolean reflectSuperClasses)
-            throws NodeTypeCreationException;
-
-    /** This method creates JCR node types from a JCR vendor specific
-     * configuration file.
-     *
-     * @param session Repository session
-     * @param jcrRepositoryXmlConfigurationFile InputStream to file
-     * @throws OperationNotSupportedException OperationNotSupportedException
-     * @throws NodeTypeCreationException NodeTypeCreationException
-     */
-    void createNodeTypesFromConfiguration(Session session,
-            InputStream jcrRepositoryConfigurationFile)
-            throws OperationNotSupportedException, NodeTypeCreationException;
-
-    /** This method removes all JCR node types that are defined in one to many
-     * jcr-mapping XML files.
-     *
-     * @param session Repository session
-     * @param mappingXmlFiles InputStreams to jcr-mapping xml file
-     * @throws NodeTypeRemovalException NodeTypeRemovalException
-     */
-    void removeNodeTypesFromMappingFile(Session session, InputStream[] mappingXmlFiles)
-    throws NodeTypeRemovalException;
-
-    /**
-     * This method removes JCR node types from a JCR vendor specific configuration file
-     * @param session Repository session
-     * @param jcrRepositoryConfigurationFile the file that contains the node type definition
-     * @throws NodeTypeRemovalException
-     */
-    void removeNodeTypesFromConfiguration(Session session, InputStream jcrRepositoryConfigurationFile)
-    throws NodeTypeRemovalException;
-
-    /** This method removes a single JCR node type identified by its jcrNodeType
-     * name.
-     *
-     * @param session Repository session
-     * @param jcrNodeType
-     * @throws NodeTypeRemovalException NodeTypeRemovalException
-     */
-    void removeSingleNodeType(Session session, String jcrNodeType)
-    throws NodeTypeRemovalException;
-
-    /** Returns the names of all node types in the repository identified by a
-     * given namespace.
-     *
-     * @param namespace Name of nodetypes to return
-     * @return list of matching JCR node types
-     */
-    List getPrimaryNodeTypeNames(Session session, String namespace);
-
-    /** Returns a list of all JCR node types.
-     *
-     * @return list of all JCR node types
-     */
-    List getAllPrimaryNodeTypeNames(Session session);
 }
diff --git a/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/impl/NodeTypeManagerImpl.java b/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/impl/NodeTypeManagerImpl.java
new file mode 100644
index 0000000..88bd051
--- /dev/null
+++ b/src/main/java/org/apache/jackrabbit/ocm/nodemanagement/impl/NodeTypeManagerImpl.java
@@ -0,0 +1,312 @@
+package org.apache.jackrabbit.ocm.nodemanagement.impl;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.nodetype.NodeDefinitionTemplate;
+import javax.jcr.nodetype.NodeTypeTemplate;
+import javax.jcr.nodetype.PropertyDefinitionTemplate;
+import javax.jcr.version.OnParentVersionAction;
+
+import org.apache.jackrabbit.ocm.mapper.model.BeanDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.ChildNodeDefDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.CollectionDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.FieldDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
+import org.apache.jackrabbit.ocm.mapper.model.PropertyDefDescriptor;
+import org.apache.jackrabbit.ocm.nodemanagement.NodeTypeManager;
+import org.apache.jackrabbit.ocm.nodemanagement.exception.NamespaceCreationException;
+import org.apache.jackrabbit.ocm.nodemanagement.exception.NodeTypeCreationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NodeTypeManagerImpl implements NodeTypeManager {
+
+    private static Logger log = LoggerFactory.getLogger(NodeTypeManagerImpl.class);
+    @Override
+    public void createNamespace(final Session session, final String namespace, final String namespaceUri) throws NamespaceCreationException {
+        if (session != null)
+        {
+            try
+            {
+                session.getWorkspace().getNamespaceRegistry().registerNamespace(namespace, namespaceUri);
+                log.info("Namespace created: " +
+                        "{" + namespaceUri + "}" + namespace);
+            }
+            catch (Exception e)
+            {
+                throw new NamespaceCreationException(e);
+            }
+        }
+    }
+
+    @Override
+    public void createNodeTypes(final Session session, final MappingDescriptor mappingDescriptor) throws NodeTypeCreationException {
+        if (mappingDescriptor != null && mappingDescriptor.getClassDescriptorsByClassName().size() > 0)
+        {
+            final Collection classDescriptorObjects = mappingDescriptor.getClassDescriptorsByClassName().values();
+            final ClassDescriptor[] classDescriptors = (ClassDescriptor[])classDescriptorObjects.toArray(new ClassDescriptor[classDescriptorObjects.size()]);
+            createNodeTypes(session, classDescriptors);
+        }
+        else
+        {
+            throw new NodeTypeCreationException("The MappingDescriptor can't be null or empty.");
+        }
+    }
+
+    @Override
+    public void createNodeTypes(final Session session, final ClassDescriptor[] classDescriptors) throws NodeTypeCreationException {
+        if (classDescriptors != null && classDescriptors.length > 0)
+        {
+            log.info("Trying to create " + classDescriptors.length +
+                    " JCR node types.");
+            for (int i = 0; i < classDescriptors.length; i++)
+            {
+                createSingleNodeType(session, classDescriptors[i]);
+            }
+        }
+        else
+        {
+            throw new NodeTypeCreationException("The ClassDescriptor can't be null or empty.");
+        }
+    }
+
+    @Override
+    public void createSingleNodeType(final Session session, final ClassDescriptor classDescriptor) throws NodeTypeCreationException {
+        try {
+            if (classDescriptor.getJcrType() != null &&
+                    (classDescriptor.getJcrType().startsWith("nt:")
+                            || classDescriptor.getJcrType().startsWith("mix:"))) {
+                throw new NodeTypeCreationException("Namespace nt and mix are reserved namespaces. Please specify your own.");
+            }
+
+            if (checkSuperTypes(session.getWorkspace().getNodeTypeManager(),
+                    classDescriptor.getJcrSuperTypes())) {
+
+                javax.jcr.nodetype.NodeTypeManager ntm = session.getWorkspace().getNodeTypeManager();
+                final NodeTypeTemplate ntt = ntm.createNodeTypeTemplate();
+
+                if (classDescriptor.getJcrType() == null) {
+                    ntt.setName(classDescriptor.getClassName());
+                } else {
+                    ntt.setName(classDescriptor.getJcrType());
+                }
+                ntt.setAbstract(classDescriptor.isAbstract());
+                if (classDescriptor.getJcrSuperTypes() != null && classDescriptor.getJcrSuperTypes().length() > 0) {
+                    String[] superTypesArray = classDescriptor.getJcrSuperTypes().split(",");
+                    //TODO  combine the mixins here as well as supertypes
+                    // Add classDescriptor.getJcrMixinTypes() to superTypesArray
+                    for (String s : classDescriptor.getJcrMixinTypes()) {
+                        System.out.println(s);
+                    }
+                    ntt.setDeclaredSuperTypeNames(superTypesArray);
+                }
+                // should we also support mixins to be created?
+                ntt.setMixin(false);
+                ntt.setQueryable(true);
+                ntt.setOrderableChildNodes(true);
+
+                final List nodeDefinitionTemplates = ntt.getNodeDefinitionTemplates();
+                final List propertyDefinitionTemplates = ntt.getPropertyDefinitionTemplates();
+
+                if (classDescriptor.getFieldDescriptors() != null) {
+                    Iterator fieldIterator = classDescriptor.getFieldDescriptors().iterator();
+                    while (fieldIterator.hasNext()) {
+                        FieldDescriptor field = (FieldDescriptor) fieldIterator.next();
+                        if (!field.isPath()) {
+                            final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
+                            // add the just created pdt to the nodetypetemplate
+                            propertyDefinitionTemplates.add(pdt);
+                        }
+                    }
+
+                    if (classDescriptor.getBeanDescriptors() != null) {
+                        Iterator beanIterator = classDescriptor.getBeanDescriptors().iterator();
+                        while (beanIterator.hasNext()) {
+                            BeanDescriptor field = (BeanDescriptor) beanIterator.next();
+                            if (this.isPropertyType(field.getJcrType())) {
+                                final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
+                                // add the just created pdt to the nodetypetemplate
+                                propertyDefinitionTemplates.add(pdt);
+                            } else {
+                                final NodeDefinitionTemplate ndt = getNodeDefinition(ntm, session.getValueFactory(), field);
+                                // add the just created pdt to the nodetypetemplate
+                                nodeDefinitionTemplates.add(ndt);
+                            }
+                        }
+                    }
+
+                    if (classDescriptor.getCollectionDescriptors() != null) {
+                        Iterator collectionIterator = classDescriptor.getCollectionDescriptors().iterator();
+                        while (collectionIterator.hasNext()) {
+                            CollectionDescriptor field = (CollectionDescriptor) collectionIterator.next();
+                            if (this.isPropertyType(field.getJcrType())) {
+                                final PropertyDefinitionTemplate pdt = getPropertyDefinition(ntm, session.getValueFactory(), field);
+                                // add the just created pdt to the nodetypetemplate
+                                propertyDefinitionTemplates.add(pdt);
+                            } else {
+                                final NodeDefinitionTemplate ndt = getNodeDefinition(ntm, session.getValueFactory(), field);
+                                // add the just created pdt to the nodetypetemplate
+                                nodeDefinitionTemplates.add(ndt);
+                            }
+                        }
+                    }
+                    ntm.registerNodeType(ntt, false);
+                    log.info("Registered JCR node type '" + ntt.getName() +
+                            "' for class '" + classDescriptor.getClassName() + "'");
+                }
+            } else {
+                throw new NodeTypeCreationException("JCR supertypes could not be resolved.");
+            }
+        } catch (Exception e) {
+            log.error("Could not create node types from class descriptor.", e);
+            throw new NodeTypeCreationException(e);
+        }
+    }
+
+    private NodeDefinitionTemplate getNodeDefinition(final javax.jcr.nodetype.NodeTypeManager ntm,
+                                                     final ValueFactory valueFactory,
+                                                     final ChildNodeDefDescriptor field) throws RepositoryException {
+
+
+        final NodeDefinitionTemplate ndt = ntm.createNodeDefinitionTemplate();
+        if (field.getJcrName() != null) {
+            ndt.setName(field.getJcrName());
+        } else {
+            ndt.setName("*");
+        }
+
+        int onParentVersion = OnParentVersionAction.IGNORE;
+
+        if (field.getJcrOnParentVersion() != null
+                && field.getJcrOnParentVersion().length() > 0) {
+            onParentVersion = OnParentVersionAction.valueFromName(field.getJcrOnParentVersion());
+        }
+        ndt.setOnParentVersion(onParentVersion);
+        ndt.setSameNameSiblings(field.isJcrSameNameSiblings());
+
+        ndt.setAutoCreated(field.isJcrAutoCreated());
+        ndt.setDefaultPrimaryTypeName(field.getDefaultPrimaryType());
+        ndt.setMandatory(field.isJcrMandatory());
+        ndt.setProtected(field.isJcrProtected());
+        ndt.setRequiredPrimaryTypeNames(getJcrSuperTypes(field.getJcrType()));
+
+        return ndt;
+    }
+
+    private PropertyDefinitionTemplate getPropertyDefinition(final javax.jcr.nodetype.NodeTypeManager ntm,
+                                                             final ValueFactory valueFactory,
+                                                             final PropertyDefDescriptor field) throws RepositoryException {
+        final PropertyDefinitionTemplate pdt = ntm.createPropertyDefinitionTemplate();
+        if (field.getJcrName() != null) {
+            pdt.setName(field.getJcrName());
+        } else {
+            pdt.setName(field.getFieldName());
+        }
+
+        if (field.getJcrType() != null) {
+            try {
+                pdt.setRequiredType(PropertyType.valueFromName(field.getJcrType()));
+            } catch (IllegalArgumentException e) {
+                log.warn("Invalid property type '{}' for '{}'. Set default to String type", field.getJcrType(), field.getJcrName());
+                pdt.setRequiredType(PropertyType.STRING);
+            }
+        } else {
+            log.info("No property type set for {}. Setting 'String' type.", field.getJcrName());
+            pdt.setRequiredType(PropertyType.STRING);
+
+        }
+        int onParentVersion = OnParentVersionAction.IGNORE;
+        if (field.getJcrOnParentVersion() != null &&
+                field.getJcrOnParentVersion().length() > 0) {
+            onParentVersion = OnParentVersionAction.valueFromName(field.getJcrOnParentVersion());
+        }
+        pdt.setOnParentVersion(onParentVersion);
+
+        pdt.setAutoCreated(field.isJcrAutoCreated());
+        pdt.setAvailableQueryOperators(new String[0]);
+
+        pdt.setFullTextSearchable(true);
+        pdt.setMandatory(field.isJcrMandatory());
+        pdt.setMultiple(field.isJcrMultiple());
+        pdt.setOnParentVersion(onParentVersion);
+        pdt.setProtected(field.isJcrProtected());
+        pdt.setQueryOrderable(true);
+
+        if (field instanceof  FieldDescriptor) {
+            FieldDescriptor f = (FieldDescriptor) field;
+            if (f.getJcrDefaultValue() != null) {
+                if (pdt.getRequiredType() == PropertyType.STRING) {
+                    Value[] vals = {valueFactory.createValue(f.getJcrDefaultValue())};
+                    pdt.setDefaultValues(vals);
+                } else {
+                    log.warn("Can only set default value for String properties. Skip for field '{}'", field.getJcrName());
+                }
+            }
+            pdt.setValueConstraints(f.getJcrValueConstraints());
+        }
+
+        return pdt;
+    }
+
+    /** Checks if all JCR super types for a given node type exist.
+     *
+     * @param ntMgr NodeTypeManager
+     * @param superTypes Comma separated String with JCR node types
+     * @return returns <code>false</code> if one of the supertypes does not exist, otherwise returns <code>true</code>
+     */
+    private boolean checkSuperTypes(javax.jcr.nodetype.NodeTypeManager ntMgr,
+                                    String superTypes)
+    {
+        boolean exists = true;
+
+        if (superTypes != null && superTypes.length() > 0)
+        {
+            String[] superTypesArray = superTypes.split(",");
+            log.debug("JCR super types found: " + superTypesArray.length);
+            for (int i = 0; i < superTypesArray.length; i++)
+            {
+                try
+                {
+                    ntMgr.getNodeType(superTypesArray[i]);
+                }
+                catch (Exception e)
+                {
+                    log.error("JCR super type '" + superTypesArray[i] + "' does not exist!");
+                    exists = false;
+                    break;
+                }
+            }
+        }
+
+        return exists;
+    }
+
+    public String[] getJcrSuperTypes(String superTypes)
+    {
+        return superTypes.split(",");
+    }
+
+    private boolean isPropertyType(String type)
+    {
+        return (type.equals(PropertyType.TYPENAME_BINARY) ||
+                type.equals(PropertyType.TYPENAME_BOOLEAN) ||
+                type.equals(PropertyType.TYPENAME_DATE) ||
+                type.equals(PropertyType.TYPENAME_DOUBLE) ||
+                type.equals(PropertyType.TYPENAME_LONG) ||
+                type.equals(PropertyType.TYPENAME_NAME) ||
+                type.equals(PropertyType.TYPENAME_PATH) ||
+                type.equals(PropertyType.TYPENAME_REFERENCE) ||
+                type.equals(PropertyType.TYPENAME_WEAKREFERENCE) ||
+                type.equals(PropertyType.TYPENAME_DECIMAL) ||
+                type.equals(PropertyType.TYPENAME_URI) ||
+                type.equals(PropertyType.TYPENAME_STRING));
+    }
+}