com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextBuilder.java

Source

/**
 * Copyright (c) 2014 Baidu, Inc. All Rights Reserved.
 *
 * 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.baidu.rigel.biplatform.tesseract.qsservice.query;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baidu.rigel.biplatform.ac.exception.MiniCubeQueryException;
import com.baidu.rigel.biplatform.ac.minicube.CallbackLevel;
import com.baidu.rigel.biplatform.ac.minicube.MiniCube;
import com.baidu.rigel.biplatform.ac.minicube.MiniCubeMeasure;
import com.baidu.rigel.biplatform.ac.minicube.MiniCubeMember;
import com.baidu.rigel.biplatform.ac.model.Cube;
import com.baidu.rigel.biplatform.ac.model.Dimension;
import com.baidu.rigel.biplatform.ac.model.Level;
import com.baidu.rigel.biplatform.ac.model.LevelType;
import com.baidu.rigel.biplatform.ac.model.Member;
import com.baidu.rigel.biplatform.ac.query.data.DataSourceInfo;
import com.baidu.rigel.biplatform.ac.query.model.AxisMeta;
import com.baidu.rigel.biplatform.ac.query.model.AxisMeta.AxisType;
import com.baidu.rigel.biplatform.ac.query.model.DimensionCondition;
import com.baidu.rigel.biplatform.ac.query.model.MeasureCondition;
import com.baidu.rigel.biplatform.ac.query.model.MetaCondition;
import com.baidu.rigel.biplatform.ac.query.model.QueryData;
import com.baidu.rigel.biplatform.ac.query.model.QuestionModel;
import com.baidu.rigel.biplatform.ac.util.DeepcopyUtils;
import com.baidu.rigel.biplatform.ac.util.MetaNameUtil;
import com.baidu.rigel.biplatform.tesseract.exception.MetaException;
import com.baidu.rigel.biplatform.tesseract.meta.MetaDataService;
import com.baidu.rigel.biplatform.tesseract.meta.impl.CallbackDimensionMemberServiceImpl;
import com.baidu.rigel.biplatform.tesseract.model.MemberNodeTree;
import com.baidu.rigel.biplatform.tesseract.qsservice.query.vo.QueryContext;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/** 
 *  
 * @author xiaoming.chen
 * @version  20141226 
 * @since jdk 1.8 or after
 */
@Service
public class QueryContextBuilder {

    /**
     * TODO ?
     */
    public static final String FILTER_DIM_KEY = "filter_Dim_Key";

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private MetaDataService metaDataService;

    @Autowired
    private CallbackDimensionMemberServiceImpl callbackDimensionService;

    public static Map<String, String> getRequestParams(QuestionModel questionModel, Cube cube) {
        Map<String, String> rs = Maps.newHashMap();
        rs.putAll(questionModel.getRequestParams());
        StringBuilder filterDimNames = new StringBuilder();
        if (questionModel.getQueryConditions() != null && questionModel.getQueryConditions().size() > 0) {
            questionModel.getQueryConditions().forEach((k, v) -> {
                Dimension dim = cube.getDimensions().get(k);
                MiniCube miniCube = (MiniCube) cube;
                if (dim != null && miniCube.getSource().equals(dim.getTableName())) {
                    DimensionCondition cond = (DimensionCondition) v;
                    StringBuilder sb = new StringBuilder();
                    List<QueryData> queryDataNodes = cond.getQueryDataNodes();
                    int size = queryDataNodes.size();
                    String[] strArray = null;
                    for (int index = 0; index < size; ++index) {
                        QueryData data = queryDataNodes.get(index);
                        strArray = MetaNameUtil.parseUnique2NameArray(data.getUniqueName());
                        sb.append(strArray[strArray.length - 1]);
                        if (index < size - 1) {
                            sb.append(",");
                        }
                    }
                    filterDimNames.append(cond.getMetaName());
                    rs.put(cond.getMetaName(), sb.toString());
                }
            });
        }
        rs.put(FILTER_DIM_KEY, filterDimNames.toString());
        return rs;
    }

