Package org.apache.jackrabbit.ocm.manager.collectionconverter.impl

Source Code of org.apache.jackrabbit.ocm.manager.collectionconverter.impl.NTCollectionConverterImpl

/*
* 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.manager.collectionconverter.impl;


import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.QueryResult;
import javax.jcr.version.VersionException;

import org.apache.jackrabbit.ocm.exception.JcrMappingException;
import org.apache.jackrabbit.ocm.manager.collectionconverter.ManageableCollection;
import org.apache.jackrabbit.ocm.manager.collectionconverter.ManageableMap;
import org.apache.jackrabbit.ocm.manager.collectionconverter.ManageableObjects;
import org.apache.jackrabbit.ocm.manager.collectionconverter.ManageableObjectsUtil;
import org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter;
import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
import org.apache.jackrabbit.ocm.mapper.model.CollectionDescriptor;
import org.apache.jackrabbit.ocm.reflection.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Collection Mapping/convertion based on node type.
*
* This collection mapping strategy maps the collection elements into subnodes based on the same node types.
*
* There are 3 constraints in this collection converter :
* 1/ this is not possible to have 2 different collections in the main object which are used the same jcr node type for their elements.
* 2/ this is not possible to make a distinction between an empty collection and an null collection.
* 3/ Map are not supported.
*
*
* If the collection element class contains an id (see the FieldDescriptor definition), this id value is used to build the collection element node name.
* Otherwise, the element node name is a simple constant (collection-element)
*
* Example - without an id attribute:
*   /test (Main object containing the collection field )
*          /collection-element (node used to store the first collection element)
*                /item-prop
*                ....
*          /collection-element (node used to store the second collection element)
*          ...
*
*          Each "collection-element" nodes have the same jcr node type
*
* Example - with an id attribute:
*   /test (Main object containing the collection field )
*          /aValue (id value assigned to the first element)
*                /item-prop
*                ....
*          /anotherValue (id value assigned to the first element)
*          ...
*
*          Each collection element nodes have the same jcr node type
*
* @author <a href="mailto:christophe.lombart@gmail.com">Christophe Lombart</a>
*
*/
public class NTCollectionConverterImpl extends AbstractCollectionConverterImpl {

    private final static Logger log = LoggerFactory.getLogger(NTCollectionConverterImpl.class);

    protected static final String COLLECTION_ELEMENT_NAME = "collection-element";

    /**
     * Constructor
     *
     * @param atomicTypeConverters
     * @param objectConverter
     * @param mapper
     */
    public NTCollectionConverterImpl(Map atomicTypeConverters,
                                     ObjectConverter objectConverter,
                                     Mapper mapper) {
        super(atomicTypeConverters, objectConverter, mapper);
    }


    protected void doInsertCollection(Session session,
                                      Node parentNode,
                                      CollectionDescriptor collectionDescriptor,
                                      ManageableObjects objects) {
        if (objects == null) {
            return;
        }

        ClassDescriptor elementClassDescriptor = mapper.getClassDescriptorByClass( ReflectionUtils.forName(collectionDescriptor.getElementClassName()));

        Iterator collectionIterator = objects.getIterator();
        while (collectionIterator.hasNext()) {
            Object item = collectionIterator.next();
            String elementJcrName = null;

            // If the element object has a unique id => the element jcr node name = the id value
            if (elementClassDescriptor.hasIdField()) {
                String idFieldName = elementClassDescriptor.getIdFieldDescriptor().getFieldName();
                elementJcrName = ReflectionUtils.getNestedProperty(item, idFieldName).toString();
            }
            else {
                elementJcrName = collectionDescriptor.getJcrElementName();
                if (elementJcrName == null) { // use PathFormat.checkFormat() here?
                    elementJcrName = COLLECTION_ELEMENT_NAME;
                }
            }

            objectConverter.insert(session, parentNode, elementJcrName, item);
        }
    }

    protected void doUpdateCollection(Session session,
                                      Node parentNode,
                                      CollectionDescriptor collectionDescriptor,
                                      ManageableObjects objects) throws RepositoryException {

        ClassDescriptor elementClassDescriptor = mapper.getClassDescriptorByClass(
                ReflectionUtils.forName(collectionDescriptor.getElementClassName()));

        if (objects == null || !elementClassDescriptor.hasIdField()) {
            this.deleteCollectionItems(session,
                                       parentNode,
                                       elementClassDescriptor.getJcrType());
        }

        if (objects == null) {
            return;
        }

        Iterator collectionIterator = objects.getIterator();
        Map updatedItems = new HashMap();
        while (collectionIterator.hasNext()) {
            Object item = collectionIterator.next();

            String elementJcrName = null;

            if (elementClassDescriptor.hasIdField()) {
                String idFieldName = elementClassDescriptor.getIdFieldDescriptor().getFieldName();
                elementJcrName = ReflectionUtils.getNestedProperty(item, idFieldName).toString();

                // Update existing JCR Nodes
                if (parentNode.hasNode(elementJcrName)) {
                    objectConverter.update(session, parentNode, elementJcrName, item);
                }
                else {
                    // Add new collection elements
                    objectConverter.insert(session, parentNode, elementJcrName, item);
                }

                updatedItems.put(elementJcrName, item);
            }
            else {
                elementJcrName = collectionDescriptor.getJcrElementName();
                if (elementJcrName == null) { // use PathFormat.checkFormat() here?
                    elementJcrName = COLLECTION_ELEMENT_NAME;
                }
                objectConverter.insert(session, parentNode, elementJcrName, item);
            }
        }

        // Delete JCR nodes that are not present in the collection
         NodeIterator nodes = this.getCollectionNodes(session, parentNode,
                                                          elementClassDescriptor.getJcrType());
         if (nodes != null && elementClassDescriptor.hasIdField()) {


            while (nodes.hasNext()) {
                Node child = (Node) nodes.next();

                if (!updatedItems.containsKey(child.getName())) {
                    child.remove();
                }
            }
        }
    }

