Java tutorial
/** * 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.impl; import java.util.List; 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.MiniCubeMember; import com.baidu.rigel.biplatform.ac.model.Cube; 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.model.ConfigQuestionModel; import com.baidu.rigel.biplatform.ac.query.model.PageInfo; import com.baidu.rigel.biplatform.ac.query.model.QuestionModel; import com.baidu.rigel.biplatform.ac.util.MetaNameUtil; import com.baidu.rigel.biplatform.tesseract.dataquery.udf.condition.CallbackCondition; import com.baidu.rigel.biplatform.tesseract.datasource.DataSourcePoolService; import com.baidu.rigel.biplatform.tesseract.exception.MetaException; import com.baidu.rigel.biplatform.tesseract.exception.OverflowQueryConditionException; import com.baidu.rigel.biplatform.tesseract.isservice.exception.IndexAndSearchException; import com.baidu.rigel.biplatform.tesseract.isservice.exception.IndexAndSearchExceptionType; import com.baidu.rigel.biplatform.tesseract.isservice.search.service.SearchService; import com.baidu.rigel.biplatform.tesseract.isservice.search.service.impl.CallbackSearchServiceImpl; import com.baidu.rigel.biplatform.tesseract.meta.MetaDataService; import com.baidu.rigel.biplatform.tesseract.model.MemberNodeTree; import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextBuilder; import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextSplitService; import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryContextSplitService.QueryContextSplitStrategy; import com.baidu.rigel.biplatform.tesseract.qsservice.query.QueryRequestBuilder; 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.qsservice.query.vo.QueryContextSplitResult; import com.baidu.rigel.biplatform.tesseract.qsservice.query.vo.QueryRequest; import com.baidu.rigel.biplatform.tesseract.resultset.isservice.SearchIndexResultSet; import com.baidu.rigel.biplatform.tesseract.util.DataModelBuilder; import com.baidu.rigel.biplatform.tesseract.util.QueryRequestUtil; import com.baidu.rigel.biplatform.tesseract.util.TesseractExceptionUtils; import com.baidu.rigel.biplatform.tesseract.util.isservice.LogInfoConstants; /** * ? * * @author xiaoming.chen * */ @Service public class QueryServiceImpl implements QueryService { /** * Logger */ private Logger logger = LoggerFactory.getLogger(this.getClass()); /** * searchService */ @Resource private SearchService searchService; /** * metaDataService */ @Resource private MetaDataService metaDataService; /** * dataSourcePoolService */ @Resource private DataSourcePoolService dataSourcePoolService; /** * queryContextSplitService */ @Resource private QueryContextSplitService queryContextSplitService; @Resource private QueryContextBuilder queryContextBuilder; @Autowired private CallbackSearchServiceImpl callbackSearchService; @Override public DataModel query(QuestionModel questionModel, QueryContext queryContext, QueryContextSplitStrategy preSplitStrategy) throws MiniCubeQueryException { long current = System.currentTimeMillis(); if (questionModel == null) { throw new IllegalArgumentException("questionModel is null"); } DataSourceInfo dataSourceInfo = null; Cube cube = null; // if (questionModel instanceof ConfigQuestionModel) { ConfigQuestionModel configQuestionModel = (ConfigQuestionModel) questionModel; dataSourceInfo = configQuestionModel.getDataSourceInfo(); cube = configQuestionModel.getCube(); // ???cache // questionModel.setUseIndex(false); } if (cube == null) { cube = metaDataService.getCube(questionModel.getCubeId()); } if (dataSourceInfo == null) { dataSourceInfo = dataSourcePoolService.getDataSourceInfo(questionModel.getDataSourceInfoKey()); } logger.info("cost :" + (System.currentTimeMillis() - current) + " to get datasource and other data"); current = System.currentTimeMillis(); try { queryContext = queryContextBuilder.buildQueryContext(questionModel, dataSourceInfo, cube, queryContext); } catch (MetaException e1) { e1.printStackTrace(); throw new MiniCubeQueryException(e1); } logger.info("cost :" + (System.currentTimeMillis() - current) + " to build query context."); // ?????? int conditionDescartes = stateQueryContextConditionCount(queryContext, questionModel.isNeedSummary()); logger.info("query condition descarte:" + conditionDescartes); logger.debug("question model:{}", questionModel); if (questionModel.getQueryConditionLimit().isWarningAtOverFlow() && conditionDescartes > questionModel.getQueryConditionLimit().getWarnningConditionSize()) { StringBuilder sb = new StringBuilder(); sb.append("condition descartes :").append(conditionDescartes).append(" over :") .append(questionModel.getQueryConditionLimit()).append(""); logger.error(sb.toString()); throw new OverflowQueryConditionException(sb.toString()); } // QueryContextSplitResult splitResult = queryContextSplitService.split(questionModel, dataSourceInfo, cube, queryContext, preSplitStrategy); DataModel result = null; // ? // TODO if (splitResult != null && (!splitResult.getCompileContexts().isEmpty() || !splitResult.getConditionQueryContext().isEmpty())) { DataSourceInfo dsInfo = dataSourceInfo; Cube finalCube = cube; // TODO ,??? splitResult.getConditionQueryContext().forEach((con, context) -> { DataModel dm = null; if (con instanceof CallbackCondition) { try { SearchIndexResultSet resultSet = callbackSearchService.query(context, QueryRequestBuilder .buildQueryRequest(dsInfo, finalCube, context, questionModel.isUseIndex(), null)); dm = new DataModelBuilder(resultSet, context).build(true); } catch (Exception e) { logger.error("catch error when process callback measure {}", e.getMessage()); throw new RuntimeException(e); } } else { dm = executeQuery(dsInfo, finalCube, context, questionModel.isUseIndex(), questionModel.getPageInfo()); } splitResult.getDataModels().put(con, dm); }); result = queryContextSplitService.mergeDataModel(splitResult); } else { result = executeQuery(dataSourceInfo, cube, queryContext, questionModel.isUseIndex(), questionModel.getPageInfo()); } return result; } private DataModel executeQuery(DataSourceInfo dataSourceInfo, Cube cube, QueryContext queryContext, boolean useIndex, PageInfo pageInfo) throws MiniCubeQueryException { long current = System.currentTimeMillis(); QueryRequest queryRequest = QueryRequestBuilder.buildQueryRequest(dataSourceInfo, cube, queryContext, useIndex, pageInfo); logger.info("transfer queryContext:{} to queryRequest:{} cost:{} ", queryContext, queryRequest, System.currentTimeMillis() - current); if (statDimensionNode(queryContext.getRowMemberTrees(), false, false) == 0 || (statDimensionNode(queryContext.getColumnMemberTrees(), false, false) == 0 && CollectionUtils.isEmpty(queryContext.getQueryMeasures()))) { return new DataModelBuilder(null, queryContext).build(false); } logger.info("cost :" + (System.currentTimeMillis() - current) + " to build query request."); current = System.currentTimeMillis(); DataModel result = null; try { SearchIndexResultSet resultSet = searchService.query(queryRequest); if (queryRequest.getGroupBy() != null && CollectionUtils.isNotEmpty(queryRequest.getGroupBy().getGroups())) { try { resultSet = QueryRequestUtil.processGroupBy(resultSet, queryRequest, queryContext); } catch (NoSuchFieldException e) { e.printStackTrace(); logger.error(String.format(LogInfoConstants.INFO_PATTERN_FUNCTION_EXCEPTION, "query", "[query:" + queryRequest + "]", e)); throw new IndexAndSearchException( TesseractExceptionUtils.getExceptionMessage( IndexAndSearchException.QUERYEXCEPTION_MESSAGE, IndexAndSearchExceptionType.SEARCH_EXCEPTION), e, IndexAndSearchExceptionType.SEARCH_EXCEPTION); } } result = new DataModelBuilder(resultSet, queryContext).build(false); } catch (IndexAndSearchException e) { logger.error("query occur when search queryRequest" + queryContext, e); throw new MiniCubeQueryException(e); } logger.info("cost :" + (System.currentTimeMillis() - current) + " to execute query."); return result; } private int stateQueryContextConditionCount(QueryContext context, boolean needSummary) { if (context == null) { throw new IllegalArgumentException("querycontext is null."); } // ? int rowConditionCount = statDimensionNode(context.getRowMemberTrees(), needSummary, true); // ?? int columnConditionCount = statDimensionNode(context.getColumnMemberTrees(), needSummary, false); int filterConditionCount = 1; if (MapUtils.isNotEmpty(context.getFilterMemberValues())) { for (Set<String> nodeIds : context.getFilterMemberValues().values()) { filterConditionCount *= nodeIds.size(); } } return rowConditionCount * columnConditionCount * filterConditionCount; } /** * ????? * * @param treeNodes * @param needSummary * @return */ private int statDimensionNode(List<MemberNodeTree> treeNodes, boolean needSummary, boolean isRow) { int rowConditionCount = 0; if (CollectionUtils.isNotEmpty(treeNodes)) { for (MemberNodeTree nodeTree : treeNodes) { int dimensionLeafIdCount = 0; // name????? if (StringUtils.isBlank(nodeTree.getName()) || MetaNameUtil.isAllMemberName(nodeTree.getName())) { // ??????????? for (MemberNodeTree child : nodeTree.getChildren()) { // ????? if (isRow && needSummary) { nodeTree.setName(MiniCubeMember.SUMMARY_NODE_NAME); nodeTree.setUniqueName(MiniCubeMember.SUMMARY_NODE_NAME); nodeTree.setCaption(MiniCubeMember.SUMMARY_NODE_CAPTION); nodeTree.setSummary(true); nodeTree.setQuerySource(child.getQuerySource()); nodeTree.getLeafIds().addAll(child.getLeafIds()); } if (nodeTree.getLeafIds().size() == 1 && MetaNameUtil.isAllMemberName(nodeTree.getLeafIds().iterator().next())) { continue; } else { dimensionLeafIdCount += child.getLeafIds().size(); } } } else { dimensionLeafIdCount = nodeTree.getLeafIds().size(); } if (rowConditionCount == 0) { rowConditionCount = dimensionLeafIdCount; } else { // ???dimensionLeafIdCount?0 rowConditionCount *= (dimensionLeafIdCount == 0 ? 1 : dimensionLeafIdCount); } } } return rowConditionCount; } }