Package com.impetus.client.mongodb

Source Code of com.impetus.client.mongodb.DocumentObjectMapper

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

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

import javax.persistence.PersistenceException;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Metamodel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.client.mongodb.utils.MongoDBUtils;
import com.impetus.kundera.gis.geometry.Point;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.metadata.model.attributes.AttributeType;
import com.impetus.kundera.persistence.EntityReaderException;
import com.impetus.kundera.property.PropertyAccessException;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.property.accessor.EnumAccessor;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;

/**
* Provides functionality for mapping between MongoDB documents and POJOs.
* Contains utility methods for converting one form into another.
*
* @author amresh.singh
*/
public class DocumentObjectMapper
{

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

    /**
     * Creates a MongoDB document object wrt a given Java object. columns in the
     * document correspond Columns provided as List.
     *
     * @param obj
     *            the obj
     * @param columns
     *            the columns
     * @return the document from object
     * @throws PropertyAccessException
     *             the property access exception
     */
    static Map<String, DBObject> getDocumentFromObject(Metamodel metaModel, Object obj, Set<Attribute> columns,
            String tableName) throws PropertyAccessException
    {
        Map<String, DBObject> embeddedObjects = new HashMap<String, DBObject>();
        BasicDBObject dBObj = new BasicDBObject();

        for (Attribute column : columns)
        {
           String collectionName = ((AbstractAttribute) column).getTableName() != null ? ((AbstractAttribute) column)
                    .getTableName() : tableName;

            DBObject dbObject = embeddedObjects.get(collectionName);
            if (dbObject == null)
            {
                dbObject = new BasicDBObject();
                embeddedObjects.put(collectionName, dbObject);
            }

            if (((MetamodelImpl) metaModel).isEmbeddable(((AbstractAttribute) column).getBindableJavaType()))
            {
                DefaultMongoDBDataHandler handler = new DefaultMongoDBDataHandler();
                handler.onEmbeddable(column, obj, metaModel, dBObj, collectionName);
            }
            else
            {
                extractFieldValue(obj, dbObject, column);
            }
        }
        return embeddedObjects;
    }

    /**
     * Creates a MongoDB document list from a given java collection. columns in
     * the document correspond Columns provided as List.
     *
     * @param coll
     *            the coll
     * @param columns
     *            the columns
     * @return the document list from collection
     * @throws PropertyAccessException
     *             the property access exception
     */
    static BasicDBObject[] getDocumentListFromCollection(Metamodel metaModel, Collection coll, Set<Attribute> columns,
            String tableName) throws PropertyAccessException
    {
        BasicDBObject[] dBObjects = new BasicDBObject[coll.size()];
        int count = 0;
        for (Object o : coll)
        {
            dBObjects[count] = (BasicDBObject) getDocumentFromObject(metaModel, o, columns, tableName).values().toArray()[0];
            count++;
        }
        return dBObjects;
    }