    /**
     * @see org.apache.jackrabbit.ocm.manager.collectionconverter.CollectionConverter#getCollection(javax.jcr.Session, javax.jcr.Node, org.apache.jackrabbit.ocm.mapper.model.CollectionDescriptor, java.lang.Class)
     */
    protected ManageableObjects doGetCollection(Session session,
                                                   Node parentNode,
                                                   CollectionDescriptor collectionDescriptor,
                                                   Class collectionFieldClass) throws RepositoryException {
      ClassDescriptor elementClassDescriptor = mapper.getClassDescriptorByClass( ReflectionUtils.forName(collectionDescriptor.getElementClassName()));
        ManageableObjects objects = ManageableObjectsUtil.getManageableObjects(collectionFieldClass);

        NodeIterator nodes = this.getCollectionNodes(session, parentNode, elementClassDescriptor.getJcrType());

        if (nodes == null || nodes.getSize() == 0)
        {
          return null;
        }

        while (nodes.hasNext()) {
            Node itemNode = (Node) nodes.next();
            log.debug("Collection node found : " + itemNode.getPath());
            Object item = objectConverter.getObject(session,  itemNode.getPath());
            mapper.getClassDescriptorByClass(item.getClass());
            if ( objects instanceof ManageableCollection)
              ((ManageableCollection)objects).addObject(item);
            else {
              if (!elementClassDescriptor.hasIdField())
              {
                throw new JcrMappingException("Impossible to use a map for the field : "
                                          + collectionDescriptor.getFieldName()
                                          + "in the class : " + collectionDescriptor.getCollectionClassName()
                                          + ". The element objects have no id field (check their OCM mapping)");
              }
              Object elementId = ReflectionUtils.getNestedProperty(item,
                                             elementClassDescriptor.getIdFieldDescriptor().getFieldName());
                ((ManageableMap) objects).addObject(elementId, item);
            }

        }

        return objects;
    }

    /**
     * @see AbstractCollectionConverterImpl#doIsNull(Session, Node, CollectionDescriptor, Class)
     *
     * return true If the parent node doesn't contains node based on the node type associated to the collection elements
     *
     */
    protected boolean doIsNull(Session session,
                                              Node parentNode,
                                              CollectionDescriptor collectionDescriptor,
                                              Class collectionFieldClass) throws RepositoryException {

        String elementClassName = collectionDescriptor.getElementClassName();
        ClassDescriptor elementClassDescriptor = mapper.getClassDescriptorByClass(ReflectionUtils.forName(elementClassName));
    QueryResult queryResult = getQuery(session, parentNode, elementClassDescriptor.getJcrType());
      return queryResult.getNodes().getSize() == 0;
    }

    private NodeIterator getCollectionNodes(Session session, Node parentNode, String itemNodeType)
    throws PathNotFoundException, ValueFormatException, RepositoryException {

        List collectionNodes = null;

        QueryResult queryResult = getQuery(session, parentNode, itemNodeType);
        return  queryResult.getNodes();

    }

    private void deleteCollectionItems(Session session, Node parentNode, String itemNodeType)
    throws VersionException,
           LockException,
           ConstraintViolationException,
           PathNotFoundException,
           ValueFormatException,
           RepositoryException
    {
        NodeIterator nodes = this.getCollectionNodes(session, parentNode, itemNodeType);
        if (nodes == null || nodes.getSize()==0) return;

        while (nodes.hasNext()) {
            Node node = (Node) nodes.next();
            node.remove();
        }
    }



  private QueryResult getQuery(Session session, Node parentNode, String jcrNodeType) throws RepositoryException, InvalidQueryException {
      String jcrExpression= "";
      if (!parentNode.getPath().startsWith("/jcr:system/jcr:versionStorage"))
      {
            jcrExpression = "SELECT * FROM " + jcrNodeType + " WHERE jcr:path LIKE '" + parentNode.getPath()
                                       + "/%' AND NOT jcr:path LIKE '" + parentNode.getPath() + "/%/%'";
            //FIXME: for doIsNull(..) only need to know if there are attributes or childnodes, queryResult.getNodes().getSize() delivers -1
            jcrExpression += " order by jcr:path";
      }
      else
      {

        jcrExpression = "SELECT * FROM nt:frozenNode" + " WHERE jcr:path LIKE '" + parentNode.getPath() + "/%'"
                         + " AND NOT jcr:path LIKE '" + parentNode.getPath() + "/%/%'"
                         + " AND jcr:frozenPrimaryType = '" + jcrNodeType + "'";


      }
        @SuppressWarnings("deprecation")
        Query jcrQuery = session.getWorkspace().getQueryManager().createQuery(jcrExpression, javax.jcr.query.Query.SQL);
        QueryResult queryResult = jcrQuery.execute();
    return queryResult;
  }
}
TOP

Related Classes of org.apache.jackrabbit.ocm.manager.collectionconverter.impl.NTCollectionConverterImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.