Package com.impetus.kundera.graph

Source Code of com.impetus.kundera.graph.GraphGenerator

/**
* Copyright 2013 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.graph;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.persistence.GeneratedValue;

import com.impetus.kundera.graph.NodeLink.LinkProperty;
import com.impetus.kundera.lifecycle.states.NodeState;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.MetadataUtils;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.Relation;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.IdGenerator;
import com.impetus.kundera.persistence.PersistenceDelegator;
import com.impetus.kundera.persistence.PersistenceValidator;
import com.impetus.kundera.persistence.context.PersistenceCache;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.proxy.ProxyHelper;
import com.impetus.kundera.validation.rules.NullOrInvalidEntityRule;
import com.impetus.kundera.validation.rules.PrimaryKeyNullCheck;

/**
* @author vivek.mishra
*
*         Responsible for:
*
*         1. Do pre-checks a) validation entity b) set id c) check for shared
*         via primary key { on parse relation } d) dirty check { on associated
*         and self entity }
*
*         2. Parse through relations and relational objects.
*
*         3. Recursively process transitive relations
*/
public final class GraphGenerator
{

    private GraphBuilder builder = new GraphBuilder();

    Set<Node> traversedNodes = new HashSet<Node>();

    private PersistenceValidator validator = new PersistenceValidator();

    /**
     * Generate entity graph and returns after assigning headnode. n
     *
     * @param entity
     *            entity.
     * @param delegator
     *            delegator
     * @param pc
     *            persistence cache
     * @return object graph.
     */
    public <E> ObjectGraph generateGraph(E entity, PersistenceDelegator delegator)
    {
        this.builder.assign(this);
        Node node = generate(entity, delegator, delegator.getPersistenceCache(), null);
        this.builder.assignHeadNode(node);
        return this.builder.getGraph();
    }

    // TODO: Till the time issue populating all objects via cache is not yet
    // solved.
    // keep this method alive!

    /**
     * Generate entity graph and returns after assigning headnode. n
     *
     * @param entity
     *            entity.
     * @param delegator
     *            delegator
     * @param pc
     *            persistence cache
     * @return object graph.
     */
    public <E> ObjectGraph generateGraph(E entity, PersistenceDelegator delegator, NodeState state)
    {

        this.builder.assign(this);
        Node node = generate(entity, delegator, delegator.getPersistenceCache(), state);
        this.builder.assignHeadNode(node);
        return this.builder.getGraph();
    }

    /**
     * Generate graph for head node. <li>traverse through it's relational
     * entities recursively
     *
     * @param entity
     *            entity object
     * @param delegator
     *            delegator object
     * @param pc
     *            persistence cache
     * @return head node
     */
    <E> Node generate(E entity, PersistenceDelegator delegator, PersistenceCache pc, NodeState state)
    {

        EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(delegator.getKunderaMetadata(),
                entity.getClass());

        if (!new NullOrInvalidEntityRule<E>(entityMetadata).validate(entity))
        {
            Object entityId = onPreChecks(entity, delegator);

            // TODO::check for composite key.
            Node node = builder.buildNode(entity, delegator, entityId, state);

            node = traverseNode(entity, delegator, pc, entityId, node);

            return node;
        }

        return null;
    }

    private <E> Node traverseNode(E entity, PersistenceDelegator delegator, PersistenceCache pc, Object entityId,
            Node node)
    {
        if (node != null && !traversedNodes.contains(node))
        {
            EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(delegator.getKunderaMetadata(),
                    entity.getClass());

            // parse relations

            for (Relation relation : entityMetadata.getRelations())
            {
                if (relation != null)
                {
                    Object childObject = PropertyAccessorHelper.getObject(entity, relation.getProperty());

                    // if child object is valid and not a proxy
                    if (childObject != null && !ProxyHelper.isProxyOrCollection(childObject))
                    {
                        // check for join by primary key, collection and map
                        EntityMetadata childMetadata = KunderaMetadataManager.getEntityMetadata(
                                delegator.getKunderaMetadata(),
                                PropertyAccessorHelper.getGenericClass(relation.getProperty()));

                        // set id,in case joined by primary key.
                        childObject = onIfSharedByPK(relation, childObject, childMetadata, entityId);

                        node = builder.getRelationBuilder(childObject, relation, node)
                                .assignResources(delegator, pc, childMetadata).build().getNode();
                    }
                }
            }

            // node.setGraphCompleted(true);
            traversedNodes.add(node);
        }
        return node;
    }

