Package com.impetus.client.mongodb

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

/*******************************************************************************
* * 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.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.metamodel.EntityType;

import org.apache.commons.lang.NotImplementedException;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.impetus.client.mongodb.query.MongoDBQuery;
import com.impetus.client.mongodb.utils.MongoDBUtils;
import com.impetus.kundera.PersistenceProperties;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.client.ClientBase;
import com.impetus.kundera.client.ClientPropertiesSetter;
import com.impetus.kundera.client.EnhanceEntity;
import com.impetus.kundera.db.RelationHolder;
import com.impetus.kundera.generator.AutoGenerator;
import com.impetus.kundera.graph.Node;
import com.impetus.kundera.index.IndexManager;
import com.impetus.kundera.lifecycle.states.RemovedState;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.model.ClientMetadata;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.PersistenceUnitMetadata;
import com.impetus.kundera.metadata.model.annotation.DefaultEntityAnnotationProcessor;
import com.impetus.kundera.metadata.model.type.AbstractManagedType;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.EntityReader;
import com.impetus.kundera.persistence.api.Batcher;
import com.impetus.kundera.persistence.context.jointable.JoinTableData;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.utils.KunderaCoreUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBEncoder;
import com.mongodb.DBObject;
import com.mongodb.DefaultDBEncoder;
import com.mongodb.WriteConcern;
import com.mongodb.WriteResult;

/**
* Client class for MongoDB database.
*
* @author impetusopensource
*/
public class MongoDBClient extends ClientBase implements Client<MongoDBQuery>, Batcher, ClientPropertiesSetter,
        AutoGenerator
{
    /** The mongo db. */
    private DB mongoDb;

    /** The reader. */
    private EntityReader reader;

    /** The data handler. */
    private DefaultMongoDBDataHandler handler;

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

    private List<Node> nodes = new ArrayList<Node>();

    private int batchSize;

    private WriteConcern writeConcern = null;

    private DBEncoder encoder = DefaultDBEncoder.FACTORY.create();

    /**
     * Instantiates a new mongo db client.
     *
     * @param mongo
     *            the mongo
     * @param mgr
     *            the mgr
     * @param reader
     *            the reader
     * @param puProperties
     */
    public MongoDBClient(Object mongo, IndexManager mgr, EntityReader reader, String persistenceUnit,
            Map<String, Object> externalProperties, ClientMetadata clientMetadata, final KunderaMetadata kunderaMetadata)
    {
        // TODO: This could be a constantly called, see how connection pooling
        // is
        // relevant here
        super(kunderaMetadata, externalProperties, persistenceUnit);
        this.mongoDb = (DB) mongo;
        this.indexManager = mgr;
        this.reader = reader;
        handler = new DefaultMongoDBDataHandler();
        this.clientMetadata = clientMetadata;
        populateBatchSize(persistenceUnit, this.externalProperties);
    }

    @Override
    public void persistJoinTable(JoinTableData joinTableData)
    {
        String joinTableName = joinTableData.getJoinTableName();
        String joinColumnName = joinTableData.getJoinColumnName();
        String invJoinColumnName = joinTableData.getInverseJoinColumnName();
        Map<Object, Set<Object>> joinTableRecords = joinTableData.getJoinTableRecords();

        DBCollection dbCollection = mongoDb.getCollection(joinTableName);
        KunderaCoreUtils.printQuery("Persist join table:" + joinTableName, showQuery);
        List<DBObject> documents = new ArrayList<DBObject>();

        for (Object key : joinTableRecords.keySet())
        {
            Set<Object> values = joinTableRecords.get(key);
            Object joinColumnValue = key;

            for (Object childId : values)
            {
                DBObject dbObj = new BasicDBObject();
                dbObj.put("_id", joinColumnValue.toString() + childId);
                dbObj.put(joinColumnName, MongoDBUtils.populateValue(joinColumnValue, joinColumnValue.getClass()));
                dbObj.put(invJoinColumnName, MongoDBUtils.populateValue(childId, childId.getClass()));
                documents.add(dbObj);
                KunderaCoreUtils.printQuery("id:" + joinColumnValue.toString() + childId + "   " + joinColumnName + ":"
                        + joinColumnValue + "   " + invJoinColumnName + ":" + childId, showQuery);
            }
        }
        dbCollection.insert(documents.toArray(new BasicDBObject[0]), getWriteConcern(), encoder);
    }

    @Override
    public <E> List<E> getColumnsById(String schemaName, String joinTableName, String joinColumnName,
            String inverseJoinColumnName, Object parentId, Class columnJavaType)
    {
        List<E> foreignKeys = new ArrayList<E>();

        DBCollection dbCollection = mongoDb.getCollection(joinTableName);
        BasicDBObject query = new BasicDBObject();

        query.put(joinColumnName, MongoDBUtils.populateValue(parentId, parentId.getClass()));
        KunderaCoreUtils.printQuery("Find by Id:" + query, showQuery);
        DBCursor cursor = dbCollection.find(query);
        DBObject fetchedDocument = null;

        while (cursor.hasNext())
        {
            fetchedDocument = cursor.next();
            Object foreignKey = fetchedDocument.get(inverseJoinColumnName);
            foreignKey = MongoDBUtils.getTranslatedObject(foreignKey, foreignKey.getClass(), columnJavaType);
            foreignKeys.add((E) foreignKey);
        }
        return foreignKeys;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#findIdsByColumn(java.lang.String,
     * java.lang.String, java.lang.String, java.lang.Object, java.lang.Class)
     */
    @Override
    public Object[] findIdsByColumn(String schemaName, String tableName, String pKeyName, String columnName,
            Object columnValue, Class entityClazz)
    {
        EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entityClazz);

        List<Object> primaryKeys = new ArrayList<Object>();

        DBCollection dbCollection = mongoDb.getCollection(tableName);
        BasicDBObject query = new BasicDBObject();

        query.put(columnName, MongoDBUtils.populateValue(columnValue, columnValue.getClass()));

        DBCursor cursor = dbCollection.find(query);
        KunderaCoreUtils.printQuery("Find id by column:" + query, showQuery);
        DBObject fetchedDocument = null;

        while (cursor.hasNext())
        {
            fetchedDocument = cursor.next();
            Object primaryKey = fetchedDocument.get(pKeyName);
            primaryKey = MongoDBUtils.getTranslatedObject(primaryKey, primaryKey.getClass(), metadata.getIdAttribute()
                    .getJavaType());
            primaryKeys.add(primaryKey);
        }

        if (primaryKeys != null && !primaryKeys.isEmpty())
        {
            return primaryKeys.toArray(new Object[0]);
        }
        return null;

    }

    /*
     * (non-Javadoc)
     *
     * @seecom.impetus.kundera.Client#loadColumns(com.impetus.kundera.ejb.
     * EntityManager, java.lang.Class, java.lang.String, java.lang.String,
     * java.lang.String, com.impetus.kundera.metadata.EntityMetadata)
     */
    @Override
    public Object find(Class entityClass, Object key)
    {
        EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entityClass);

        List<String> relationNames = entityMetadata.getRelationNames();

        BasicDBObject query = new BasicDBObject();

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

        AbstractManagedType managedType = (AbstractManagedType) metaModel.entity(entityMetadata.getEntityClazz());

        if (metaModel.isEmbeddable(entityMetadata.getIdAttribute().getBindableJavaType()))
        {
            MongoDBUtils.populateCompoundKey(query, entityMetadata, metaModel, key);
        }
        else
        {
            query.put("_id", MongoDBUtils.populateValue(key, key.getClass()));
        }

        // For secondary tables.
        List<String> secondaryTables = ((DefaultEntityAnnotationProcessor) managedType.getEntityAnnotation())
                .getSecondaryTablesName();
        secondaryTables.add(entityMetadata.getTableName());

        Object enhancedEntity = null;
        Map<String, Object> relationValue = null;
        // Here you need to fetch by sub managed type.

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

        for (String tableName : secondaryTables)
        {
            DBCollection dbCollection = mongoDb.getCollection(tableName);
            KunderaCoreUtils.printQuery("Find document:" + query, showQuery);
            DBObject fetchedDocument = dbCollection.findOne(query);

            if (fetchedDocument != null)
            {
                List<AbstractManagedType> subManagedType = ((AbstractManagedType) entityType).getSubManagedType();

                EntityMetadata subEntityMetadata = null;
                if (!subManagedType.isEmpty())
                {
                    for (AbstractManagedType subEntity : subManagedType)
                    {
                        String discColumn = subEntity.getDiscriminatorColumn();
                        String disColValue = subEntity.getDiscriminatorValue();
                        Object value = fetchedDocument.get(discColumn);
                        if (value != null && value.toString().equals(disColValue))
                        {
                            subEntityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
                                    subEntity.getJavaType());
                            break;
                        }
                    }

                    enhancedEntity = instantiateEntity(subEntityMetadata.getEntityClazz(), enhancedEntity);
                    relationValue = handler.getEntityFromDocument(subEntityMetadata.getEntityClazz(), enhancedEntity,
                            subEntityMetadata, fetchedDocument, subEntityMetadata.getRelationNames(), relationValue,
                            kunderaMetadata);
                }
                else
                {
                    enhancedEntity = instantiateEntity(entityClass, enhancedEntity);
                    relationValue = handler.getEntityFromDocument(entityMetadata.getEntityClazz(), enhancedEntity,
                            entityMetadata, fetchedDocument, relationNames, relationValue, kunderaMetadata);
                }

            }
        }

        if (relationValue != null && !relationValue.isEmpty())
        {
            EnhanceEntity entity = new EnhanceEntity(enhancedEntity, PropertyAccessorHelper.getId(enhancedEntity,
                    entityMetadata), relationValue);
            return entity;
        }
        else
        {
            return enhancedEntity;
        }
    }

    private Object instantiateEntity(Class entityClass, Object entity)
    {
        try
        {
            if (entity == null)
            {
                return entityClass.newInstance();
            }
            return entity;
        }
        catch (InstantiationException e)
        {
            log.error("Error while instantiating " + entityClass + ", Caused by: ", e);
        }
        catch (IllegalAccessException e)
        {
            log.error("Error while instantiating " + entityClass + ", Caused by: ", e);
        }
        return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#findAll(java.lang.Class,
     * java.lang.Object[])
     */
    @Override
    public <E> List<E> findAll(Class<E> entityClass, String[] columnsToSelect, Object... keys)
    {
        EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entityClass);

        log.debug("Fetching data from " + entityMetadata.getTableName() + " for Keys " + keys);

        DBCollection dbCollection = mongoDb.getCollection(entityMetadata.getTableName());

        BasicDBObject query = new BasicDBObject();

        query.put("_id", new BasicDBObject("$in", keys));

        DBCursor cursor = dbCollection.find(query);
        KunderaCoreUtils.printQuery("Find collection:" + query, showQuery);
        List entities = new ArrayList<E>();
        while (cursor.hasNext())
        {
            DBObject fetchedDocument = cursor.next();

            populateEntity(entityMetadata, entities, fetchedDocument);
        }
        return entities;
    }

    /**
     * Loads columns from multiple rows restricting results to conditions stored
     * in <code>filterClauseQueue</code>.
     *
     * @param <E>
     *            the element type
     * @param entityMetadata
     *            the entity metadata
     * @param mongoQuery
     *            the mongo query
     * @param result
     *            the result
     * @param relationNames
     *            the relation names
     * @param orderBy
     *            the order by
     * @param maxResult
     * @param keys
     * @return the list
     * @throws Exception
     *             the exception
     */
    public <E> List<E> loadData(EntityMetadata entityMetadata, BasicDBObject mongoQuery, List<String> relationNames,
            BasicDBObject orderBy, int maxResult, int firstResult, BasicDBObject keys, String... results)
            throws Exception
    {
        String documentName = entityMetadata.getTableName();
        Class clazz = entityMetadata.getEntityClazz();

        List entities = new ArrayList<E>();

        boolean isCountQuery = false;
        if (results != null && results.length > 1)
        {
            if (results[0].toLowerCase().indexOf("count(") == 0)
            {
                isCountQuery = true;
            }
        }

        Object object = getDBCursorInstance(mongoQuery, orderBy, maxResult, firstResult, keys, documentName,
                isCountQuery);

        DBCursor cursor = null;

        if (object instanceof Long)
        {
            List<Long> lst = new ArrayList<Long>();
            lst.add((Long) object);
            return (List<E>) lst;
        }
        else
        {
            cursor = (DBCursor) object;
        }

        if (results != null && results.length > 0)
        {
            DBCollection dbCollection = mongoDb.getCollection(documentName);
            KunderaCoreUtils.printQuery("Find document: " + mongoQuery, showQuery);
            for (int i = 1; i < results.length; i++)
            {
                String result = results[i];

                // If User wants search on a column within a particular super
                // column,
                // fetch that embedded object collection only
                // otherwise retrieve whole entity
                // TODO: improve code
                if (result != null && result.indexOf(".") >= 0)
                {
                    // TODO i need to discuss with Amresh before modifying it.
                    entities.addAll(handler.getEmbeddedObjectList(dbCollection, entityMetadata, documentName,
                            mongoQuery, result, orderBy, maxResult, firstResult, keys, kunderaMetadata));
                    return entities;
                }
            }
        }
        log.debug("Fetching data from " + documentName + " for Filter " + mongoQuery.toString());

        while (cursor.hasNext())
        {
            DBObject fetchedDocument = cursor.next();

            populateEntity(entityMetadata, entities, fetchedDocument);
        }
        return entities;
    }

    public Object getDBCursorInstance(BasicDBObject mongoQuery, BasicDBObject orderBy, int maxResult, int firstResult,
            BasicDBObject keys, String documentName, boolean isCountQuery)
    {
        DBCollection dbCollection = mongoDb.getCollection(documentName);
      
        DBCursor cursor = null;
        if (isCountQuery)
            return dbCollection.count(mongoQuery);
        else
            cursor = orderBy != null ? dbCollection.find(mongoQuery, keys).sort(orderBy).limit(maxResult)
                    .skip(firstResult) : dbCollection.find(mongoQuery, keys).limit(maxResult).skip(firstResult);
        return cursor;
    }

    /*
     * (non-Javadoc) object
     *
     * @see com.impetus.kundera.client.Client#delete(java.lang.Object,
     * java.lang.Object)
     */
    @Override
    public void delete(Object entity, Object pKey)
    {
        EntityMetadata entityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entity.getClass());

        // Find the DBObject to remove first
        BasicDBObject query = new BasicDBObject();

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

        if (metaModel.isEmbeddable(entityMetadata.getIdAttribute().getBindableJavaType()))
        {
            MongoDBUtils.populateCompoundKey(query, entityMetadata, metaModel, pKey);
        }
        else
        {

            query.put("_id", MongoDBUtils.populateValue(pKey, pKey.getClass()));
        }

        AbstractManagedType managedType = (AbstractManagedType) metaModel.entity(entityMetadata.getEntityClazz());
        // For secondary tables.
        List<String> secondaryTables = ((DefaultEntityAnnotationProcessor) managedType.getEntityAnnotation())
                .getSecondaryTablesName();
        secondaryTables.add(entityMetadata.getTableName());

        for (String collectionName : secondaryTables)
        {
            KunderaCoreUtils.printQuery("Drop existing collection:" + query, showQuery);
            DBCollection dbCollection = mongoDb.getCollection(collectionName);
            dbCollection.remove(query, getWriteConcern(), encoder);
        }
       
        getIndexManager().remove(entityMetadata, entity, pKey);
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#close()
     */
    @Override
    public void close()
    {
        // TODO Once pool is implemented this code should not be there.
        // Workaround for pool
        this.indexManager.flush();
        externalProperties = null;
        clear();
    }

    /**
     * Creates the index.
     *
     * @param collectionName
     *            the collection name
     * @param columnList
     *            the column list
     * @param order
     *            the order
     */
    public void createIndex(String collectionName, List<String> columnList, int order)
    {
        DBCollection coll = mongoDb.getCollection(collectionName);

        List<DBObject> indexes = coll.getIndexInfo(); // List of all current
        // indexes on collection
        Set<String> indexNames = new HashSet<String>(); // List of all current
        // index names
        for (DBObject index : indexes)
        {
            BasicDBObject obj = (BasicDBObject) index.get("key");
            Set<String> set = obj.keySet(); // Set containing index name which
            // is key
            indexNames.addAll(set);
        }

        // Create index if not already created
        for (String columnName : columnList)
        {
            if (!indexNames.contains(columnName))
            {
                KunderaCoreUtils.printQuery("Create index on:" + columnName, showQuery);
                coll.createIndex(new BasicDBObject(columnName, order));
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#find(java.lang.Class,
     * java.util.Map)
     */
    @Override
    public <E> List<E> find(Class<E> entityClass, Map<String, String> col)
    {
        throw new NotImplementedException("Not yet implemented");
    }

    /**
     * Method to find entity for given association name and association value.
     *
     * @param colName
     *            the col name
     * @param colValue
     *            the col value
     * @param m
     *            the m
     * @return the list
     */
    public List<Object> findByRelation(String colName, Object colValue, Class entityClazz)
    {
        EntityMetadata m = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, entityClazz);
        // you got column name and column value.
        DBCollection dbCollection = mongoDb.getCollection(m.getTableName());

        BasicDBObject query = new BasicDBObject();

        query.put(colName, MongoDBUtils.populateValue(colValue, colValue.getClass()));
        KunderaCoreUtils.printQuery("Find by relation:" + query, showQuery);
        DBCursor cursor = dbCollection.find(query);
        DBObject fetchedDocument = null;
        List<Object> results = new ArrayList<Object>();
        while (cursor.hasNext())
        {
            fetchedDocument = cursor.next();
            populateEntity(m, results, fetchedDocument);
        }

        return results.isEmpty() ? null : results;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#getReader()
     */
    @Override
    public EntityReader getReader()
    {
        return reader;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#deleteByColumn(java.lang.String,
     * java.lang.String, java.lang.Object)
     */
    public void deleteByColumn(String schemaName, String tableName, String columnName, Object columnValue)
    {
        DBCollection dbCollection = mongoDb.getCollection(tableName);
        BasicDBObject query = new BasicDBObject();
        query.put(columnName, columnValue);
        KunderaCoreUtils.printQuery("Delete column:" + query, showQuery);
        dbCollection.remove(query, getWriteConcern(), encoder);
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.client.Client#getQueryImplementor()
     */
    @Override
    public Class<MongoDBQuery> getQueryImplementor()
    {
        return MongoDBQuery.class;
    }

    @Override
    protected void onPersist(EntityMetadata entityMetadata, Object entity, Object id, List<RelationHolder> rlHolders)
    {
        Map<String, List<DBObject>> collections = new HashMap<String, List<DBObject>>();
        collections = onPersist(collections, entity, id, entityMetadata, rlHolders, isUpdate);
        onFlushCollection(collections);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.impetus.kundera.persistence.api.Batcher#addBatch(com.impetus.kundera
     * .graph.Node)
     */
    public void addBatch(Node node)
    {
        if (node != null)
        {
            nodes.add(node);
        }
        onBatchLimit();
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.persistence.api.Batcher#getBatchSize()
     */
    @Override
    public int getBatchSize()
    {
        return batchSize;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.persistence.api.Batcher#clear()
     */
    @Override
    public void clear()
    {
        if (nodes != null)
        {
            nodes.clear();
            nodes = new ArrayList<Node>();
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.impetus.kundera.persistence.api.Batcher#executeBatch()
     */
    @Override
    public int executeBatch()
    {
        Map<String, List<DBObject>> collections = new HashMap<String, List<DBObject>>();
        for (Node node : nodes)
        {
            if (node.isDirty())
            {
                node.handlePreEvent();
                // delete can not be executed in batch
                if (node.isInState(RemovedState.class))
                {
                    delete(node.getData(), node.getEntityId());
                }
                else
                {
                    List<RelationHolder> relationHolders = getRelationHolders(node);
                    EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
                            node.getDataClass());
                    collections = onPersist(collections, node.getData(), node.getEntityId(), metadata, relationHolders,
                            node.isUpdate());
                    indexNode(node, metadata);
                }
                node.handlePostEvent();
            }
        }
        if (!collections.isEmpty())
        {
            onFlushCollection(collections);
        }
        return collections.size();
    }

    /**
     * On collections flush.
     *
     * @param collections
     *            collection containing records to be inserted in mongo db.
     */
    private void onFlushCollection(Map<String, List<DBObject>> collections)
    {
        for (String tableName : collections.keySet())
        {
            DBCollection dbCollection = mongoDb.getCollection(tableName);
            KunderaCoreUtils.printQuery("Persist collection:" + tableName, showQuery);
            dbCollection.insert(collections.get(tableName).toArray(new DBObject[0]), getWriteConcern(), encoder);
        }
    }

    /**
     * Executes on list of entities to be persisted.
     *
     * @param collections
     *            collection containing list of db objects.
     * @param entity
     *            entity in question.
     * @param id
     *            entity id.
     * @param metadata
     *            entity metadata
     * @param relationHolders
     *            relation holders.
     * @param isUpdate
     *            if it is an update
     * @return collection of DB objects.
     */
    private Map<String, List<DBObject>> onPersist(Map<String, List<DBObject>> collections, Object entity, Object id,
            EntityMetadata metadata, List<RelationHolder> relationHolders, boolean isUpdate)
    {
        persistenceUnit = metadata.getPersistenceUnit();
        // String documentName = metadata.getTableName();
        Map<String, DBObject> documents = handler.getDocumentFromEntity(metadata, entity, relationHolders,
                kunderaMetadata);
        if (isUpdate)
        {
            for (String documentName : documents.keySet())
            {
                BasicDBObject query = new BasicDBObject();

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

                if (metaModel.isEmbeddable(metadata.getIdAttribute().getBindableJavaType()))
                {
                    MongoDBUtils.populateCompoundKey(query, metadata, metaModel, id);
                }
                else
                {
                    query.put("_id", MongoDBUtils.populateValue(id, id.getClass()));
                }
                DBCollection dbCollection = mongoDb.getCollection(documentName);
                KunderaCoreUtils.printQuery("Persist collection:" + documentName, showQuery);
                DBObject obj = dbCollection.findOne(query);
                if (obj != null)
                {
                    obj.putAll(documents.get(documentName));

                    dbCollection.save(obj);
                }
                else
                {
                    dbCollection.save(documents.get(documentName));
                }
            }
        }
        else
        {
            for (String documentName : documents.keySet())
            {
                // a db collection can have multiple records..
                // and we can have a collection of records as well.
                List<DBObject> dbStatements = null;
                if (collections.containsKey(documentName))
                {
                    dbStatements = collections.get(documentName);
                    dbStatements.add(documents.get(documentName));
                }
                else
                {
                    dbStatements = new ArrayList<DBObject>();
                    dbStatements.add(documents.get(documentName));
                    collections.put(documentName, dbStatements);
                }
            }
        }
        return collections;
    }

    /**
     * Check on batch limit.
     */
    private void onBatchLimit()
    {
        if (batchSize > 0 && batchSize == nodes.size())
        {
            executeBatch();
            nodes.clear();
        }
    }

    @Override
    public void populateClientProperties(Client client, Map<String, Object> properties)
    {
        new MongoDBClientProperties().populateClientProperties(client, properties);
    }

    /**
     * @param mongoDb
     *            the mongoDb to set
     */
    public void setMongoDb(DB mongoDb)
    {
        this.mongoDb = mongoDb;
    }

    /**
     * @param handler
     *            the handler to set
     */
    public void setHandler(DefaultMongoDBDataHandler handler)
    {
        this.handler = handler;
    }

    /**
     * @param nodes
     *            the nodes to set
     */
    public void setNodes(List<Node> nodes)
    {
        this.nodes = nodes;
    }

    /**
     * @param writeConcern
     *            the writeConcern to set
     */
    public void setWriteConcern(WriteConcern writeConcern)
    {
        this.writeConcern = writeConcern;
    }

    /**
     * @param encoder
     *            the encoder to set
     */
    public void setEncoder(DBEncoder encoder)
    {
        this.encoder = encoder;
    }

    /**
     * @return the encoder
     */
    public DBEncoder getEncoder()
    {
        return encoder;
    }

    /**
     * @return the writeConcern
     */
    public WriteConcern getWriteConcern()
    {
        if (writeConcern == null)
        {
            return mongoDb.getWriteConcern();
        }
        return writeConcern;
    }

    /**
     * @param batchSize
     *            the batchSize to set
     */
    public void setBatchSize(int batchSize)
    {
        this.batchSize = batchSize;
    }

    /**
     * @param persistenceUnit
     * @param puProperties
     */
    private void populateBatchSize(String persistenceUnit, Map<String, Object> puProperties)
    {
        String batch_Size = puProperties != null ? (String) puProperties.get(PersistenceProperties.KUNDERA_BATCH_SIZE)
                : null;
        if (batch_Size != null)
        {
            batchSize = Integer.valueOf(batch_Size);
            if (batchSize == 0)
            {
                throw new IllegalArgumentException("kundera.batch.size property must be numeric and > 0");
            }
        }
        else
        {
            PersistenceUnitMetadata puMetadata = KunderaMetadataManager.getPersistenceUnitMetadata(kunderaMetadata,
                    persistenceUnit);
            batchSize = puMetadata.getBatchSize();
        }
    }

    @Override
    public Object generate()
    {
        // return auto generated id used by mongodb.
        return new ObjectId();
    }

    /**
     * Method to execute mongo jscripts.
     *
     * @param script
     *            jscript in string format
     *
     * @return result object.
     */
    @Override
    public Object executeScript(String script)
    {
        Object result = mongoDb.eval(script);
        KunderaCoreUtils.printQuery("Execute mongo jscripts:" + script, showQuery);
        return result;
    }

    private void populateEntity(EntityMetadata entityMetadata, List entities, DBObject fetchedDocument)
    {
        Map<String, Object> relationValue = null;
        if (fetchedDocument != null)
        {
            MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
                    entityMetadata.getPersistenceUnit());

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

            List<AbstractManagedType> subManagedType = ((AbstractManagedType) entityType).getSubManagedType();

            EntityMetadata subEntityMetadata = null;
            Object enhancedEntity = null;
            if (!subManagedType.isEmpty())
            {
                for (AbstractManagedType subEntity : subManagedType)
                {
                    String discColumn = subEntity.getDiscriminatorColumn();
                    String disColValue = subEntity.getDiscriminatorValue();
                    Object value = fetchedDocument.get(discColumn);
                    if (value != null && value.toString().equals(disColValue))
                    {
                        subEntityMetadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata,
                                subEntity.getJavaType());
                        break;
                    }
                }
                enhancedEntity = instantiateEntity(subEntityMetadata.getEntityClazz(), enhancedEntity);
                relationValue = handler.getEntityFromDocument(subEntityMetadata.getEntityClazz(), enhancedEntity,
                        subEntityMetadata, fetchedDocument, subEntityMetadata.getRelationNames(), relationValue,
                        kunderaMetadata);

            }
            else
            {
                enhancedEntity = instantiateEntity(entityMetadata.getEntityClazz(), enhancedEntity);
                relationValue = handler.getEntityFromDocument(entityMetadata.getEntityClazz(), enhancedEntity,
                        entityMetadata, fetchedDocument, entityMetadata.getRelationNames(), relationValue,
                        kunderaMetadata);
            }

            if (relationValue != null && !relationValue.isEmpty())
            {
                enhancedEntity = new EnhanceEntity(enhancedEntity, PropertyAccessorHelper.getId(enhancedEntity,
                        entityMetadata), relationValue);
            }

            if (enhancedEntity != null)
            {
                entities.add(enhancedEntity);
            }
        }
    }

    public int handleUpdateFunctions(BasicDBObject query, BasicDBObject update, String collName)
    {
        DBCollection collection = mongoDb.getCollection(collName);
        KunderaCoreUtils.printQuery("Update collection:" + query, showQuery);
        WriteResult result = collection.update(query, update);
        if (result.getError() != null || result.getN() <= 0)
            return -1;
        return result.getN();
    }

}
TOP

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

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.