    /**
     * Creates an instance of <code>clazz</code> and populates fields fetched
     * from MongoDB document object. Field names are determined from
     * <code>columns</code>
     *
     * @param documentObj
     *            the document obj
     * @param clazz
     *            the clazz
     * @param columns
     *            the columns
     * @return the object from document
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    static Object getObjectFromDocument(Metamodel metamodel, BasicDBObject documentObj, Set<Attribute> columns,
            Object obj) throws InstantiationException, IllegalAccessException
    {
        // try
        // {
        // Object obj = clazz.newInstance();
        for (Attribute column : columns)
        {
            if (((MetamodelImpl) metamodel).isEmbeddable(((AbstractAttribute) column).getBindableJavaType()))
            {
                DefaultMongoDBDataHandler handler = new DefaultMongoDBDataHandler();
                handler.onViaEmbeddable(column, obj, metamodel, documentObj);
            }
            else
            {
                setFieldValue(documentObj, obj, column);
            }
        }
        return obj;
        // }
        // catch (InstantiationException e)
        // {
        // throw new PersistenceException(e);
        // }
        // catch (IllegalAccessException e)
        // {
        // throw new PersistenceException(e);
        // }
    }

    /**
     * Setter for column value, by default converted from string value, in case
     * of map it is automatically converted into map using BasicDBObject.
     *
     * @param document
     *            mongo document
     * @param entityObject
     *            searched entity.
     * @param column
     *            column field.
     */
    static void setFieldValue(DBObject document, Object entityObject, Attribute column)
    {
        Object value = null;

        if (document != null)
        {
            value = document.get(((AbstractAttribute) column).getJPAColumnName());
        }
        if (value != null)
        {
            Class javaType = column.getJavaType();
            try
            {
                switch (AttributeType.getType(javaType))
                {
                case MAP:
                    PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(),
                            ((BasicDBObject) value).toMap());
                    break;
                case SET:
                    List collectionValues = Arrays.asList(((BasicDBList) value).toArray());
                    PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(), new HashSet(
                            collectionValues));
                    break;
                case LIST:
                    PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(),
                            Arrays.asList(((BasicDBList) value).toArray()));
                    break;
                case POINT:

                    BasicDBList list = (BasicDBList) value;

                    Object xObj = list.get(0);
                    Object yObj = list.get(1);

                    if (xObj != null && yObj != null)
                    {
                        try
                        {
                            double x = Double.parseDouble(xObj.toString());
                            double y = Double.parseDouble(yObj.toString());

                            Point point = new Point(x, y);
                            PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(), point);
                        }
                        catch (NumberFormatException e)
                        {
                            log.error(
                                    "Error while reading geolocation data for column {} ; Reason - possible corrupt data, Caused by : .",
                                    column, e);
                            throw new EntityReaderException("Error while reading geolocation data for column " + column
                                    + "; Reason - possible corrupt data.", e);
                        }
                    }
                    break;
                case ENUM:
                    EnumAccessor accessor = new EnumAccessor();
                    value = accessor.fromString(javaType, value.toString());
                    PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(), value);
                    break;
                case PRIMITIVE:
                    value = MongoDBUtils.populateValue(value, value.getClass());
                    value = MongoDBUtils.getTranslatedObject(value, value.getClass(), javaType);
                    PropertyAccessorHelper.set(entityObject, (Field) column.getJavaMember(), value);
                    break;
                }
            }
            catch (PropertyAccessException paex)
            {
                log.error("Error while setting column {} value, caused by : .",
                        ((AbstractAttribute) column).getJPAColumnName(), paex);
                throw new PersistenceException(paex);
            }
        }
    }

    /**
     * Extract entity field.
     *
     * @param entity
     *            the entity
     * @param dbObj
     *            the db obj
     * @param column
     *            the column
     * @throws PropertyAccessException
     *             the property access exception
     */
    static void extractFieldValue(Object entity, DBObject dbObj, Attribute column) throws PropertyAccessException
    {
        try
        {
            Object valueObject = PropertyAccessorHelper.getObject(entity, (Field) column.getJavaMember());

            if (valueObject != null)
            {
                Class javaType = column.getJavaType();
                switch (AttributeType.getType(javaType))
                {
                case MAP:
                    Map mapObj = (Map) valueObject;
                    // BasicDBObjectBuilder builder =
                    // BasicDBObjectBuilder.start(mapObj);
                    BasicDBObjectBuilder b = new BasicDBObjectBuilder();
                    Iterator i = mapObj.entrySet().iterator();
                    while (i.hasNext())
                    {
                        Map.Entry entry = (Map.Entry) i.next();
                        b.add(entry.getKey().toString(),
                                MongoDBUtils.populateValue(entry.getValue(), entry.getValue().getClass()));
                    }
                    dbObj.put(((AbstractAttribute) column).getJPAColumnName(), b.get());
                    break;
                case SET:
                case LIST:
                    Collection collection = (Collection) valueObject;
                    BasicDBList basicDBList = new BasicDBList();
                    for (Object o : collection)
                    {
                        basicDBList.add(o);
                    }
                    dbObj.put(((AbstractAttribute) column).getJPAColumnName(), basicDBList);
                    break;
                case POINT:

                    Point p = (Point) valueObject;
                    double[] coordinate = new double[] { p.getX(), p.getY() };
                    dbObj.put(((AbstractAttribute) column).getJPAColumnName(), coordinate);
                    break;
                case ENUM:
                case PRIMITIVE:
                    dbObj.put(((AbstractAttribute) column).getJPAColumnName(),
                            MongoDBUtils.populateValue(valueObject, javaType));
                    break;
                }
            }
        }
        catch (PropertyAccessException paex)
        {
            log.error("Error while getting column {} value, caused by : .",
                    ((AbstractAttribute) column).getJPAColumnName(), paex);
            throw new PersistenceException(paex);
        }
    }

    /**
     * Creates a collection of <code>embeddedObjectClass</code> instances
     * wherein each element is java object representation of MongoDB document
     * object contained in <code>documentList</code>. Field names are determined
     * from <code>columns</code>.
     *
     * @param documentList
     *            the document list
     * @param embeddedCollectionClass
     *            the embedded collection class
     * @param embeddedObjectClass
     *            the embedded object class
     * @param columns
     *            the columns
     * @param metamodel
     * @return the collection from document list
     */
    static Collection<?> getCollectionFromDocumentList(Metamodel metamodel, BasicDBList documentList,
            Class embeddedCollectionClass, Class embeddedObjectClass, Set<Attribute> columns)
    {
        Collection<Object> embeddedCollection = null;
        if (embeddedCollectionClass.equals(Set.class))
        {
            embeddedCollection = new HashSet<Object>();
        }
        else if (embeddedCollectionClass.equals(List.class))
        {
            embeddedCollection = new ArrayList<Object>();
        }
        else
        {
            throw new PersistenceException("Invalid collection class " + embeddedCollectionClass
                    + "; only Set and List allowed");
        }

        for (Object dbObj : documentList)
        {
            try
            {
                Object obj = embeddedObjectClass.newInstance();
                embeddedCollection.add(getObjectFromDocument(metamodel, (BasicDBObject) dbObj, columns, obj));
            }
            catch (InstantiationException e)
            {
                throw new PersistenceException(e);
            }
            catch (IllegalAccessException e)
            {
                throw new PersistenceException(e);
            }
        }

        return embeddedCollection;
    }
}
TOP

Related Classes of com.impetus.client.mongodb.DocumentObjectMapper

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.