org.tinygroup.mongodb.engine.view.MongoViewContext.java Source code

Java tutorial

Introduction

Here is the source code for org.tinygroup.mongodb.engine.view.MongoViewContext.java

Source

/**
 *  Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 *
 *  Licensed under the GPL, Version 3.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.gnu.org/licenses/gpl.html
 *
 *  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 org.tinygroup.mongodb.engine.view;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bson.BSONObject;
import org.tinygroup.commons.tools.CollectionUtil;
import org.tinygroup.commons.tools.StringUtil;
import org.tinygroup.context.Context;
import org.tinygroup.imda.processor.ParameterBuilder;
import org.tinygroup.mongodb.common.ConditionField;
import org.tinygroup.mongodb.common.DisplayField;
import org.tinygroup.mongodb.common.Field;
import org.tinygroup.mongodb.common.GroupField;
import org.tinygroup.mongodb.common.HavingField;
import org.tinygroup.mongodb.common.MongoRelation;
import org.tinygroup.mongodb.common.ObjectField;
import org.tinygroup.mongodb.common.OrderField;
import org.tinygroup.mongodb.common.RelationCondition;
import org.tinygroup.mongodb.common.View;
import org.tinygroup.mongodb.common.ViewGroup;
import org.tinygroup.mongodb.engine.MongoDbContext;
import org.tinygroup.mongodb.engine.MongoField;
import org.tinygroup.mongodb.engine.PageInfo;
import org.tinygroup.mongodb.engine.view.extendinfo.FieldMaps;
import org.tinygroup.mongodb.engine.view.tree.TreeViewParamterBuilder;
import org.tinygroup.mongodb.model.MongoDBModel;
import org.tinygroup.mongodb.util.ModelUtil;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;

/**
 * 
 * : 
 * <p>
    
 * ?: renhui <br>
 * ?: 2013-11-27 <br>
 * <br>
 */
public class MongoViewContext extends MongoDbContext {

    private View view;

    private List<DisplayField> statistics = new ArrayList<DisplayField>();

    private Map<String, MongoRelationData> mongoRelations = new HashMap<String, MongoRelationData>();

    private DBObject displayObject;

    private DBObject groupObject;

    private String nestedObject;// ?

    public MongoViewContext(MongoDBModel model, View view, Context context) {
        super(model, context);
        this.view = view;
        displayObject = generateDisplayObject();
        groupObject = generateGroupObject();
        List<MongoRelation> relations = view.getRelations();
        for (MongoRelation mongoRelation : relations) {
            List<RelationCondition> conditions = mongoRelation.getConditions();
            for (RelationCondition condition : conditions) {
                String sourceRelationField = condition.getSourceRelationField();
                MongoField field = getMongoField(sourceRelationField);
                String objectFieldName = null;
                ObjectField of = field.getObjectField();
                if (of != null) {
                    objectFieldName = of.getName();
                }
                String sourcePropertyName = field.getField().getName();
                String targetRelationField = condition.getTargetRelationField();
                mongoRelations.put(sourcePropertyName, new MongoRelationData(objectFieldName, sourcePropertyName,
                        targetRelationField, mongoRelation));
            }
        }

    }

    public PageInfo queryMongoModel() {

        if (view != null) {
            DBObject conditionObject = generateConditionObject();
            DBObject havingObject = generateHavingConditionObject();
            DBObject orderObject = generateOrderObject();
            int pageSize = checkPageSize();
            String pageNumStr = context.get(ParameterBuilder.PAGE_NUMBER);
            int pageNum = 1;
            if (pageNumStr != null) {
                pageNum = Integer.parseInt(pageNumStr);
            }
            PageInfo pageInfo = persistence.find(displayObject, conditionObject, groupObject, havingObject,
                    orderObject, pageNum, pageSize);

            // ??????
            BSONObject[] records = pageInfo.getObjects();
            if (records != null) {
                for (BSONObject record : records) {
                    filterArrayRecords(record);
                }
            }
            return pageInfo;
        }

        return null;
    }