    /**
     * 
     * 
     * @param questionModel 
     * @param dsInfo ???
     * @param cube cube
     * @param queryContext 
     * @return ?
     * @throws MiniCubeQueryException 
     * @throws MetaException
     */
    public QueryContext buildQueryContext(QuestionModel questionModel, DataSourceInfo dsInfo, Cube cube,
            QueryContext queryContext) throws MiniCubeQueryException, MetaException {
        if (queryContext == null) {
            queryContext = new QueryContext();
            QuestionModel cloneQuestionModel = DeepcopyUtils.deepCopy(questionModel);
            long current = System.currentTimeMillis();
            AxisMeta axisMeta = null;
            AxisType axisType = AxisType.COLUMN;
            Map<String, String> requestParams = questionModel.getRequestParams();
            while (axisType != null && (axisMeta = cloneQuestionModel.getAxisMetas().get(axisType)) != null) {
                if (CollectionUtils.isNotEmpty(axisMeta.getCrossjoinDims())) {
                    int i = 0;
                    for (String dimName : axisMeta.getCrossjoinDims()) {
                        DimensionCondition dimCondition = (DimensionCondition) cloneQuestionModel
                                .getQueryConditions().remove(dimName);
                        if (dimCondition == null) {
                            dimCondition = new DimensionCondition(dimName);
                        }
                        queryContext.addMemberNodeTreeByAxisType(axisType, buildQueryMemberTree(dsInfo, cube,
                                dimCondition, i == 0, questionModel.getRequestParams()));
                        i++;
                    }
                }
                logger.info("cost:{}ms in build axisTye:{},axisMeta:{}", System.currentTimeMillis() - current,
                        axisType, axisMeta);
                current = System.currentTimeMillis();
                if (CollectionUtils.isNotEmpty(axisMeta.getQueryMeasures())) {
                    for (String measureName : axisMeta.getQueryMeasures()) {
                        if (cube.getMeasures().containsKey(measureName)) {
                            queryContext.getQueryMeasures()
                                    .add((MiniCubeMeasure) cube.getMeasures().get(measureName));
                        }
                        // ?cube???????????
                    }
                }
                logger.info("cost:{}ms in build axisTye:{},axisMeta:{}", System.currentTimeMillis() - current,
                        axisType, axisMeta);
                current = System.currentTimeMillis();
                if (axisType.equals(AxisType.ROW)) {
                    axisType = null;
                } else {
                    axisType = AxisType.ROW;
                }
            }

            if (!cloneQuestionModel.getQueryConditions().isEmpty()) {
                for (MetaCondition condition : cloneQuestionModel.getQueryConditions().values()) {
                    if (condition == null) {
                        logger.warn("meta condition is null,skip.");
                        continue;
                    }
                    if (condition instanceof DimensionCondition) {
                        DimensionCondition dimCondition = (DimensionCondition) condition;
                        Map<String, Set<String>> filterCondition = buildFilterCondition(dsInfo, cube, dimCondition,
                                requestParams);
                        if (MapUtils.isNotEmpty(filterCondition)) {
                            queryContext.getFilterMemberValues().putAll(filterCondition);
                        }
                    } else {
                        MeasureCondition measureCon = (MeasureCondition) condition;
                        // ?
                        queryContext.getFilterExpression().put(measureCon.getMetaName(),
                                measureCon.getMeasureConditions());
                    }
                    logger.info("cost:{}ms,in build filter conditon:{}", System.currentTimeMillis() - current,
                            condition);
                    current = System.currentTimeMillis();
                }
            }
        }
        return queryContext;
    }

