com.impetus.kundera.mongodb.MongoDBDataHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.impetus.kundera.mongodb.MongoDBDataHandler.java

Source

/*
 * Copyright 2011 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.mongodb;

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

import javax.persistence.CascadeType;
import javax.persistence.PersistenceException;

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

import com.impetus.kundera.ejb.EntityManagerImpl;
import com.impetus.kundera.metadata.EntityMetadata;
import com.impetus.kundera.metadata.EntityMetadata.Column;
import com.impetus.kundera.metadata.EntityMetadata.Relation;
import com.impetus.kundera.property.PropertyAccessException;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
 * Provides utility methods for handling data held in MongoDB
 * @author amresh.singh
 */
public class MongoDBDataHandler {
    private static Log log = LogFactory.getLog(MongoDBDataHandler.class);

    public Object getEntityFromDocument(EntityManagerImpl em, Class<?> entityClass, EntityMetadata m,
            DBObject document) {
        Object entity = null;
        try {
            entity = entityClass.newInstance();

            //Populate entity columns
            List<Column> columns = m.getColumnsAsList();
            for (Column column : columns) {
                PropertyAccessorHelper.set(entity, column.getField(), document.get(column.getName()));
            }

            //Populate embedded relationship object
            List<Relation> relations = m.getRelations();

            for (Relation relation : relations) {
                Class<?> embeddedEntityClass = relation.getTargetEntity(); //Embedded entity class
                Field embeddedPropertyField = relation.getProperty(); //Mapped to this property               
                boolean optional = relation.isOptional(); // Is it optional? TODO: Where to use this?                           

                EntityMetadata relMetadata = em.getMetadataManager().getEntityMetadata(embeddedEntityClass);
                relMetadata.addColumn(relMetadata.getIdColumn().getName(), relMetadata.getIdColumn()); //Add PK column

                Object embeddedObject = document.get(embeddedPropertyField.getName());

                if (embeddedObject != null) {
                    if (relation.isUnary()) {
                        BasicDBObject relDBObj = (BasicDBObject) embeddedObject;
                        Object embeddedEntity = new MongoDBDataHandler().getEntityFromDocument(em,
                                embeddedEntityClass, relMetadata, relDBObj);
                        PropertyAccessorHelper.set(entity, embeddedPropertyField, embeddedEntity);
                    } else if (relation.isCollection()) {
                        BasicDBList relList = (BasicDBList) embeddedObject; //List of embedded objects

                        Collection<Object> embeddedEntities = null; //Collection of embedded entities
                        if (relation.getPropertyType().equals(Set.class)) {
                            embeddedEntities = new HashSet<Object>();
                        } else if (relation.getPropertyType().equals(List.class)) {
                            embeddedEntities = new ArrayList<Object>();
                        }

                        for (int i = 0; i < relList.size(); i++) {
                            BasicDBObject relObj = (BasicDBObject) relList.get(i);
                            Object embeddedEntity = new MongoDBDataHandler().getEntityFromDocument(em,
                                    embeddedEntityClass, relMetadata, relObj);
                            embeddedEntities.add(embeddedEntity);
                        }

                        PropertyAccessorHelper.set(entity, embeddedPropertyField, embeddedEntities);
                    }
                }

            }

        } catch (InstantiationException e) {
            log.error("Error while instantiating " + entityClass + ". Details:" + e.getMessage());
            return entity;
        } catch (IllegalAccessException e) {
            log.error("Error while Getting entity from Document. Details:" + e.getMessage());
            return entity;
        } catch (PropertyAccessException e) {
            log.error("Error while Getting entity from Document. Details:" + e.getMessage());
            return entity;
        }
        return entity;
    }

    public BasicDBObject getDocumentFromEntity(EntityManagerImpl em, EntityMetadata m, Object entity)
            throws PropertyAccessException {
        List<Column> columns = m.getColumnsAsList();
        BasicDBObject dbObj = new BasicDBObject();

        //Populate columns
        for (Column column : columns) {
            try {
                extractEntityField(entity, dbObj, column);
            } catch (PropertyAccessException e1) {
                log.error("Can't access property " + column.getField().getName());
            }
        }

        //Populate Relationship fields
        List<Relation> relations = m.getRelations();
        for (Relation relation : relations) {
            // Cascade?
            if (!relation.getCascades().contains(CascadeType.ALL)
                    && !relation.getCascades().contains(CascadeType.PERSIST)) {
                continue;
            }

            Class<?> embeddedEntityClass = relation.getTargetEntity(); //Target entity
            Field embeddedEntityField = relation.getProperty(); //Mapped to this property         
            boolean optional = relation.isOptional(); // Is it optional         
            Object embeddedObject = PropertyAccessorHelper.getObject(entity, embeddedEntityField); // Value         

            EntityMetadata relMetadata = em.getMetadataManager().getEntityMetadata(embeddedEntityClass);
            relMetadata.addColumn(relMetadata.getIdColumn().getName(), relMetadata.getIdColumn()); //Add PK column

            if (embeddedObject == null) {
                if (!optional) {
                    throw new PersistenceException(
                            "Field " + embeddedEntityField + " is not optional, and hence must be set.");
                }

            } else {
                if (relation.isUnary()) {
                    BasicDBObject relDBObj = getDocumentFromEntity(em, relMetadata, embeddedObject);
                    dbObj.put(embeddedEntityField.getName(), relDBObj);

                } else if (relation.isCollection()) {
                    Collection collection = (Collection) embeddedObject;
                    BasicDBObject[] relDBObjects = new BasicDBObject[collection.size()];
                    int count = 0;
                    for (Object o : collection) {
                        relDBObjects[count] = getDocumentFromEntity(em, relMetadata, o);
                        count++;
                    }
                    dbObj.put(embeddedEntityField.getName(), relDBObjects);
                }

            }

        }
        return dbObj;
    }

    /**
     * @param entity
     * @param dbObj
     * @param column
     * @throws PropertyAccessException
     */
    private void extractEntityField(Object entity, BasicDBObject dbObj, Column column)
            throws PropertyAccessException {
        //A column field may be a collection(not defined as 1-to-M relationship)
        if (column.getField().getType().equals(List.class) || column.getField().getType().equals(Set.class)) {
            Collection collection = (Collection) PropertyAccessorHelper.getObject(entity, column.getField());
            BasicDBList basicDBList = new BasicDBList();
            for (Object o : collection) {
                basicDBList.add(o);
            }
            dbObj.put(column.getName(), basicDBList);
        } else {
            dbObj.put(column.getName(), PropertyAccessorHelper.getString(entity, column.getField()));
        }
    }

}