    /**
     * 
     * ??,??
     * 
     * @param record
     */
    private void filterArrayRecords(BSONObject record) {
        List<ConditionField> conditionFields = view.getConditionFields();
        for (ConditionField conditionField : conditionFields) {
            MongoField mongoField = getMongoField(conditionField.getFieldId());
            ObjectField of = mongoField.getObjectField();
            String fieldName = mongoField.getField().getName();
            if (of != null) {
                if (of.isArray()) {
                    String propertyName = mongoField.getFieldName();
                    Object value = context.get(propertyName);
                    if (value != null) {// ?null?
                        Object itemArray = record.get(of.getName());// 
                        if (itemArray != null) {
                            BasicDBList newList = new BasicDBList();
                            if (itemArray instanceof BasicDBList) {
                                BasicDBList itemList = (BasicDBList) itemArray;
                                for (Object item : itemList) {
                                    BSONObject itemRecord = (BSONObject) item;
                                    if (itemRecord.get(fieldName).equals(value)) {
                                        newList.add(itemRecord);
                                    }
                                }
                                record.put(of.getName(), newList);
                            }
                        }
                    }

                }
            }
        }
    }

    /**
     * 
     * 
     * 
     * @return
     */
    public PageInfo nestedArrayQuery() {
        PageInfo pageInfo = new PageInfo();
        int pageSize = checkPageSize();
        String pageNumStr = context.get(ParameterBuilder.PAGE_NUMBER);
        int pageNum = 1;
        if (pageNumStr != null) {
            pageNum = Integer.parseInt(pageNumStr);
        }
        int size = 0;

        if (view != null) {
            DBObject conditionObject = generateConditionObject();
            DBObject havingObject = generateHavingConditionObject();
            DBObject orderObject = generateOrderObject();
            DBObject displayObject = generateNestedDisplayObject();
            BSONObject[] records = persistence.find(displayObject, conditionObject, groupObject, havingObject,
                    orderObject);
            if (records != null && records.length == 1) {
                BSONObject record = records[0];
                filterArrayRecords(record);// ??
                Object object = record.get(nestedObject);
                if (object != null) {
                    if (object instanceof BasicDBList) {
                        BasicDBList nestedObjects = (BasicDBList) object;
                        size = nestedObjects.size();
                        pageInfo.pageAttributeSet(pageSize, pageNum, size);
                        int start = pageInfo.getStart();
                        int length = start + pageInfo.getPageSize();
                        int pageLength = pageInfo.getPageSize();
                        ;
                        if (size < length) {
                            pageLength = size - start;
                        }
                        BSONObject[] pageObjects = new BSONObject[pageLength];
                        for (int i = start, j = 0; j < pageLength; i++, j++) {
                            BSONObject bsonObject = (BSONObject) nestedObjects.get(i);
                            pageObjects[j] = bsonObject;
                        }
                        pageInfo.setObjects(pageObjects);
                        return pageInfo;
                    }
                }

            } else {
                pageInfo.pageAttributeSet(pageSize, pageNum, size);
                pageInfo.setObjects(new BSONObject[0]);
            }
        }

        return pageInfo;

    }

    /**
     * 
     * ?
     * 
     * @return
     */
    public PageInfo relationQueryMongoModel() {

        if (view != null) {
            BSONObject[] records = getRecords();
            if (records != null) {
                List<BSONObject> bsonObjects = new ArrayList<BSONObject>();
                for (BSONObject record : records) {
                    List<BSONObject> objects = new ArrayList<BSONObject>();
                    boolean first = true;
                    for (String propertyName : mongoRelations.keySet()) {
                        if (first) {
                            BSONObject object = new BasicDBObject();
                            object.putAll(record);
                            objects.add(object);
                            first = false;
                        }
                        MongoRelationData data = mongoRelations.get(propertyName);
                        objects = data.generateObjects(objects);
                    }
                    bsonObjects.addAll(objects);
                }
                int pageSize = checkPageSize();
                String pageNumStr = context.get(ParameterBuilder.PAGE_NUMBER);
                int pageNum = 1;
                if (pageNumStr != null) {
                    pageNum = Integer.parseInt(pageNumStr);
                }
                int size = bsonObjects.size();
                PageInfo pageInfo = new PageInfo();
                pageInfo.pageAttributeSet(pageSize, pageNum, size);
                int start = pageInfo.getStart();
                int length = start + pageInfo.getPageSize();
                int pageLength = pageInfo.getPageSize();
                if (size < length) {
                    pageLength = size - start;
                }
                BSONObject[] pageObjects = new BSONObject[pageLength];
                for (int i = start, j = 0; j < pageLength; i++, j++) {
                    BSONObject bsonObject = bsonObjects.get(i);
                    pageObjects[j] = bsonObject;
                }
                pageInfo.setObjects(pageObjects);
                return pageInfo;
            }

        }

        return null;
    }

