You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by cl...@apache.org on 2007/09/05 23:22:15 UTC

svn commit: r573066 - in /jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper: AnnotatedObjectMapper.java ExtractNTCreationAnnotatedObjectMapper.java

Author: clombart
Date: Wed Sep  5 14:22:14 2007
New Revision: 573066

URL: http://svn.apache.org/viewvc?rev=573066&view=rev
Log:
Refactor Mapper & reader (issue 1113). 

Added:
    jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/ExtractNTCreationAnnotatedObjectMapper.java
Modified:
    jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/AnnotatedObjectMapper.java   (props changed)

Propchange: jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/AnnotatedObjectMapper.java
------------------------------------------------------------------------------
    svn:executable = *

Added: jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/ExtractNTCreationAnnotatedObjectMapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/ExtractNTCreationAnnotatedObjectMapper.java?rev=573066&view=auto
==============================================================================
--- jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/ExtractNTCreationAnnotatedObjectMapper.java (added)
+++ jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/annotation/src/main/java/org/apache/jackrabbit/ocm/annotation/mapper/ExtractNTCreationAnnotatedObjectMapper.java Wed Sep  5 14:22:14 2007
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.ocm.annotation.mapper;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Workspace;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
+
+import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
+import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
+import org.apache.jackrabbit.ocm.annotation.Bean;
+import org.apache.jackrabbit.ocm.annotation.Collection;
+import org.apache.jackrabbit.ocm.annotation.Field;
+import org.apache.jackrabbit.ocm.annotation.Node;
+import org.apache.jackrabbit.ocm.exception.IncorrectPersistentClassException;
+import org.apache.jackrabbit.ocm.mapper.Mapper;
+import org.apache.jackrabbit.ocm.mapper.model.BeanDescriptor;
+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.nodemanagement.NodeTypeManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An implementation of the OCM mapper that builds class descriptors based on
+ * the use of annotations on the underlying classes
+ * 
+ * @author Philip Dodds
+ * 
+ */
+public class ExtractNTCreationAnnotatedObjectMapper implements Mapper {
+
+	/** namespace prefix constant */
+	public static final String OCM_NAMESPACE_PREFIX = "ocm";
+
+	/** namespace constant */
+	public static final String OCM_NAMESPACE = "http://jackrabbit.apache.org/ocm";
+	
+	private static final String OCM_NAMESPACE_XML = "/org/apache/jackrabbit/ocm/annotation/ocm_nodetypes.xml";
+
+	private static Logger log = LoggerFactory.getLogger(ExtractNTCreationAnnotatedObjectMapper.class);
+
+	private List<String> annotatedClassNames = new ArrayList<String>();
+
+	private Map<Class, ClassDescriptor> descriptorMap = new HashMap<Class, ClassDescriptor>();
+
+	private Map<String, ClassDescriptor> nodeTypeMap = new HashMap<String, ClassDescriptor>();
+
+	public ExtractNTCreationAnnotatedObjectMapper(Session session,
+			List<String> annotatedClassNames, 
+			NodeTypeManager nodeTypeManager ) throws ClassNotFoundException {
+		this.annotatedClassNames = annotatedClassNames;
+		try {
+			List<ClassDescriptor> classDescriptorsRequiringRegistration = buildClassDescriptors(session);
+			registerNamespaces(session);
+			registerNodeTypes(session);
+
+			if (!classDescriptorsRequiringRegistration.isEmpty()) {
+				log.info("Registering "
+						+ classDescriptorsRequiringRegistration.size()
+						+ " missing node types");
+				nodeTypeManager
+						.createNodeTypes(
+								session,
+								(ClassDescriptor[]) classDescriptorsRequiringRegistration
+										.toArray(new ClassDescriptor[0]));
+			}
+			else
+			{
+				log.warn("No class descriptor to register in the JCR repository");
+			}
+		} catch (Exception e) {
+			throw new RuntimeException("Unable to register node types", e);
+		}
+	}
+
+	private void registerNamespaces(Session session) throws RepositoryException {
+
+		String[] jcrNamespaces = session.getWorkspace().getNamespaceRegistry()
+				.getPrefixes();
+		boolean createNamespace = true;
+		for (int i = 0; i < jcrNamespaces.length; i++) {
+			if (jcrNamespaces[i].equals(OCM_NAMESPACE_PREFIX)) {
+				createNamespace = false;
+				log.debug("Jackrabbit OCM namespace exists.");
+			}
+		}
+
+		if (createNamespace) {
+			session.getWorkspace().getNamespaceRegistry().registerNamespace(
+					OCM_NAMESPACE_PREFIX, OCM_NAMESPACE);
+			log.info("Successfully created Jackrabbit OCM namespace.");
+		}
+
+
+	}
+
+	private void registerNodeTypes(Session session)
+	    throws InvalidNodeTypeDefException, javax.jcr.RepositoryException,
+	    IOException {
+	    	InputStream xml = getClass().getResourceAsStream(OCM_NAMESPACE_XML);
+	    	
+	    	if (xml == null) {
+	    	    throw new FileNotFoundException(OCM_NAMESPACE_XML + " was not found in the classpath"); 
+	    	}
+        
+        	// HINT: throws InvalidNodeTypeDefException, IOException
+        	NodeTypeDef[] types = NodeTypeReader.read(xml);
+        
+        	Workspace workspace = session.getWorkspace();
+        	javax.jcr.nodetype.NodeTypeManager ntMgr = workspace.getNodeTypeManager();
+        	NodeTypeRegistry ntReg = ((org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry();
+        
+        	for (int j = 0; j < types.length; j++) {
+        	    NodeTypeDef def = types[j];
+        
+        	    try {
+        		ntReg.getNodeTypeDef(def.getName());
+        	    } catch (NoSuchNodeTypeException nsne) {
+        		// HINT: if not already registered than register custom node
+        		// type
+        		ntReg.registerNodeType(def);
+        	    }
+        
+        	}
+        }
+
+	private List<ClassDescriptor> buildClassDescriptors(Session session)
+			throws ClassNotFoundException {
+		List<ClassDescriptor> classDescriptorsToRegister = new ArrayList<ClassDescriptor>();
+		for (String className : getAnnotatedClassNames()) {
+			Class clazz = Class.forName(className);
+			ClassDescriptor classDescriptor = buildClassDescriptor(clazz);
+			try {
+				session.getWorkspace().getNodeTypeManager().getNodeType(
+						classDescriptor.getJcrType());
+				log.info("Class " + className + " already registered");
+			} catch (NoSuchNodeTypeException e) {
+				log.info("Class " + className + " will be registered");
+				classDescriptorsToRegister.add(classDescriptor);
+			} catch (RepositoryException e) {
+				throw new RuntimeException(e);
+			}
+
+			descriptorMap.put(clazz, classDescriptor);
+			nodeTypeMap.put(classDescriptor.getJcrType(), classDescriptor);
+		}
+
+		return classDescriptorsToRegister;
+	}
+
+	private ClassDescriptor buildClassDescriptor(Class clazz) throws ClassNotFoundException {
+		Node annotationNode =  (Node) clazz.getAnnotation(Node.class);
+		ClassDescriptor descriptor = new ClassDescriptor();
+		descriptor.setClassName(clazz.getName());
+		descriptor.setJcrType(annotationNode.jcrType());
+		descriptor.setJcrSuperTypes(annotationNode.jcrSuperTypes());		
+		descriptor.setJcrMixinTypes(annotationNode.jcrMixinTypes());
+		descriptor.setExtend(annotationNode.extend());		
+		descriptor.setAbstract(annotationNode.isAbstract());
+		descriptor.setInterface(clazz.isInterface());
+		
+		addFieldDescriptors(descriptor, clazz);
+		addBeanDescriptors(descriptor, clazz);
+		addCollectionDescriptors(descriptor, clazz);
+		return descriptor;
+	}
+
+	private void addCollectionDescriptors(ClassDescriptor descriptor,Class clazz) {
+		BeanInfo beanInfo;
+		try {
+			beanInfo = Introspector.getBeanInfo(clazz);
+		} catch (IntrospectionException e) {
+			throw new RuntimeException(e);
+		}
+		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+			Collection jcrChildNode = propertyDescriptor.getReadMethod().getAnnotation(Collection.class);
+			if (jcrChildNode != null) {
+				Class targetClass = jcrChildNode.type();
+				CollectionDescriptor collectionDescriptor = new CollectionDescriptor();
+				ClassDescriptor classDescriptor = descriptorMap.get(targetClass);
+
+				if (classDescriptor == null)
+					throw new RuntimeException(
+							"Unable to reference class "
+									+ targetClass.getName()
+									+ " as a child node since it has not been registered, ordering perhaps?");
+
+				if (jcrChildNode.jcrName() != null && ! jcrChildNode.jcrName().equals(""))
+				{
+				   collectionDescriptor.setJcrName(jcrChildNode.jcrName());
+				}
+				else
+				{
+				   collectionDescriptor.setJcrName(propertyDescriptor.getName());
+				}
+				
+				Node annotationNode = (Node) targetClass.getAnnotation(Node.class);
+				collectionDescriptor.setDefaultPrimaryType(annotationNode.jcrType());
+				collectionDescriptor.setJcrSameNameSiblings(jcrChildNode.sameNameSiblings());
+				collectionDescriptor.setJcrAutoCreated(jcrChildNode.autoCreate());
+				collectionDescriptor.setJcrProtected(jcrChildNode.protect());
+				collectionDescriptor.setJcrOnParentVersion(jcrChildNode.onParentVersion());
+				collectionDescriptor.setJcrMandatory(jcrChildNode.mandatory());
+				collectionDescriptor.setAutoInsert(jcrChildNode.autoInsert());
+				collectionDescriptor.setAutoRetrieve(jcrChildNode.autoRetrieve());
+				collectionDescriptor.setAutoUpdate(jcrChildNode.autoUpdate());
+				collectionDescriptor.setCollectionClassName(propertyDescriptor.getReadMethod().getReturnType().getName());
+				collectionDescriptor.setElementClassName(targetClass.getName());
+				collectionDescriptor.setCollectionConverter(jcrChildNode.converter().getName());
+				collectionDescriptor.setFieldName(propertyDescriptor.getName());
+
+				collectionDescriptor.setJcrType(annotationNode.jcrType());
+				collectionDescriptor.setJcrSameNameSiblings(jcrChildNode.sameNameSiblings());
+				collectionDescriptor.setProxy(jcrChildNode.proxy());
+
+				descriptor.addCollectionDescriptor(collectionDescriptor);
+			}
+		}
+
+	}
+
+	
+	private void addBeanDescriptors(ClassDescriptor descriptor,Class clazz) {
+		BeanInfo beanInfo;
+		try {
+			beanInfo = Introspector.getBeanInfo(clazz);
+		} catch (IntrospectionException e) {
+			throw new RuntimeException(e);
+		}
+		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+			Bean jcrChildNode = propertyDescriptor.getReadMethod().getAnnotation(Bean.class);
+			if (jcrChildNode != null) {
+				
+				BeanDescriptor beanDescriptor = new BeanDescriptor();
+				beanDescriptor.setFieldName(propertyDescriptor.getName());
+				if (jcrChildNode.jcrName() != null && ! jcrChildNode.jcrName().equals(""))
+				{
+				   beanDescriptor.setJcrName(jcrChildNode.jcrName());
+				}
+				else
+				{
+					beanDescriptor.setJcrName(propertyDescriptor.getName());
+				}
+				
+				beanDescriptor.setProxy(jcrChildNode.proxy());				
+				beanDescriptor.setConverter(jcrChildNode.converter().getName());
+				beanDescriptor.setAutoInsert(jcrChildNode.autoInsert());
+				beanDescriptor.setAutoRetrieve(jcrChildNode.autoRetrieve());
+				beanDescriptor.setAutoUpdate(jcrChildNode.autoUpdate());
+				beanDescriptor.setJcrType(jcrChildNode.jcrType());
+				beanDescriptor.setJcrAutoCreated(jcrChildNode.jcrAutoCreated());
+				beanDescriptor.setJcrMandatory(jcrChildNode.jcrMandatory());
+				beanDescriptor.setJcrOnParentVersion(jcrChildNode.jcrOnParentVersion());
+				beanDescriptor.setJcrProtected(jcrChildNode.jcrProtected());			            
+				beanDescriptor.setJcrSameNameSiblings(jcrChildNode.jcrSameNameSiblings());				
+
+				descriptor.addBeanDescriptor(beanDescriptor);
+			}
+		}
+
+	}
+	
+	private void addFieldDescriptors(ClassDescriptor descriptor, Class clazz) {
+		BeanInfo beanInfo;
+		try {
+			beanInfo = Introspector.getBeanInfo(clazz);
+		} catch (IntrospectionException e) {
+			throw new RuntimeException(e);
+		}
+
+		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
+		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
+			Field jcrProperty = propertyDescriptor.getReadMethod().getAnnotation(Field.class);
+			if (jcrProperty != null) {
+				FieldDescriptor fieldDescriptor = new FieldDescriptor();				
+				fieldDescriptor.setFieldName(propertyDescriptor.getName());
+				if ((jcrProperty.jcrName() != null) && (!jcrProperty.jcrName().equals("")))
+				{
+					fieldDescriptor.setJcrName(jcrProperty.jcrName());	
+				}
+				else
+				{
+					fieldDescriptor.setJcrName(propertyDescriptor.getName());	
+				}
+				fieldDescriptor.setId(jcrProperty.id());				
+				fieldDescriptor.setPath(jcrProperty.path());
+				fieldDescriptor.setUuid(jcrProperty.uuid());
+				
+				// It is not possible to set a null value into a annotation attribute.
+				// If the converter == Object.class, it shoudl be considered as null
+				if (! jcrProperty.converter().equals(Object.class))
+				{
+				    fieldDescriptor.setConverter(jcrProperty.converter().getName());
+				}
+				fieldDescriptor.setJcrDefaultValue(jcrProperty.jcrDefaultValue());			
+				fieldDescriptor.setJcrValueConstraints(jcrProperty.jcrDefaultValue());
+				fieldDescriptor.setJcrType(jcrProperty.jcrType());
+				
+				fieldDescriptor.setJcrAutoCreated(jcrProperty.jcrAutoCreated());
+				fieldDescriptor.setJcrMandatory(jcrProperty.jcrMandatory());
+				fieldDescriptor.setJcrOnParentVersion(jcrProperty.jcrOnParentVersion());
+				fieldDescriptor.setJcrProtected(jcrProperty.jcrProtected());
+				fieldDescriptor.setJcrMultiple(jcrProperty.jcrMultiple());
+				
+				//fieldDescriptor.setJcrType(value)
+				descriptor.addFieldDescriptor(fieldDescriptor);
+			}
+		}
+
+	}    
+    
+
+    	
+	public ClassDescriptor getClassDescriptorByClass(Class clazz) {
+		ClassDescriptor descriptor = (ClassDescriptor) descriptorMap.get(clazz);
+		 if (descriptor==null) {
+				throw new IncorrectPersistentClassException("Class of type: " + clazz.getName() + " has no descriptor.");
+		   }
+	       return descriptor ;
+	}
+
+	public ClassDescriptor getClassDescriptorByNodeType(String jcrNodeType) {
+		ClassDescriptor descriptor =  nodeTypeMap.get(jcrNodeType);
+		 if (descriptor==null) {
+			 throw new IncorrectPersistentClassException("Node type: " + jcrNodeType + " has no descriptor.");
+		   }
+	       return descriptor ;
+		
+	}
+
+	public List<String> getAnnotatedClassNames() {
+		return annotatedClassNames;
+	}
+
+	public void setAnnotatedClassNames(List<String> annotatedClassNames) {
+		this.annotatedClassNames = annotatedClassNames;
+	}
+
+}