com.baidu.rigel.biplatform.tesseract.action.MetaQueryAction.java Source code

Java tutorial

Introduction

Here is the source code for com.baidu.rigel.biplatform.tesseract.action.MetaQueryAction.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.action;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.slf4j.MDC;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.baidu.rigel.biplatform.ac.exception.MiniCubeQueryException;
import com.baidu.rigel.biplatform.ac.minicube.MiniCubeMember;
import com.baidu.rigel.biplatform.ac.model.Cube;
import com.baidu.rigel.biplatform.ac.query.MiniCubeConnection;
import com.baidu.rigel.biplatform.ac.query.data.DataModel;
import com.baidu.rigel.biplatform.ac.query.data.DataSourceInfo;
import com.baidu.rigel.biplatform.ac.query.data.HeadField;
import com.baidu.rigel.biplatform.ac.query.data.vo.MetaJsonDataInfo;
import com.baidu.rigel.biplatform.ac.query.model.ConfigQuestionModel;
import com.baidu.rigel.biplatform.ac.query.model.DimensionCondition;
import com.baidu.rigel.biplatform.ac.query.model.MetaCondition;
import com.baidu.rigel.biplatform.ac.query.model.SortRecord;
import com.baidu.rigel.biplatform.ac.util.AnswerCoreConstant;
import com.baidu.rigel.biplatform.ac.util.DataModelUtils;
import com.baidu.rigel.biplatform.ac.util.DeepcopyUtils;
import com.baidu.rigel.biplatform.ac.util.JsonUnSeriallizableUtils;
import com.baidu.rigel.biplatform.ac.util.MetaNameUtil;
import com.baidu.rigel.biplatform.ac.util.ResponseResult;
import com.baidu.rigel.biplatform.ac.util.ResponseResultUtils;
import com.baidu.rigel.biplatform.tesseract.datasource.DataSourcePoolService;
import com.baidu.rigel.biplatform.tesseract.exception.DataSourceException;
import com.baidu.rigel.biplatform.tesseract.exception.MetaException;
import com.baidu.rigel.biplatform.tesseract.meta.MetaDataService;
import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextBuilder;
import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextSplitService.QueryContextSplitStrategy;
import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryService;
import com.baidu.rigel.biplatform.tesseract.qsservice.query.vo.QueryContext;
import com.baidu.rigel.biplatform.tesseract.util.TesseractConstant;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;

/**
 * ???memberschildren
 * 
 * @author xiaoming.chen
 *
 */

@RestController
public class MetaQueryAction {

    private static Logger LOG = LoggerFactory.getLogger(MetaQueryAction.class);

    @Resource
    private MetaDataService metaDataService;

    @Resource
    private QueryService queryService;

    @Resource
    private DataSourcePoolService dataSourcePoolService;

