com.impetus.kundera.persistence.EntityResolver.java Source code

Java tutorial

Introduction

Here is the source code for com.impetus.kundera.persistence.EntityResolver.java

Source

/*******************************************************************************
 * * Copyright 2012 Impetus Infotech.
 *  *
 *  * Licensed 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 com.impetus.kundera.persistence;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.CascadeType;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.Relation;
import com.impetus.kundera.property.PropertyAccessException;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.proxy.EnhancedEntity;

/**
 * The Class EntityReachabilityResolver.
 * 
 * @author animesh.kumar
 */
public class EntityResolver {

    /** The Constant log. */
    private static final Log LOG = LogFactory.getLog(EntityResolver.class);

    /**
     * Resolve all reachable entities from entity.
     * 
     * @param entity
     *            the entity
     * @param cascadeType
     *            the cascade type
     * @param persistenceUnits
     *            the persistence units
     * @return the all reachable entities
     */
    public static List<EnhancedEntity> resolve(Object entity, CascadeType cascadeType) {
        Map<String, EnhancedEntity> map = new LinkedHashMap<String, EnhancedEntity>();
        try {
            LOG.debug("Resolving reachable entities for cascade " + cascadeType);

            recursivelyResolveEntities(entity, cascadeType, map);

        } catch (PropertyAccessException e) {
            throw new ReaderResolverException(e);
        }

        if (LOG.isDebugEnabled()) {
            for (Map.Entry<String, EnhancedEntity> entry : map.entrySet()) {
                LOG.debug(
                        "Entity => " + entry.getKey() + ", ForeignKeys => " + entry.getValue().getForeignKeysMap());
            }
        }

        return new ArrayList<EnhancedEntity>(map.values());
    }

    /**
     * helper method to recursively build reachable object list.
     * 
     * @param object
     *            the o
     * @param cascadeType
     *            the cascade type
     * @param entities
     *            the entities
     * @param persistenceUnits
     *            the persistence units
     * @return the all reachable entities
     * @throws PropertyAccessException
     *             the property access exception
     */
    private static void recursivelyResolveEntities(Object object, CascadeType cascadeType,
            Map<String, EnhancedEntity> entities) throws PropertyAccessException {

        EntityMetadata entityMetaData = null;
        entityMetaData = KunderaMetadataManager.getEntityMetadata(object.getClass());

        if (entityMetaData == null) {
            return;
        }

        String id = PropertyAccessorHelper.getId(object, entityMetaData);

        // Ensure that @Id is set
        if (null == id || id.trim().isEmpty()) {
            throw new ReaderResolverException("Missing primary key >> " + entityMetaData.getEntityClazz().getName()
                    + "#" + entityMetaData.getIdColumn().getField().getName());
        }

        // Dummy name to check if the object is already processed
        String mapKeyForEntity = entityMetaData.getEntityClazz().getName() + "_" + id;

        if (entities.containsKey(mapKeyForEntity)) {
            return;
        }

        LOG.debug("Resolving >> " + mapKeyForEntity);

        // Map to hold property-name=>foreign-entity relations
        Map<String, Set<String>> foreignKeysMap = new HashMap<String, Set<String>>();

        // Save to map
        entities.put(mapKeyForEntity, getEnhancedEntity(object, id, foreignKeysMap));

        // Iterate over EntityMetata.Relation relations
        for (Relation relation : entityMetaData.getRelations()) {

            // Cascade?
            if (!relation.getCascades().contains(CascadeType.ALL)
                    && !relation.getCascades().contains(cascadeType)) {
                continue;
            }

            // Target entity
            Class<?> targetClass = relation.getTargetEntity();
            // Mapped to this property
            Field targetField = relation.getProperty();
            // Is it optional?
            boolean optional = relation.isOptional();

            // Value
            Object value = PropertyAccessorHelper.getObject(object, targetField);

            // if object is not null, then proceed
            if (null != value) {
                EntityMetadata relMetadata = KunderaMetadataManager.getEntityMetadata(targetClass);

                if (relation.isUnary()) {
                    // Unary relation will have single target object.
                    String targetId = PropertyAccessorHelper.getId(value, relMetadata);

                    Set<String> foreignKeys = new HashSet<String>();

                    foreignKeys.add(targetId);
                    // put to map
                    foreignKeysMap.put(targetField.getName(), foreignKeys);

                    // get all other reachable objects from object "value"
                    recursivelyResolveEntities(value, cascadeType, entities);

                }
                if (relation.isCollection()) {
                    // Collection relation can have many target objects.

                    // Value must map to Collection interface.
                    @SuppressWarnings("unchecked")
                    Collection collection = (Collection) value;

                    Set<String> foreignKeys = new HashSet<String>();

                    // Iterate over each Object and get the @Id
                    for (Object o_ : collection) {
                        String targetId = PropertyAccessorHelper.getId(o_, relMetadata);

                        foreignKeys.add(targetId);

                        // Get all other reachable objects from "o_"
                        recursivelyResolveEntities(o_, cascadeType, entities);
                    }
                    foreignKeysMap.put(targetField.getName(), foreignKeys);
                }
            }

            // if the value is null
            else {
                // halt, if this was a non-optional property
                if (!optional) {
                    throw new ReaderResolverException(
                            "Missing " + targetClass.getName() + "." + targetField.getName());
                }
            }
        }
    }

    /**
     * Gets the enhanced entity.
     * 
     * @param entity
     *            the entity
     * @param id
     *            the id
     * @param foreignKeyMap
     *            the foreign key map
     * @return the enhanced entity
     */
    public static EnhancedEntity getEnhancedEntity(Object entity, String id,
            Map<String, Set<String>> foreignKeyMap) {
        return KunderaMetadataManager.getEntityEnhancerFactory().getProxy(entity, id, foreignKeyMap);
    }
}