    /**
     * ?
     * 
     * @param dataSourceInfo ???
     * @param cube cube?
     * @param dimCondition ?
     * @param params ?
     * @return ?
     * @throws MiniCubeQueryException 
     * @throws MetaException ??
     */
    public Map<String, Set<String>> buildFilterCondition(DataSourceInfo dataSourceInfo, Cube cube,
            DimensionCondition dimCondition, Map<String, String> params)
            throws MiniCubeQueryException, MetaException {
        if (dimCondition == null) {
            throw new IllegalArgumentException("dimension condition is null");
        }
        if (dimCondition.getQueryDataNodes().isEmpty()) {
            logger.info("filter axises ignore all member filter");
            return null;
        }
        Map<String, Set<String>> filterValues = new HashMap<>();

        Dimension dimension = cube.getDimensions().get(dimCondition.getMetaName());
        boolean hasCallbackLevel = false;
        int callbackLevelIndex = 0;
        List<String> callbackParams = null;
        List<Level> levels = Lists.newArrayList(dimension.getLevels().values());
        for (int i = 0; i < levels.size(); i++) {
            if (levels.get(i).getType().equals(LevelType.CALL_BACK)) {
                hasCallbackLevel = true;
                callbackLevelIndex = i;
                callbackParams = new ArrayList<>();
                break;
            }
        }

        for (QueryData queryData : dimCondition.getQueryDataNodes()) {
            if (MetaNameUtil.isAllMemberUniqueName(queryData.getUniqueName())) {
                logger.info("filter axises ignore all member filter");
                return null;
            }
            String[] names = MetaNameUtil.parseUnique2NameArray(queryData.getUniqueName());
            if (hasCallbackLevel && (names.length - 2 == callbackLevelIndex)) {
                callbackParams.add(names[names.length - 1]);
                continue;
            } else {
                MiniCubeMember member = metaDataService.lookUp(dataSourceInfo, cube, queryData.getUniqueName(),
                        params);
                if (member != null) {
                    String querySource = member.getLevel().getFactTableColumn();
                    Set<String> nodes = CollectionUtils.isEmpty(member.getQueryNodes())
                            ? Sets.newHashSet(member.getName())
                            : member.getQueryNodes();
                    if (filterValues.containsKey(querySource)) {
                        filterValues.get(querySource).addAll(nodes);
                    } else {
                        filterValues.put(querySource, nodes);
                    }
                } else {
                    logger.warn("can not found member by query data:{}", queryData);
                }
            }
        }
        if (hasCallbackLevel && CollectionUtils.isNotEmpty(callbackParams)) {
            Map<String, String> newParams = new HashMap<>(params);
            newParams.put(dimCondition.getMetaName(), StringUtils.join(callbackParams, ","));
            List<MiniCubeMember> callbackMembers = callbackDimensionService.getMembers(cube,
                    levels.get(callbackLevelIndex), dataSourceInfo, null, newParams);
            String querySource = null;
            if (CollectionUtils.isNotEmpty(callbackMembers)) {
                for (MiniCubeMember member : callbackMembers) {
                    querySource = member.getLevel().getFactTableColumn();
                    Set<String> nodes = CollectionUtils.isEmpty(member.getQueryNodes())
                            ? Sets.newHashSet(member.getName())
                            : member.getQueryNodes();
                    if (filterValues.containsKey(querySource)) {
                        filterValues.get(querySource).addAll(nodes);
                    } else {
                        filterValues.put(querySource, nodes);
                    }

                }
            }
        }

        return filterValues;
    }