    @RequestMapping(value = "/meta/getMembers", method = RequestMethod.POST)
    //    @ResponseBody
    public ResponseResult getMembers(@RequestBody String requestJson) {
        // ?JSON?
        if (StringUtils.isBlank(requestJson)) {
            return ResponseResultUtils.getErrorResult("get members question is null", 100);
        }
        List<MiniCubeMember> members;
        String errorMsg = null;
        try {
            Map<String, String> requestParams = parseRequestJson(requestJson);

            ConfigQuestionModel questionModel = AnswerCoreConstant.GSON.fromJson(
                    requestParams.get(MiniCubeConnection.QUESTIONMODEL_PARAM_KEY), ConfigQuestionModel.class);
            setMDCContext(questionModel.getRequestParams().get("_flag"));
            members = null;
            // ?queryCondition
            String dimName = null;
            String levelName = null;
            if (MapUtils.isNotEmpty(questionModel.getQueryConditions())) {
                // ??
                dimName = questionModel.getQueryConditions().keySet().toArray(new String[] {})[0];
                // ?
                MetaCondition dimConfition = questionModel.getQueryConditions().get(dimName);
                if (dimConfition instanceof DimensionCondition) {
                    // levelmembers?UniqueNamelevelname
                    levelName = ((DimensionCondition) dimConfition).getQueryDataNodes().get(0).getUniqueName();
                } else {
                    errorMsg = "meta condition is illegal";
                }
                DataSourceInfo dataSourceInfo = questionModel.getDataSourceInfo();
                if (dataSourceInfo == null) {
                    dataSourceInfo = dataSourcePoolService.getDataSourceInfo(questionModel.getDataSourceInfoKey());
                }
                Cube cube = questionModel.getCube();
                if (cube == null) {
                    cube = metaDataService.getCube(questionModel.getCubeId());
                }
                JsonUnSeriallizableUtils.fillCubeInfo(cube);
                levelName = MetaNameUtil.parseUnique2NameArray(levelName)[1];

                members = metaDataService.getMembers(dataSourceInfo, cube, dimName, levelName,
                        questionModel.getRequestParams());
                List<MetaJsonDataInfo> metaJsons = new ArrayList<MetaJsonDataInfo>(members.size());
                if (CollectionUtils.isNotEmpty(members)) {
                    for (MiniCubeMember member : members) {
                        metaJsons.add(JsonUnSeriallizableUtils.parseMember2MetaJson(member));
                    }
                }
                StringBuilder sb = new StringBuilder();
                sb.append("get ").append(members.size()).append(" members from dimension:").append(dimName)
                        .append(" in level:").append(levelName);
                return ResponseResultUtils.getCorrectResult(sb.toString(), metaJsons);
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            // ?
            errorMsg = "json syntax exception:" + e.getMessage();
        } catch (MiniCubeQueryException e) {
            e.printStackTrace();
            errorMsg = "query members error:" + e.getMessage();
        } catch (MetaException e) {
            e.printStackTrace();
            errorMsg = "meta is illegal," + e.getMessage();
        }
        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);
    }

    @RequestMapping(value = "/meta/getChildren", method = RequestMethod.POST)
    //    @ResponseBody
    public ResponseResult getChildren(@RequestBody String requestJson) {
        // ?JSON?
        if (StringUtils.isBlank(requestJson)) {
            return ResponseResultUtils.getErrorResult("get members question is null", 100);
        }
        List<MiniCubeMember> children;
        String errorMsg = null;
        try {
            Map<String, String> requestParams = parseRequestJson(requestJson);

            ConfigQuestionModel questionModel = AnswerCoreConstant.GSON.fromJson(
                    requestParams.get(MiniCubeConnection.QUESTIONMODEL_PARAM_KEY), ConfigQuestionModel.class);
            setMDCContext(questionModel.getRequestParams().get("_flag"));
            children = null;
            // ?queryCondition
            String uniqueName = null;
            String metaName = null;
            if (MapUtils.isNotEmpty(questionModel.getQueryConditions())) {
                // ??
                metaName = questionModel.getQueryConditions().keySet().toArray(new String[] {})[0];
                // ?
                MetaCondition dimConfition = questionModel.getQueryConditions().get(metaName);
                if (dimConfition instanceof DimensionCondition) {
                    uniqueName = ((DimensionCondition) dimConfition).getQueryDataNodes().get(0).getUniqueName();
                } else {
                    errorMsg = "meta condition is illegal";
                }
                DataSourceInfo dataSourceInfo = questionModel.getDataSourceInfo();
                if (dataSourceInfo == null) {
                    dataSourceInfo = dataSourcePoolService.getDataSourceInfo(questionModel.getDataSourceInfoKey());
                }
                Cube cube = questionModel.getCube();
                if (cube == null) {
                    cube = metaDataService.getCube(questionModel.getCubeId());
                }
                JsonUnSeriallizableUtils.fillCubeInfo(cube);

                children = metaDataService.getChildren(dataSourceInfo, cube, uniqueName,
                        QueryContextBuilder.getRequestParams(questionModel, cube));
                if (CollectionUtils.isNotEmpty(children)) {
                    List<MetaJsonDataInfo> metaJsons = new ArrayList<MetaJsonDataInfo>(children.size());
                    for (MiniCubeMember member : children) {
                        metaJsons.add(JsonUnSeriallizableUtils.parseMember2MetaJson(member));
                    }
                    StringBuilder sb = new StringBuilder();
                    sb.append("get ").append(children.size()).append(" children from dimension:").append(metaName)
                            .append(" by uniqueName:").append(uniqueName);
                    return ResponseResultUtils.getCorrectResult(sb.toString(), metaJsons);
                }
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            // ?
            errorMsg = "json syntax exception:" + e.getMessage();
        } catch (MiniCubeQueryException e) {
            e.printStackTrace();
            errorMsg = "query children error:" + e.getMessage();
        } catch (MetaException e) {
            e.printStackTrace();
            errorMsg = "meta is illegal," + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            errorMsg = "server error,msg" + e.getMessage();
        }
        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);
    }

    @RequestMapping(value = "/query", method = RequestMethod.POST)
    //    @ResponseBody
    public ResponseResult query(@RequestBody String requestJson) {
        long current = System.currentTimeMillis();
        // ?JSON?
        if (StringUtils.isBlank(requestJson)) {
            return ResponseResultUtils.getErrorResult("get members question is null", 100);
        }
        String errorMsg = null;
        try {
            Map<String, String> requestParams = parseRequestJson(requestJson);

            ConfigQuestionModel questionModel = AnswerCoreConstant.GSON.fromJson(
                    requestParams.get(MiniCubeConnection.QUESTIONMODEL_PARAM_KEY), ConfigQuestionModel.class);
            setMDCContext(questionModel.getRequestParams().get("_flag"));
            DataSourceInfo dataSourceInfo = questionModel.getDataSourceInfo();
            if (dataSourceInfo == null) {
                dataSourceInfo = dataSourcePoolService.getDataSourceInfo(questionModel.getDataSourceInfoKey());
            }
            Cube cube = questionModel.getCube();
            if (cube == null) {
                cube = metaDataService.getCube(questionModel.getCubeId());
            }
            JsonUnSeriallizableUtils.fillCubeInfo(cube);
            questionModel.setDataSourceInfo(dataSourceInfo);
            questionModel.setCube(cube);
            QueryContext queryContext = null;
            QueryContextSplitStrategy preSplitStrategy = null;
            // ??
            if (requestParams.containsKey(MiniCubeConnection.QUERYCONTEXT_PARAM_KEY)) {
                queryContext = AnswerCoreConstant.GSON
                        .fromJson(requestParams.get(MiniCubeConnection.QUERYCONTEXT_PARAM_KEY), QueryContext.class);
            }
            if (requestParams.containsKey(MiniCubeConnection.SPLITSTRATEGY_PARAM_KEY)) {
                preSplitStrategy = AnswerCoreConstant.GSON.fromJson(
                        requestParams.get(MiniCubeConnection.SPLITSTRATEGY_PARAM_KEY),
                        QueryContextSplitStrategy.class);
            }

            DataModel dataModel = queryService.query(questionModel, queryContext, preSplitStrategy);
            if (dataModel != null) {
                if (questionModel.isFilterBlank()) {
                    DataModelUtils.filterBlankRow(dataModel);
                }
                dataModel = sortAndTrunc(dataModel, questionModel.getSortRecord(),
                        questionModel.getRequestParams().get(TesseractConstant.NEED_OTHERS));
            }
            LOG.info("cost:" + (System.currentTimeMillis() - current) + " success to execute query.");
            return ResponseResultUtils.getCorrectResult("query success.",
                    AnswerCoreConstant.GSON.toJson(dataModel));

        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            // ?
            errorMsg = "json syntax exception:" + e.getMessage();
        } catch (MiniCubeQueryException e) {
            e.printStackTrace();
            errorMsg = "query error:" + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            errorMsg = "unexpected error:" + e.getMessage();
        }
        LOG.error("cost:" + (System.currentTimeMillis() - current) + " error,errorMsg:" + errorMsg);
        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);
    }

    public static Map<String, String> parseRequestJson(String requestJson) {
        String[] requestArray = requestJson.split("&");
        Map<String, String> requestParams = new HashMap<String, String>();
        for (String request : requestArray) {
            String[] keyValue = request.split("=");
            String value = keyValue[1];
            try {
                value = URLDecoder.decode(value, "utf-8");
            } catch (UnsupportedEncodingException e) {
                LOG.warn("decode value:" + value + " error", e);
            }
            requestParams.put(keyValue[0], value);
        }
        return requestParams;
    }

    @RequestMapping(value = "/publish", method = RequestMethod.POST)
    @ResponseBody
    public ResponseResult publish(@RequestBody String requestJson) {
        String errorMsg = null;
        try {
            if (StringUtils.isBlank(requestJson)) {
                return ResponseResultUtils.getErrorResult("get members question is null", 100);
            }

            Map<String, String> requestParams = parseRequestJson(requestJson);

            String listCubeJson = requestParams.get(MiniCubeConnection.CUBE_PARAM_KEY);
            String dataSourceJson = requestParams.get(MiniCubeConnection.DATASOURCEINFO_PARAM_KEY);
            List<Cube> cubes = AnswerCoreConstant.GSON.fromJson(listCubeJson, new TypeToken<List<Cube>>() {
            }.getType());
            DataSourceInfo dataSourceInfo = AnswerCoreConstant.GSON.fromJson(dataSourceJson, DataSourceInfo.class);
            metaDataService.publish(cubes, dataSourceInfo);
            return ResponseResultUtils.getCorrectResult("success", "public cubes success.");
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            errorMsg = "json parse error," + e.getMessage();
        } catch (DataSourceException e) {
            e.printStackTrace();
            errorMsg = "init datasource error." + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            errorMsg = "unexpected error:" + e.getMessage();
        }

        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);
    }

    @RequestMapping(value = "/lookUp", method = RequestMethod.POST)
    @ResponseBody
    public ResponseResult lookUp(@RequestBody String requestJson) {
        String errorMsg = null;
        try {
            if (StringUtils.isBlank(requestJson)) {
                return ResponseResultUtils.getErrorResult("get members question is null", 100);
            }

            Map<String, String> requestParams = parseRequestJson(requestJson);

            ConfigQuestionModel questionModel = AnswerCoreConstant.GSON.fromJson(
                    requestParams.get(MiniCubeConnection.QUESTIONMODEL_PARAM_KEY), ConfigQuestionModel.class);
            setMDCContext(questionModel.getRequestParams().get("_flag"));
            MetaCondition uniqueNameCondition = questionModel.getQueryConditions()
                    .get(MiniCubeConnection.UNIQUENAME_PARAM_KEY);

            if (uniqueNameCondition != null && uniqueNameCondition instanceof DimensionCondition) {
                DimensionCondition dimCondition = (DimensionCondition) uniqueNameCondition;
                String uniqueName = CollectionUtils.isNotEmpty(dimCondition.getQueryDataNodes())
                        ? dimCondition.getQueryDataNodes().get(0).getUniqueName()
                        : null;
                Cube cube = questionModel.getCube();
                MiniCubeMember member = metaDataService.lookUp(questionModel.getDataSourceInfo(), cube, uniqueName,
                        QueryContextBuilder.getRequestParams(questionModel, cube));

                return ResponseResultUtils.getCorrectResult("return member:" + member.getName(),
                        JsonUnSeriallizableUtils.parseMember2MetaJson(member));
            }
            errorMsg = "can not get uniquename info from questionmodel:"
                    + requestParams.get(MiniCubeConnection.QUESTIONMODEL_PARAM_KEY);

        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            errorMsg = "json parse error," + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            errorMsg = "unexpected error:" + e.getMessage();
        }

        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);
    }

    @RequestMapping(value = "/refresh", method = RequestMethod.POST)
    @ResponseBody
    public ResponseResult refresh(@RequestBody String requestJson) {
        // ?JSON?
        String errorMsg = null;
        try {
            if (StringUtils.isBlank(requestJson)) {
                return ResponseResultUtils.getErrorResult("get members question is null", 100);
            }

            Map<String, String> requestParams = parseRequestJson(requestJson);

            String dataSetString = requestParams.get(MiniCubeConnection.DATASET_PARAM_KEY);
            String dataSourceJson = requestParams.get(MiniCubeConnection.DATASOURCEINFO_PARAM_KEY);
            String paramsJason = requestParams.get(MiniCubeConnection.PARAMS);

            Map<String, Map<String, BigDecimal>> params = AnswerCoreConstant.GSON.fromJson(paramsJason,
                    new TypeToken<Map<String, Map<String, BigDecimal>>>() {
                    }.getType());
            DataSourceInfo dataSourceInfo = AnswerCoreConstant.GSON.fromJson(dataSourceJson, DataSourceInfo.class);

            metaDataService.refresh(dataSourceInfo, dataSetString, params);

            return ResponseResultUtils.getCorrectResult("success", "refresh success.");
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            errorMsg = "json parse error," + e.getMessage();
        } catch (DataSourceException e) {
            e.printStackTrace();
            errorMsg = "init datasource error." + e.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
            errorMsg = "unexpected error:" + e.getMessage();
        }

        // ???100???
        return ResponseResultUtils.getErrorResult(errorMsg, 100);

    }

    /**
     * ?500?
     * @param result
     * @param sortRecord
     * @param needOthers 
     * @return DataModel
     */
    private DataModel sortAndTrunc(DataModel result, SortRecord sortRecord, String needOthers) {
        if (sortRecord != null) {
            DataModelUtils.sortDataModelBySort(result, sortRecord);
        }
        if (sortRecord == null) {
            return result;
        }
        //            int recordSize = sortRecord == null ? 500 : sortRecord.getRecordSize();
        //  
        if (TesseractConstant.NEED_OTHERS_VALUE.equals(needOthers)) {
            //TODO ???? ????
            return tonNSetting4Chart(result, sortRecord);
        }
        return DataModelUtils.truncModel(result, sortRecord.getRecordSize());
    }

    private void setMDCContext(String value) {
        if (StringUtils.isNotBlank(value)) {
            MDC.put("REQUESTFLAG", value);
        }
    }

    /**
     * 
     * @param result
     * @param sortRecord
     * @return DataModel
     */
    private DataModel tonNSetting4Chart(DataModel result, SortRecord sortRecord) {
        BigDecimal sum = BigDecimal.ZERO;
        for (BigDecimal tmp : result.getColumnBaseData().get(0)) {
            //TODO ??
            if (tmp == null) {
                continue;
            }
            sum = sum.add(tmp);
        }
        // 
        result = DataModelUtils.truncModel(result, sortRecord.getRecordSize() - 1);
        BigDecimal sum1 = BigDecimal.ZERO;
        for (BigDecimal tmp : result.getColumnBaseData().get(0)) {
            //TODO ??
            if (tmp == null) {
                continue;
            }
            sum1 = sum1.add(tmp);
        }
        BigDecimal other = null;
        if (sum1 != BigDecimal.ZERO) {
            other = sum.subtract(sum1);
        }
        result.getColumnBaseData().get(0).add(other);
        HeadField otherRowField = DeepcopyUtils.deepCopy(result.getRowHeadFields().get(0));
        otherRowField.setSummarizeData(other);
        String caption = "";
        otherRowField.setCaption(caption);
        String dimName = MetaNameUtil.getDimNameFromUniqueName(otherRowField.getValue());
        String uniqueName = "[" + dimName + "].[" + caption + "]";
        String nodeUniqueName = "{" + uniqueName + "}";
        otherRowField.setNodeUniqueName(nodeUniqueName);
        otherRowField.setValue(uniqueName);
        result.getRowHeadFields().add(otherRowField);
        return result;
    }
}