    private int checkPageSize() {
        String pageSizeStr = context.get(ParameterBuilder.PAGE_SIZE);
        int pageSize = 0;
        if (view.isFrontPaging()) {// ??0
            return 0;
        }

        if (pageSizeStr == null) {
            pageSize = view.getPageSize();
        } else {
            pageSize = Integer.parseInt(pageSizeStr);
        }
        return pageSize;
    }

    /**
     * 
     * 
     * 
     * @param <T>
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T[] queryMongoModelOfTree(Class<T> clazz) {
        if (view != null) {
            BSONObject[] records = getRecords();
            if (records != null) {
                String queryAll = context.get(TreeViewParamterBuilder.QUERY_ALL_TREE);
                FieldMaps maps = new FieldMaps(this, context);
                maps.parserExtendInfos(view.getExtendInformation());
                T[] treeNodes = (T[]) Array.newInstance(clazz, records.length);
                for (int i = 0; i < records.length; i++) {
                    if (!StringUtil.isBlank(queryAll) && queryAll.equals("true")) {
                        BSONObject[] subRecords = getSubRecords(records[i]);
                        treeNodes[i] = maps.object2TreeNodeWithRecursive(records[i], subRecords, clazz);
                    } else {
                        treeNodes[i] = maps.object2TreeNode(records[i], clazz);
                    }
                }
                return treeNodes;
            }
        }
        return null;

    }

    private BSONObject[] getRecords() {
        DBObject conditionObject = generateConditionObject();
        DBObject havingObject = generateHavingConditionObject();
        DBObject orderObject = generateOrderObject();
        BSONObject[] records = persistence.find(displayObject, conditionObject, groupObject, havingObject,
                orderObject);
        return records;
    }

    public BSONObject[] getSubRecords(BSONObject bsonObject) {
        contextReplace(bsonObject);
        return getRecords();
    }

    /**
     * 
     * ??
     * 
     * @param bsonObject
     */
    private void contextReplace(BSONObject bsonObject) {
        List<ConditionField> conditionFields = view.getConditionFields();
        for (ConditionField conditionField : conditionFields) {
            String propertyName = getFieldName(conditionField.getFieldId());
            if (bsonObject.containsField(propertyName)) {
                Object value = bsonObject.get(propertyName);
                context.put(propertyName, value);
            }
        }
    }

    /**
     * 
     * view?
     * 
     * @param newContext
     * @param conditionFields
     * @return
     */
    public Context buildConditionParameter(Context newContext, List<ConditionField> conditionFields) {
        super.buildConditionFieldParamter(conditionFields, newContext);
        if (view.getHavingFields() != null) {
            for (HavingField havingField : view.getHavingFields()) {
                processHavingParamter(havingField, newContext);
            }
        }
        return newContext;
    }

    public DBObject generateDisplayObject() {
        List<ViewGroup> viewGroups = view.getViewGroups();
        if (viewGroups != null && viewGroups.size() > 0) {
            DBObject display = new BasicDBObject();
            for (ViewGroup viewGroup : viewGroups) {
                List<DisplayField> displayFields = viewGroup.getFields();
                for (DisplayField displayField : displayFields) {
                    MongoField field = getMongoField(displayField.getFieldId());
                    String propertyName = field.getFieldName();
                    String aggregateFunction = displayField.getAggregateFunction();
                    if (aggregateFunction != null) {
                        statistics.add(displayField);
                    }
                    display.put(propertyName, 1);
                }
            }
            return display;
        }
        return null;
    }