    /**
     * ??
     * 
     * @param dataSourceInfo ???
     * @param cube cube
     * @param dimCondition ?
     * @param isFirstInRow ?
     * @return 
     * @throws MiniCubeQueryException 
     * @throws MetaException
     */
    public MemberNodeTree buildQueryMemberTree(DataSourceInfo dataSourceInfo, Cube cube,
            DimensionCondition dimCondition, boolean isFirstInRow, Map<String, String> params)
            throws MiniCubeQueryException, MetaException {
        if (dimCondition == null) {
            throw new IllegalArgumentException("dimension condition is null");
        }
        long current = System.currentTimeMillis();
        MemberNodeTree nodeTree = new MemberNodeTree(null);
        if (dimCondition.getQueryDataNodes().isEmpty()) {
            String allMemberUniqueName = cube.getDimensions().get(dimCondition.getMetaName()).getAllMember()
                    .getUniqueName();
            QueryData queryData = new QueryData(allMemberUniqueName);
            queryData.setExpand(isFirstInRow);
            queryData.setShow(true);
            dimCondition.getQueryDataNodes().add(queryData);
            logger.info("cost:{}ms,in build default member:{}", System.currentTimeMillis() - current, dimCondition);
            current = System.currentTimeMillis();
        }
        Dimension dimension = cube.getDimensions().get(dimCondition.getMetaName());
        boolean hasCallbackLevel = false;
        int callbackLevelIndex = 0;
        List<String> callbackParams = null;
        List<Level> levels = Lists.newArrayList(dimension.getLevels().values());
        for (int i = 0; i < levels.size(); i++) {
            if (levels.get(i).getType().equals(LevelType.CALL_BACK)) {
                hasCallbackLevel = true;
                callbackLevelIndex = i;
                callbackParams = new ArrayList<>();
                break;
            }
        }
        for (QueryData queryData : dimCondition.getQueryDataNodes()) {
            String[] names = MetaNameUtil.parseUnique2NameArray(queryData.getUniqueName());

            if (hasCallbackLevel && (names.length - 2 == callbackLevelIndex)) {
                callbackParams.add(names[names.length - 1]);
                continue;
            } else {
                MiniCubeMember member = metaDataService.lookUp(dataSourceInfo, cube, queryData.getUniqueName(),
                        params);

                MemberNodeTree memberNode = new MemberNodeTree(nodeTree);
                List<MemberNodeTree> childNodes = new ArrayList<MemberNodeTree>();
                //   ??,
                // FIXME  ?Callback
                if (queryData.isExpand()) {
                    List<MiniCubeMember> children = Lists.newArrayList();
                    try {
                        children = metaDataService.getChildren(dataSourceInfo, cube, member, params);
                    } catch (Exception e) {
                        // TODO NONE ?? ?
                    }
                    if (CollectionUtils.isNotEmpty(children)) {
                        memberNode.setSummary(true);
                        children.forEach((child) -> {
                            MemberNodeTree childNode = new MemberNodeTree(nodeTree);
                            buildMemberNodeByMember(dataSourceInfo, cube, childNode, child, params);
                            childNodes.add(childNode);
                            //                        member.getQueryNodes().addAll(child.getQueryNodes());
                        });
                    }
                }
                // ?????
                if (queryData.isShow() || CollectionUtils.isEmpty(childNodes)) {
                    buildMemberNodeByMember(dataSourceInfo, cube, memberNode, member, params);
                    memberNode.setChildren(childNodes);
                    nodeTree.getChildren().add(memberNode);
                    //                return memberNode;
                } else {
                    nodeTree.getChildren().addAll(childNodes);
                }
            }

        }
        if (hasCallbackLevel && CollectionUtils.isNotEmpty(callbackParams)) {
            Map<String, String> newParams = new HashMap<>(params);
            newParams.put(dimCondition.getMetaName(), StringUtils.join(callbackParams, ","));
            List<MiniCubeMember> callbackMembers = callbackDimensionService.getMembers(cube,
                    levels.get(callbackLevelIndex), dataSourceInfo, null, newParams);
            if (CollectionUtils.isNotEmpty(callbackMembers)) {
                if (callbackMembers.size() == 1) {
                    List<Member> children = callbackMembers.get(0).getChildren();
                    MemberNodeTree parentNode = new MemberNodeTree(nodeTree);
                    buildMemberNodeByMember(dataSourceInfo, cube, parentNode, callbackMembers.get(0), params);
                    if (CollectionUtils.isNotEmpty(children)) {
                        children.forEach((child) -> {
                            MemberNodeTree childNode = new MemberNodeTree(nodeTree);
                            buildMemberNodeByMember(dataSourceInfo, cube, childNode, (MiniCubeMember) child,
                                    params);
                            parentNode.getChildren().add(childNode);
                        });
                    }
                    nodeTree.getChildren().add(parentNode);
                } else {
                    callbackMembers.forEach((child) -> {
                        MemberNodeTree childNode = new MemberNodeTree(nodeTree);
                        buildMemberNodeByMember(dataSourceInfo, cube, childNode, child, params);
                        nodeTree.getChildren().add(childNode);
                    });
                }
            }
        }
        // ?DESCASC?
        nodeTree.sort(dimCondition.getMemberSortType());
        logger.info("cost:{}ms,in build dimCondition:{}", System.currentTimeMillis() - current, dimCondition);
        return nodeTree;
    }

    /**
     * ?
     * @param node 
     * @param member 
     */
    private void buildMemberNodeByMember(DataSourceInfo dataSource, Cube cube, MemberNodeTree node,
            MiniCubeMember member, Map<String, String> params) {
        node.setCaption(member.getCaption());
        if (CollectionUtils.isNotEmpty(member.getQueryNodes())) {
            node.setLeafIds(member.getQueryNodes());
        } else {
            node.getLeafIds().add(member.getName());
        }
        node.setName(member.getName());
        node.setUniqueName(member.getUniqueName());
        node.setOrdinal(member.getName());
        // ??
        node.setQuerySource(member.getLevel().getFactTableColumn());

        // ???????
        if (member.isAll()) {
            node.setHasChildren(true);
        } else if (member.getLevel() instanceof CallbackLevel) {
            if (CollectionUtils.isNotEmpty(member.getQueryNodes())) {
                node.setHasChildren(true);
            }
        } else {
            // TODO ?
            List<MiniCubeMember> children = null;
            try {
                children = metaDataService.getChildren(dataSource, cube, member, params);
            } catch (Exception e) {
                logger.warn(e.getMessage(), e);
            }
            if (CollectionUtils.isNotEmpty(children)) {
                node.setHasChildren(true);
            }
            //            Dimension dim = member.getLevel().getDimension();
            //            List<String> levelNames = Lists.newArrayList(dim.getLevels().keySet());
            //            for (int i = 0; i < levelNames.size(); i++) {
            //                if (member.getLevel().getName().equals(levelNames.get(i))) {
            //                    if (i < levelNames.size() - 1) {
            //                        node.setHasChildren(true);
            //                    }
            //                    break;
            //                }
            //            }
        }

    }

}