All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.ocm.mapper.impl.AbstractMapperImpl Maven / Gradle / Ivy

Go to download

This Jackrabbit subproject is an object/JCR persistence and query service. This tools lets you to persist java objects into a JCR compliant repository - including association, inheritance, polymorphism, composition, and the Java collections framework. Furthermore, this jcr-mapping allows you to express queries in Java-based Criteria, as well as in JCR query language. It offers also features like version support and object locking.

The newest version!
/*
 * 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.mapper.impl;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.jackrabbit.ocm.exception.IncorrectPersistentClassException;
import org.apache.jackrabbit.ocm.exception.InitMapperException;
import org.apache.jackrabbit.ocm.exception.JcrMappingException;
import org.apache.jackrabbit.ocm.mapper.DescriptorReader;
import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.MappingDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * Abstract class for {@link org.apache.jackrabbit.ocm.mapper.Mapper}
 *
 * @author Lombart Christophe 
 * @author : Boni Gopalan
 *
 * TODO : Add more reference tests. For exemple, the mapper has to check if the class used for the elements
 *        of a collectiondescriptor exists. For performance reasone, we can defined some optional validations.
 */
public abstract class AbstractMapperImpl implements Mapper {
    protected static final Logger log = LoggerFactory.getLogger(AbstractMapperImpl.class);

    protected DescriptorReader descriptorReader;
    protected MappingDescriptor mappingDescriptor;
    protected Collection rootClassDescriptors = new ArrayList(); // contains the class descriptor which have not ancestors

    public void buildMapper()
    {
    	mappingDescriptor = descriptorReader.loadClassDescriptors();
    	mappingDescriptor.setMapper(this);
    	
        if (null != this.mappingDescriptor)
        {
            List errors = new ArrayList();
            errors =  solveReferences(errors);
            errors = validateDescriptors(errors, rootClassDescriptors);

            if (!errors.isEmpty())
            {
                throw new InitMapperException("Mapping descriptors contain errors."
                        + getErrorMessage(errors));
            }
        }
        else
        {
            throw new InitMapperException("No mappings were provided");
        }

    }

    
    /**
     * This method check class descriptor references (ancestor & implemented interfaces) : 
     * For each classdescriptor found, this method will check if the ancestor class and the implemented 
     * interfaces are also persistent or not. 
     * 
     * @param errors
     * @return
     */
    protected List solveReferences(List errors) {
        for(Iterator it = this.mappingDescriptor.getClassDescriptorsByClassName().entrySet().iterator(); it.hasNext(); ) {
            Map.Entry entry = (Map.Entry) it.next();
            ClassDescriptor cd = (ClassDescriptor) entry.getValue();
            
            // Check if the ancestor is a persistent class
            if (null != cd.getExtend() && !"".equals(cd.getExtend()))
            {
                ClassDescriptor superClassDescriptor = this.mappingDescriptor.getClassDescriptorByName(cd.getExtend());

                if (null == superClassDescriptor)
                {
                	// Just a debug info because we can have a non persisted ancestor class
                	log.debug("Cannot find mapping for class "
                            + cd.getExtend()
                            + " referenced as extends from "
                            + cd.getClassName());
                	
                	// This is not necessary to keep a non persisted ancestor class
                	cd.setExtend(null);

                }
                else
                {
            	    log.debug("Class " +cd.getClassName() +  " extends " + cd.getExtend());
                    cd.setSuperClassDescriptor(superClassDescriptor);
                }
            }
            else
            {
                   rootClassDescriptors.add(cd);
            }

            // Check if the implemented interfaces are persistent classes
            Set interfaces = cd.getImplements();
            Set mappedInterfaces  = new HashSet();
            
            if (interfaces.size() > 0)
            {	
            	      for (Iterator iterator = interfaces.iterator(); iterator.hasNext();)
            	      {
            	    	  String interfaceName= (String) iterator.next();
                          ClassDescriptor interfaceClassDescriptor = this.mappingDescriptor.getClassDescriptorByName(interfaceName);

                          if (null == interfaceClassDescriptor)
                          {
                        	  // Just a debug info because we can have a non persisted interface reference 
                        	  log.debug("Cannot find mapping for interface "
                                      + interfaceName
                                      + " referenced as implements from "
                                      + cd.getClassName());
                        	  
                          }
                          else
                          {
                      	      log.debug("Class " +cd.getClassName() +  " implements " + interfaceName);
                      	      interfaceClassDescriptor.addDescendantClassDescriptor(cd);
                      	      mappedInterfaces.add(interfaceName);
                          }
            	    	
            	      }
            	      
            	      cd.setImplements(mappedInterfaces); 
            }

        }

        return errors;
    }

    /**
     * Validate all class descriptors.
     * This method validates the toplevel ancestors and after the descendants.
     * Otherwise, we can have invalid settings in the class descriptors
     * @param errors all errors found during the validation process
     * @param classDescriptors the ancestor classdescriptors
     * @return
     */
    protected List  validateDescriptors(List errors, Collection classDescriptors ) {
        for(Iterator it = classDescriptors.iterator(); it.hasNext(); ) {
            ClassDescriptor classDescriptor = (ClassDescriptor) it.next();
            try {
                classDescriptor.afterPropertiesSet();
                if (classDescriptor.hasDescendants()) {
                    errors = validateDescriptors(errors, classDescriptor.getDescendantClassDescriptors());
                }
            }
            catch(JcrMappingException jme) {
                log.warn("Mapping of class " + classDescriptor.getClassName() + " is invalid", jme);
                errors.add(jme.getMessage());
            }
        }
        return errors;
    }

    protected 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();
    }

    /**
    *
    * @see org.apache.jackrabbit.ocm.mapper.Mapper#getClassDescriptorByClass(java.lang.Class)
    */
   public ClassDescriptor getClassDescriptorByClass(Class clazz) {
	   ClassDescriptor descriptor = mappingDescriptor.getClassDescriptorByName(clazz.getName());
	   if (descriptor==null) {
			throw new IncorrectPersistentClassException("Class of type: " + clazz.getName() + " has no descriptor.");
	   }
       return descriptor ;
   }

   /**
   * @see org.apache.jackrabbit.ocm.mapper.Mapper#getClassDescriptorByNodeType(String)
   */
  public ClassDescriptor getClassDescriptorByNodeType(String jcrNodeType) {
	  ClassDescriptor descriptor = mappingDescriptor.getClassDescriptorByNodeType(jcrNodeType);
	   if (descriptor==null) {
			throw new IncorrectPersistentClassException("Node type: " + jcrNodeType + " has no descriptor.");
	   }
      return descriptor ;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy