com.impetus.client.neo4j.GraphEntityMapper.java Source code

Java tutorial

Introduction

Here is the source code for com.impetus.client.neo4j.GraphEntityMapper.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.client.neo4j;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.persistence.PersistenceException;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.commons.lang.StringUtils;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.graphdb.index.ReadableIndex;
import org.neo4j.graphdb.index.UniqueFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.client.neo4j.index.Neo4JIndexManager;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.Relation;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.utils.KunderaCoreUtils;
import com.impetus.kundera.utils.ReflectUtils;

/**
 * Responsible for converting Neo4J graph (nodes+relationships) into JPA
 * entities and vice versa
 * 
 * @author amresh.singh
 */
public final class GraphEntityMapper {
    /** Separator between constituents of composite key */
    private static final String COMPOSITE_KEY_SEPARATOR = "$CKS$";

    private static final String PROXY_NODE_TYPE_KEY = "$NODE_TYPE$";

    private static final String PROXY_NODE_VALUE = "$PROXY_NODE$";

    /** The log. */
    private static Logger log = LoggerFactory.getLogger(GraphEntityMapper.class);

    private Neo4JIndexManager indexer;

    private KunderaMetadata kunderaMetadata;

    public GraphEntityMapper(Neo4JIndexManager indexer, final KunderaMetadata kunderaMetadata) {
        this.indexer = indexer;
        this.kunderaMetadata = kunderaMetadata;
    }

    /**
     * Fetches(and converts) {@link Node} instance from Entity object If it's a
     * update operation, node is searched and attributes populated Otherwise
     * Node is created into database (replacing any existing node) with
     * attributes populated
     * 
     * @param id
     * 
     */
    public Node getNodeFromEntity(Object entity, Object key, GraphDatabaseService graphDb, EntityMetadata m,
            boolean isUpdate) {

        // Construct top level node first, making sure unique ID in the index
        Node node = null;
        if (!isUpdate) {
            node = getOrCreateNodeWithUniqueFactory(entity, key, m, graphDb);
        } else {

            node = searchNode(key, m, graphDb, true);
        }

        if (node != null) {
            populateNodeProperties(entity, m, node);
        }

        return node;
    }

    /**
     * Create "Proxy" nodes into Neo4J. Proxy nodes are defined as nodes in
     * Neo4J that refer to a record in some other database. They cater to
     * polyglot persistence cases.
     */
    public Node createProxyNode(Object sourceNodeId, Object targetNodeId, GraphDatabaseService graphDb,
            EntityMetadata sourceEntityMetadata, EntityMetadata targetEntityMetadata) {

        String sourceNodeIdColumnName = ((AbstractAttribute) sourceEntityMetadata.getIdAttribute())
                .getJPAColumnName();
        String targetNodeIdColumnName = ((AbstractAttribute) targetEntityMetadata.getIdAttribute())
                .getJPAColumnName();

        Node node = graphDb.createNode();
        node.setProperty(PROXY_NODE_TYPE_KEY, PROXY_NODE_VALUE);
        node.setProperty(sourceNodeIdColumnName, sourceNodeId);
        node.setProperty(targetNodeIdColumnName, targetNodeId);
        return node;
    }

    /**
     * 
     * Converts a {@link Node} instance to entity object
     */
    public Object getEntityFromNode(Node node, EntityMetadata m) {
        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(m.getPersistenceUnit());
        EntityType entityType = metaModel.entity(m.getEntityClazz());

        // Iterate over, entity attributes
        Set<Attribute> attributes = entityType.getSingularAttributes();

        Object entity = null;

        try {
            // entity = m.getEntityClazz().newInstance();

            for (Attribute attribute : attributes) {
                Field field = (Field) attribute.getJavaMember();
                String columnName = ((AbstractAttribute) attribute).getJPAColumnName();

                // Set Entity level properties
                if (metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())
                        && m.getIdAttribute().getJavaType().equals(field.getType())) {
                    Object idValue = deserializeIdAttributeValue(m, (String) node.getProperty(columnName));
                    if (idValue != null) {
                        entity = initialize(m, entity);
                        PropertyAccessorHelper.set(entity, field, idValue);
                    }
                } else if (!attribute.isCollection() && !attribute.isAssociation()
                        && !((AbstractAttribute) m.getIdAttribute()).getJPAColumnName().equals(columnName)) {
                    Object columnValue = node.getProperty(columnName, null);
                    if (columnValue != null) {
                        entity = initialize(m, entity);
                        PropertyAccessorHelper.set(entity, field, fromNeo4JObject(columnValue, field));
                    }
                }
            }

            if (entity != null && !metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())) {
                Object rowKey = node.getProperty(((AbstractAttribute) m.getIdAttribute()).getJPAColumnName());
                if (rowKey != null) {
                    PropertyAccessorHelper.setId(entity, m,
                            fromNeo4JObject(rowKey, (Field) m.getIdAttribute().getJavaMember()));
                }
            }
        } catch (NotFoundException e) {
            log.info(e.getMessage());
            return null;
        }

        return entity;
    }

    /**
     * 
     * Converts a {@link Relationship} object to corresponding entity object
     */
    public Object getEntityFromRelationship(Relationship relationship, EntityMetadata topLevelEntityMetadata,
            Relation relation) {
        EntityMetadata relationshipEntityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
                relation.getMapKeyJoinClass());

        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(relationshipEntityMetadata.getPersistenceUnit());
        EntityType entityType = metaModel.entity(relationshipEntityMetadata.getEntityClazz());

        // Iterate over, entity attributes
        Set<Attribute> attributes = entityType.getSingularAttributes();

        Object entity = null;

        try {
            // entity =
            // relationshipEntityMetadata.getEntityClazz().newInstance();

            for (Attribute attribute : attributes) {
                Field field = (Field) attribute.getJavaMember();
                String columnName = ((AbstractAttribute) attribute).getJPAColumnName();

                // Set Entity level properties
                if (metaModel.isEmbeddable(relationshipEntityMetadata.getIdAttribute().getBindableJavaType())
                        && relationshipEntityMetadata.getIdAttribute().getJavaType().equals(field.getType())) {
                    Object idValue = deserializeIdAttributeValue(relationshipEntityMetadata,
                            (String) relationship.getProperty(columnName));
                    if (idValue != null) {
                        entity = initialize(relationshipEntityMetadata, entity);
                        PropertyAccessorHelper.set(entity, field, idValue);
                    }
                } else if (!attribute.isCollection() && !attribute.isAssociation()
                        && !field.getType().equals(topLevelEntityMetadata.getEntityClazz())
                        && !field.getType().equals(relation.getTargetEntity())) {
                    Object value = relationship.getProperty(columnName, null);
                    if (value != null) {
                        entity = initialize(relationshipEntityMetadata, entity);
                        PropertyAccessorHelper.set(entity, field, fromNeo4JObject(value, field));
                    }
                }
            }

            if (entity != null
                    && !metaModel.isEmbeddable(relationshipEntityMetadata.getIdAttribute().getBindableJavaType())) {
                Object rowKey = relationship.getProperty(
                        ((AbstractAttribute) relationshipEntityMetadata.getIdAttribute()).getJPAColumnName());
                if (rowKey != null) {
                    PropertyAccessorHelper.setId(entity, relationshipEntityMetadata, fromNeo4JObject(rowKey,
                            (Field) relationshipEntityMetadata.getIdAttribute().getJavaMember()));
                }
            }
        } catch (NotFoundException e) {
            log.info(e.getMessage());
            return null;
        }

        return entity;
    }

    /**
     * Creates a Map containing all properties (and their values) for a given
     * entity
     * 
     * @param entity
     * @param m
     * @return
     */
    public Map<String, Object> createNodeProperties(Object entity, EntityMetadata m) {
        Map<String, Object> props = new HashMap<String, Object>();

        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(m.getPersistenceUnit());

        EntityType entityType = metaModel.entity(m.getEntityClazz());

        // Iterate over entity attributes
        Set<Attribute> attributes = entityType.getSingularAttributes();
        for (Attribute attribute : attributes) {
            Field field = (Field) attribute.getJavaMember();

            // Set Node level properties
            if (!attribute.isCollection() && !attribute.isAssociation()) {

                String columnName = ((AbstractAttribute) attribute).getJPAColumnName();
                Object value = PropertyAccessorHelper.getObject(entity, field);
                if (value != null) {
                    props.put(columnName, toNeo4JProperty(value));
                }
            }
        }
        return props;
    }

    /**
     * Populates Node properties from Entity object
     * 
     * @param entity
     * @param m
     * @param node
     */
    private void populateNodeProperties(Object entity, EntityMetadata m, Node node) {
        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(m.getPersistenceUnit());
        EntityType entityType = metaModel.entity(m.getEntityClazz());

        // Iterate over entity attributes
        Set<Attribute> attributes = entityType.getSingularAttributes();
        for (Attribute attribute : attributes) {
            Field field = (Field) attribute.getJavaMember();

            // Set Node level properties
            if (!attribute.isCollection() && !attribute.isAssociation()
                    && !((SingularAttribute) attribute).isId()) {
                String columnName = ((AbstractAttribute) attribute).getJPAColumnName();
                Object value = PropertyAccessorHelper.getObject(entity, field);
                if (value != null) {
                    node.setProperty(columnName, toNeo4JProperty(value));
                }
            }
        }
    }

    /**
     * Populates a {@link Relationship} with attributes of a given relationship
     * entity object <code>relationshipObj</code>
     * 
     * @param entityMetadata
     * @param targetNodeMetadata
     * @param relationship
     * @param relationshipObj
     */
    public void populateRelationshipProperties(EntityMetadata entityMetadata, EntityMetadata targetNodeMetadata,
            Relationship relationship, Object relationshipObj) {
        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(entityMetadata.getPersistenceUnit());
        EntityType entityType = metaModel.entity(relationshipObj.getClass());

        Set<Attribute> attributes = entityType.getSingularAttributes();
        for (Attribute attribute : attributes) {
            Field f = (Field) attribute.getJavaMember();
            if (!f.getType().equals(entityMetadata.getEntityClazz())
                    && !f.getType().equals(targetNodeMetadata.getEntityClazz())) {
                EntityMetadata relMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
                        relationshipObj.getClass());
                String columnName = ((AbstractAttribute) attribute).getJPAColumnName();
                if (metaModel.isEmbeddable(relMetadata.getIdAttribute().getBindableJavaType())
                        && ((SingularAttribute) attribute).isId()) {
                    // Populate Embedded attribute value into relationship
                    Object id = PropertyAccessorHelper.getId(relationshipObj, relMetadata);
                    Object serializedIdValue = serializeIdAttributeValue(relMetadata, metaModel, id);
                    relationship.setProperty(columnName, serializedIdValue);

                    // Populate attributes of embedded fields into relationship
                    Set<Attribute> embeddableAttributes = metaModel
                            .embeddable(relMetadata.getIdAttribute().getBindableJavaType()).getSingularAttributes();
                    for (Attribute embeddableAttribute : embeddableAttributes) {
                        String embeddedColumn = ((AbstractAttribute) embeddableAttribute).getJPAColumnName();
                        if (embeddedColumn == null)
                            embeddedColumn = embeddableAttribute.getName();
                        Object value = PropertyAccessorHelper.getObject(id,
                                (Field) embeddableAttribute.getJavaMember());

                        if (value != null)
                            relationship.setProperty(embeddedColumn, value);
                    }
                } else {
                    Object value = PropertyAccessorHelper.getObject(relationshipObj, f);
                    relationship.setProperty(columnName, toNeo4JProperty(value));
                }

            }
        }

    }

    /**
     * Creates a Map containing all properties (and their values) for a given
     * relationship entity
     * 
     * @param entityMetadata
     * @param targetEntityMetadata
     * @param relationshipProperties
     * @param relationshipEntity
     */
    public Map<String, Object> createRelationshipProperties(EntityMetadata entityMetadata,
            EntityMetadata targetEntityMetadata, Object relationshipEntity) {
        MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(entityMetadata.getPersistenceUnit());
        EntityType entityType = metaModel.entity(relationshipEntity.getClass());
        Map<String, Object> relationshipProperties = new HashMap<String, Object>();

        Set<Attribute> attributes = entityType.getSingularAttributes();
        for (Attribute attribute : attributes) {
            Field f = (Field) attribute.getJavaMember();
            if (!f.getType().equals(entityMetadata.getEntityClazz())
                    && !f.getType().equals(targetEntityMetadata.getEntityClazz())) {
                String relPropertyName = ((AbstractAttribute) attribute).getJPAColumnName();
                Object value = PropertyAccessorHelper.getObject(relationshipEntity, f);
                relationshipProperties.put(relPropertyName, toNeo4JProperty(value));
            }
        }
        return relationshipProperties;
    }

    /**
     * 
     * Gets (if available) or creates a node for the given entity
     */
    private Node getOrCreateNodeWithUniqueFactory(final Object entity, final Object id, final EntityMetadata m,
            GraphDatabaseService graphDb) {
        final String idColumnName = ((AbstractAttribute) m.getIdAttribute()).getJPAColumnName();
        final MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(m.getPersistenceUnit());
        final String idUniqueValue = serializeIdAttributeValue(m, metaModel, id);

        UniqueFactory<Node> factory = new UniqueFactory.UniqueNodeFactory(graphDb, m.getIndexName()) {
            /**
             * Initialize ID attribute
             */
            @Override
            protected void initialize(Node created, Map<String, Object> properties) {
                // Set Embeddable ID attribute
                if (metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())) {
                    // Populate embedded field value in serialized format
                    created.setProperty(idColumnName, idUniqueValue);

                    // Populated all other attributes of embedded into this node
                    Set<Attribute> embeddableAttributes = metaModel
                            .embeddable(m.getIdAttribute().getBindableJavaType()).getSingularAttributes();
                    for (Attribute attribute : embeddableAttributes) {
                        String columnName = ((AbstractAttribute) attribute).getJPAColumnName();
                        if (columnName == null)
                            columnName = attribute.getName();
                        Object value = PropertyAccessorHelper.getObject(id, (Field) attribute.getJavaMember());

                        if (value != null)
                            created.setProperty(columnName, value);
                    }
                } else {
                    created.setProperty(idColumnName, properties.get(idColumnName));
                }

            }
        };

        if (metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())) {
            return factory.getOrCreate(idColumnName, idUniqueValue);
        } else {
            return factory.getOrCreate(idColumnName, id);
        }

    }

    /**
     * Prepares ID column value for embedded IDs by combining its attributes
     * 
     * @param m
     * @param id
     * @param metaModel
     * @return
     */
    private String serializeIdAttributeValue(final EntityMetadata m, MetamodelImpl metaModel, Object id) {
        if (!metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())) {
            return null;
        }

        Class<?> embeddableClass = m.getIdAttribute().getBindableJavaType();
        String idUniqueValue = "";

        for (Field embeddedField : embeddableClass.getDeclaredFields()) {
            if (!ReflectUtils.isTransientOrStatic(embeddedField)) {

                Object value = PropertyAccessorHelper.getObject(id, embeddedField);
                if (value != null && !StringUtils.isEmpty(value.toString()))
                    idUniqueValue = idUniqueValue + value + COMPOSITE_KEY_SEPARATOR;
            }
        }

        if (idUniqueValue.endsWith(COMPOSITE_KEY_SEPARATOR))
            idUniqueValue = idUniqueValue.substring(0, idUniqueValue.length() - COMPOSITE_KEY_SEPARATOR.length());
        return idUniqueValue;
    }

    /**
     * Prepares Embedded ID field from value prepared via
     * serializeIdAttributeValue method.
     */
    private Object deserializeIdAttributeValue(final EntityMetadata m, String idValue) {
        if (idValue == null) {
            return null;
        }
        Class<?> embeddableClass = m.getIdAttribute().getBindableJavaType();
        Object embeddedObject = embeddedObject = KunderaCoreUtils.createNewInstance(embeddableClass);
        List<String> tokens = new ArrayList<String>();
        StringTokenizer st = new StringTokenizer((String) idValue, COMPOSITE_KEY_SEPARATOR);
        while (st.hasMoreTokens()) {
            tokens.add((String) st.nextElement());
        }

        int count = 0;
        for (Field embeddedField : embeddableClass.getDeclaredFields()) {
            if (!ReflectUtils.isTransientOrStatic(embeddedField)) {
                if (count < tokens.size()) {
                    String value = tokens.get(count++);
                    PropertyAccessorHelper.set(embeddedObject, embeddedField, value);
                }
            }
        }
        return embeddedObject;
    }

    /**
     * Gets (if available) or creates a relationship for the given entity
     */
    private Relationship getOrCreateRelationshipWithUniqueFactory(Object entity, EntityMetadata m,
            GraphDatabaseService graphDb) {
        Object id = PropertyAccessorHelper.getObject(entity, (Field) m.getIdAttribute().getJavaMember());
        final String idFieldName = m.getIdAttribute().getName();

        UniqueFactory<Relationship> factory = new UniqueFactory.UniqueRelationshipFactory(graphDb,
                m.getIndexName()) {

            @Override
            protected Relationship create(Map<String, Object> paramMap) {
                return null;
            }

            @Override
            protected void initialize(Relationship relationship, Map<String, Object> properties) {
                relationship.setProperty(idFieldName, properties.get(idFieldName));
            }
        };

        return factory.getOrCreate(idFieldName, id);
    }

    /**
     * Converts a given field value to an object that is Neo4J compatible
     * 
     * @param source
     * @return
     */
    public Object toNeo4JProperty(Object source) {
        if (source instanceof BigDecimal || source instanceof BigInteger) {
            return source.toString();
        } else if ((source instanceof Calendar) || (source instanceof GregorianCalendar)) {
            return PropertyAccessorHelper.fromSourceToTargetClass(String.class, Date.class,
                    ((Calendar) source).getTime());
        }
        if (source instanceof Date) {
            Class<?> sourceClass = source.getClass();
            return PropertyAccessorHelper.fromSourceToTargetClass(String.class, sourceClass, source);
        }
        return source;
    }

    /**
     * Converts a property stored in Neo4J (nodes or relationship) to
     * corresponding entity field value
     */
    public Object fromNeo4JObject(Object source, Field field) {
        Class<?> targetClass = field.getType();

        if (targetClass.isAssignableFrom(BigDecimal.class) || targetClass.isAssignableFrom(BigInteger.class)) {
            return PropertyAccessorHelper.fromSourceToTargetClass(field.getType(), source.getClass(), source);
        } else if (targetClass.isAssignableFrom(Calendar.class)
                || targetClass.isAssignableFrom(GregorianCalendar.class)) {
            Date d = (Date) PropertyAccessorHelper.fromSourceToTargetClass(Date.class, source.getClass(), source);
            Calendar cal = Calendar.getInstance();
            cal.setTime(d);
            return cal;
        } else if (targetClass.isAssignableFrom(Date.class)) {
            return PropertyAccessorHelper.fromSourceToTargetClass(field.getType(), source.getClass(), source);
        } else {
            return source;
        }

    }

    /**
     * Searches a node from the database for a given key
     */
    public Node searchNode(Object key, EntityMetadata m, GraphDatabaseService graphDb, boolean skipProxy) {
        Node node = null;
        String idColumnName = ((AbstractAttribute) m.getIdAttribute()).getJPAColumnName();

        final MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata()
                .getMetamodel(m.getPersistenceUnit());
        if (metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType())) {
            key = serializeIdAttributeValue(m, metaModel, key);
        }

        if (indexer.isNodeAutoIndexingEnabled(graphDb)) {
            // Get the Node auto index
            ReadableIndex<Node> autoNodeIndex = graphDb.index().getNodeAutoIndexer().getAutoIndex();
            IndexHits<Node> nodesFound = autoNodeIndex.get(idColumnName, key);
            node = getMatchingNodeFromIndexHits(nodesFound, skipProxy);
        } else {
            // Searching within manually created indexes
            Index<Node> nodeIndex = graphDb.index().forNodes(m.getIndexName());
            IndexHits<Node> nodesFound = nodeIndex.get(idColumnName, key);
            node = getMatchingNodeFromIndexHits(nodesFound, skipProxy);
        }

        return node;
    }

    /**
     * Fetches first Non-proxy node from Index Hits
     * 
     * @param skipProxy
     * @param nodesFound
     * @return
     */
    protected Node getMatchingNodeFromIndexHits(IndexHits<Node> nodesFound, boolean skipProxy) {
        Node node = null;
        try {
            if (nodesFound == null || nodesFound.size() == 0 || !nodesFound.hasNext()) {
                return null;
            } else {
                if (skipProxy)
                    node = getNonProxyNode(nodesFound);
                else
                    node = nodesFound.next();
            }
        } finally {
            nodesFound.close();
        }
        return node;
    }

    /**
     * Fetches Non-proxy nodes from index hits
     */
    private Node getNonProxyNode(IndexHits<Node> nodesFound) {
        Node node = null;
        if (nodesFound.hasNext()) {
            node = nodesFound.next();
        } else {
            return null;
        }

        try {
            Object proxyNodeProperty = node.getProperty(PROXY_NODE_TYPE_KEY);
        } catch (NotFoundException e) {
            return node;
        } catch (IllegalStateException e) {
            return node;
        }
        return getNonProxyNode(nodesFound);
    }

    /**
     * 
     * @param m
     * @param entity
     * @param id
     * @return
     */
    private Object initialize(EntityMetadata m, Object entity) {
        try {
            if (entity == null) {
                entity = KunderaCoreUtils.createNewInstance(m.getEntityClazz());
            }

            return entity;
        } catch (Exception e) {
            throw new PersistenceException("Error occured while instantiating entity, Caused by : ", e);
        }
    }
}