    public DBObject generateNestedDisplayObject() {
        List<ViewGroup> viewGroups = view.getViewGroups();
        if (viewGroups != null && viewGroups.size() > 0) {
            DBObject display = new BasicDBObject();
            for (ViewGroup viewGroup : viewGroups) {
                List<DisplayField> displayFields = viewGroup.getFields();
                for (DisplayField displayField : displayFields) {
                    MongoField field = getMongoField(displayField.getFieldId());
                    ObjectField of = field.getObjectField();
                    if (of != null) {
                        if (nestedObject == null) {
                            nestedObject = of.getName();
                        }
                        String propertyName = field.getFieldName();
                        display.put(propertyName, 1);
                    }

                }
            }
            return display;
        }
        return null;
    }

    /**
     * 
     * ?view?BSONObject
     * 
     * @return
     */
    public DBObject generateConditionObject() {
        return generateConditionObject(view.getConditionFields());
    }

    /**
     * 
     * ?viewhaving?BSONObject
     * 
     * @return
     */
    public DBObject generateHavingConditionObject() {
        List<ConditionField> conditionFields = new ArrayList<ConditionField>();
        conditionFields.addAll(view.getHavingFields());
        return generateConditionObject(conditionFields);
    }

    /**
     * 
     * ?viewBSONObject
     * 
     * @return
     */
    public DBObject generateGroupObject() {
        List<GroupField> groupFields = view.getGroupFields();
        if (!CollectionUtil.isEmpty(groupFields)) {
            BSONObject _group = new BasicDBObject();
            for (GroupField groupField : groupFields) {
                MongoField field = getMongoField(groupField.getFieldId());
                String propertyName = field.getFieldName();
                _group.put(propertyName, "$" + propertyName);
            }
            DBObject objectFields = new BasicDBObject("_id", _group);
            for (DisplayField displayField : statistics) {
                MongoField field = getMongoField(displayField.getFieldId());
                String propertyName = field.getFieldName();
                String aggregateFunction = displayField.getAggregateFunction();
                if (aggregateFunction != null) {
                    objectFields.put(propertyName + aggregateFunction,
                            new BasicDBObject("$" + aggregateFunction, "$" + propertyName));
                }
            }
            return objectFields;
        }
        return null;
    }

    public DBObject generateOrderObject() {
        List<OrderField> orderFields = view.getOrderFields();
        if (!CollectionUtil.isEmpty(orderFields)) {
            DBObject order = new BasicDBObject();
            for (OrderField orderField : orderFields) {
                MongoField field = getMongoField(orderField.getFieldId());
                String propertyName = field.getFieldName();
                if (orderField.getOrderMode() != null && orderField.getOrderMode().equals(DESC)) {
                    order.put(propertyName, -1);
                } else {
                    order.put(propertyName, 1);
                }
            }
            return order;
        }
        return null;
    }

    private void processHavingParamter(HavingField havingField, Context newContext) {
        Field field = getField(havingField.getFieldId());
        String propertyName = field.getName();
        String paramName = ModelUtil.getSpliceParamterName(propertyName, HAVING_FIELD);
        Object value = context.get(paramName);
        if (value == null) {
            if (havingField.isHidden()) {
                value = field.getDefaultValue();
            }
        }
        if (value != null) {
            newContext.put(paramName, value);
        }
        String compareParamterName = ModelUtil.getSpliceParamterName(propertyName, HAVING_COMPARE_MODE);
        Object compareModeValue = context.get(compareParamterName);
        if (compareModeValue != null) {
            newContext.put(compareParamterName, compareModeValue);
        }
    }

    public boolean hasGroupByField() {
        return !CollectionUtil.isEmpty(view.getGroupFields());
    }

    public boolean hasHavingField() {
        return !CollectionUtil.isEmpty(view.getHavingFields());
    }

    public boolean hasOrderField() {
        return !CollectionUtil.isEmpty(view.getOrderFields());
    }

}