    /**
     * Check and set if relation is set via primary key.
     *
     * @param relation
     *            relation
     * @param childObject
     *            target entity
     * @param childMetadata
     *            target entity metadata
     * @param entityId
     *            entity id
     * @return target entity.
     */
    private Object onIfSharedByPK(Relation relation, Object childObject, EntityMetadata childMetadata, Object entityId)
    {
        if (relation.isJoinedByPrimaryKey())
        {
            PropertyAccessorHelper.setId(childObject, childMetadata, entityId);
        }

        return childObject;
    }

    /**
     * On pre checks before generating graph. performed checks: <li>Check if
     * entity is valid.</li> <li>generated and set id in case
     * {@link GeneratedValue} is present and not set.</li> <li>Check if primary
     * key is not null.</li>
     *
     *
     * @param entity
     *            entity
     * @param client
     *            client
     * @return entity id
     */
    private <E> Object onPreChecks(E entity, PersistenceDelegator delegator)
    {
        // pre validation.
        // check if entity is Null or with Invalid meta data!
        Object id = null;

        EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(delegator.getKunderaMetadata(),
                entity.getClass());
        id = PropertyAccessorHelper.getId(entity, entityMetadata);

        // set id, in case of auto generation and still not set.

        if (ObjectGraphUtils.onAutoGenerateId((Field) entityMetadata.getIdAttribute().getJavaMember(), id))
        {
            id = new IdGenerator().generateAndSetId(entity, entityMetadata, delegator, delegator.getKunderaMetadata());
        }

        // check if id is set or not.
        new PrimaryKeyNullCheck<Object>().validate(id);

        validator.validate(entity, delegator.getKunderaMetadata());

        // }

        return id;
    }

    /**
     * On building child node
     *
     * @param childObject
     *            child object
     * @param childMetadata
     *            child metadata
     * @param delegator
     *            persistence delegator
     * @param pc
     *            persistence cache
     * @param node
     *            node
     * @param relation
     *            entity relation
     */
    void onBuildChildNode(Object childObject, EntityMetadata childMetadata, PersistenceDelegator delegator,
            PersistenceCache pc, Node node, Relation relation)
    {
        Node childNode = generate(childObject, delegator, pc, null);
        if (childNode != null)
        {
            assignNodeLinkProperty(node, relation, childNode);
        }
    }

    /**
     * On assigning node link properties
     *
     * @param node
     *            node
     * @param relation
     *            relation
     * @param childNode
     *            child node
     */
    private void assignNodeLinkProperty(Node node, Relation relation, Node childNode)
    {
        // Construct Node Link for this relationship
        NodeLink nodeLink = new NodeLink(node.getNodeId(), childNode.getNodeId());
        setLink(node, relation, childNode, nodeLink);
    }

    /**
     * Set link property
     *
     * @param node
     *            node
     * @param relation
     *            relation
     * @param childNode
     *            target node
     * @param nodeLink
     *            node link(bridge)
     */
    void setLink(Node node, Relation relation, Node childNode, NodeLink nodeLink)
    {
        nodeLink.setMultiplicity(relation.getType());

        EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(node.getPersistenceDelegator()
                .getKunderaMetadata(), node.getDataClass());
        nodeLink.setLinkProperties(getLinkProperties(metadata, relation, node.getPersistenceDelegator()
                .getKunderaMetadata()));

        // Add Parent node to this child
        childNode.addParentNode(nodeLink, node);

        // Add child node to this node
        node.addChildNode(nodeLink, childNode);
    }

    /**
     *
     * @param metadata
     *            Entity metadata of the parent node
     * @param relation
     * @return
     */
    private Map<LinkProperty, Object> getLinkProperties(EntityMetadata metadata, Relation relation,
            final KunderaMetadata kunderaMetadata)
    {
        Map<LinkProperty, Object> linkProperties = new HashMap<NodeLink.LinkProperty, Object>();

        linkProperties.put(LinkProperty.LINK_NAME, MetadataUtils.getMappedName(metadata, relation, kunderaMetadata));
        linkProperties.put(LinkProperty.IS_SHARED_BY_PRIMARY_KEY, relation.isJoinedByPrimaryKey());
        linkProperties.put(LinkProperty.IS_BIDIRECTIONAL, !relation.isUnary());
        linkProperties.put(LinkProperty.IS_RELATED_VIA_JOIN_TABLE, relation.isRelatedViaJoinTable());
        linkProperties.put(LinkProperty.PROPERTY, relation.getProperty());
        linkProperties.put(LinkProperty.CASCADE, relation.getCascades());

        if (relation.isRelatedViaJoinTable())
        {
            linkProperties.put(LinkProperty.JOIN_TABLE_METADATA, relation.getJoinTableMetadata());
        }
        return linkProperties;
    }

}
TOP

Related Classes of com.impetus.kundera.graph.GraphGenerator

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.