/** {@inheritDoc} */ @Override public ReportDesignModel copyModel(String src, String targetName) throws ReportModelOperationException { if (StringUtils.isEmpty(src)) { logger.warn("source name is empty"); throw new ReportModelOperationException("source name is empty"); } if (StringUtils.isEmpty(targetName)) { logger.warn("target name is empty"); throw new ReportModelOperationException("target name is empty"); } if (isNameExist(targetName)) { throw new ReportModelOperationException("target name already exists: " + targetName); } if (isNameExist(src)) { ReportDesignModel model = getModelByIdOrName(src, false); model.setId(UuidGeneratorUtils.generate()); model.setName(targetName); MiniCubeSchema schema = (MiniCubeSchema) model.getSchema(); if (schema != null) { schema.setId(UuidGeneratorUtils.generate()); } return saveOrUpdateModel(model); } throw new ReportModelOperationException("source not exists: " + src); }
@Deprecated private String getOriReleaseReportLocation(ReportDesignModel model) { if (model == null) { return null; } String name = model.getName(); String productLine = ContextManager.getProductLine(); try { String[] listFile = fileService.ls(this.getReleaseReportDir()); for (String file : listFile) { if (file.startsWith(model.getId())) { return productLine + File.separator + reportBaseDir + File.separator + "release" + File.separator + file; } } } catch (FileServiceException e) { logger.error(e.getMessage(), e); } return productLine + File.separator + reportBaseDir + File.separator + "release" + File.separator + model.getId() + Constants.FILE_NAME_SEPERATOR + name; }
/** * 升级方法 * * @param model * @return String */ @Deprecated private String generateOriDevReportLocation(ReportDesignModel model) { if (model == null) { return null; } StringBuilder builder = new StringBuilder(); builder.append(getDevReportDir()); builder.append(File.separator); String name = null; try { String[] listFile = fileService.ls(this.getDevReportDir()); for (String file : listFile) { if (file.startsWith(model.getId())) { name = file; builder.append(name); break; } } } catch (FileServiceException e) { logger.error(e.getMessage(), e); } if (name == null) { builder.append(model.getId()); builder.append(Constants.FILE_NAME_SEPERATOR); builder.append(name); builder.append(Constants.FILE_NAME_SEPERATOR); builder.append(model.getDsId()); } return builder.toString(); }
/** * @param model * @return Map<String, List<Dimension>> */ private static Map<String, List<Dimension>> collectFilterDim(ReportDesignModel model) { Map<String, List<Dimension>> rs = Maps.newHashMap(); for (ExtendArea area : model.getExtendAreaList()) { if (isFilterArea(area.getType())) { Cube cube = model.getSchema().getCubes().get(area.getCubeId()); if (rs.get(area.getCubeId()) == null) { List<Dimension> dims = Lists.newArrayList(); area.listAllItems() .values() .forEach( key -> { MiniCubeDimension dim = (MiniCubeDimension) DeepcopyUtils.deepCopy(cube.getDimensions().get(key.getId())); dim.setLevels(Maps.newLinkedHashMap()); cube.getDimensions() .get(key.getId()) .getLevels() .values() .forEach( level -> { dim.getLevels().put(level.getName(), level); }); dims.add(dim); }); rs.put(area.getCubeId(), dims); } else { area.listAllItems() .values() .forEach( key -> { MiniCubeDimension dim = (MiniCubeDimension) DeepcopyUtils.deepCopy(cube.getDimensions().get(key.getId())); dim.setLevels(Maps.newLinkedHashMap()); ; cube.getDimensions() .get(key.getId()) .getLevels() .values() .forEach( level -> { dim.getLevels().put(level.getName(), level); }); rs.get(area.getCubeId()).add(dim); }); } } } return rs; }
/** * 依据model对象生成持久化文件名称 * * @param model * @return */ private String generateDevReportLocation(ReportDesignModel model) { if (model == null) { return null; } StringBuilder builder = new StringBuilder(); builder.append(getDevReportDir()); builder.append(File.separator); builder.append(model.getId()); builder.append(Constants.FILE_NAME_SEPERATOR); builder.append(model.getName().hashCode()); builder.append(Constants.FILE_NAME_SEPERATOR); builder.append(model.getDsId()); return builder.toString(); }
/** * 获取发布的报表的存储路径 * * @return */ private String getReleaseReportLocation(ReportDesignModel model) { if (model == null) { return null; } String productLine = ContextManager.getProductLine(); return productLine + File.separator + reportBaseDir + File.separator + "release" + File.separator + model.getId() + Constants.FILE_NAME_SEPERATOR + model.getName().hashCode(); }
/** {@inheritDoc} */ @Override public boolean updateReportModel(ReportDesignModel model, boolean modelInCache) { ReportDesignModel persModel = DeepcopyUtils.deepCopy(model); // 如果当前model在编辑状态,需要更新持久化的model的name if (isNameExist(model.getName(), model.getId())) { return false; } if (modelInCache) { persModel = getModelByIdOrName(model.getId(), false); } try { try { this.deleteModel(persModel, true); } catch (Exception e) { try { fileService.rm(generateOriDevReportLocation(persModel)); } catch (FileServiceException e1) { throw new ReportModelOperationException(e1); } } persModel.setName(model.getName()); this.saveOrUpdateModel(persModel); } catch (ReportModelOperationException e) { logger.error(e.getMessage(), e); return false; } return true; }
/** {@inheritDoc} */ @Override public ReportDesignModel saveOrUpdateModel(ReportDesignModel model) throws ReportModelOperationException { if (model == null) { logger.warn("current model is null"); throw new ReportModelOperationException("model can not be null"); } if (StringUtils.isEmpty(model.getName())) { logger.debug("model's name can not be empty"); throw new ReportModelOperationException("model's name can not be empty"); } if (StringUtils.isEmpty(model.getId())) { model.setId(UuidGeneratorUtils.generate()); } try { ReportDesignModel oldReport = getModelByIdOrName(model.getId(), false); if (oldReport != null) { try { this.deleteModel(oldReport, true); } catch (Exception e) { try { fileService.rm(generateOriDevReportLocation(model)); } catch (Exception e1) { logger.error(e.getMessage(), e); } } } boolean rs = fileService.write(generateDevReportLocation(model), SerializationUtils.serialize(model)); if (rs) { return model; } } catch (FileServiceException e) { logger.error(e.getMessage(), e); } return null; }
/** * @param reportModel * @param area * @return * @throws QueryModelBuildException */ private static Cube getCubeFromReportModel(ReportDesignModel reportModel, ExtendArea area) throws QueryModelBuildException { String cubeId = area.getCubeId(); if (StringUtils.isEmpty(cubeId)) { throw new QueryModelBuildException("cube id is empty"); } Schema schema = reportModel.getSchema(); if (schema == null) { throw new QueryModelBuildException("schema is not define"); } Map<String, ? extends Cube> cubes = schema.getCubes(); if (cubes == null) { throw new QueryModelBuildException("can not get cube define from schema : " + schema.getId()); } Cube oriCube = cubes.get(area.getCubeId()); if (oriCube == null) { throw new QueryModelBuildException( "can not get cube define from schema : " + area.getCubeId()); } return oriCube; }
/** * {@inheritDoc} * * @throws DataSourceOperationException */ @Override public boolean publishReport(ReportDesignModel model, String securityKey) throws ReportModelOperationException, DataSourceOperationException { boolean result = false; String devReportLocation = this.generateDevReportLocation(model); String realeaseLocation = this.getReleaseReportLocation(model); try { // 删除原来已经发布的报表,如果不存在,忽略此处异常 ReportDesignModel tmp = this.getModelByIdOrName(model.getId(), true); if (tmp != null) { try { fileService.rm(getReleaseReportLocation(tmp)); } catch (Exception e) { fileService.rm(getOriReleaseReportLocation(tmp)); } } } catch (FileServiceException e1) { logger.info(e1.getMessage(), e1); } try { result = this.fileService.copy(devReportLocation, realeaseLocation); } catch (FileServiceException e) { logger.error(e.getMessage(), e); throw new ReportModelOperationException("发布报表失败!"); } if (!result) { logger.error("拷贝报表失败!"); throw new ReportModelOperationException("发布报表失败!"); } /** 发布 */ DataSourceDefine dsDefine; DataSourceInfo dsInfo; try { dsDefine = dsService.getDsDefine(model.getDsId()); DataSourceConnectionService<?> dsConnService = DataSourceConnectionServiceFactory.getDataSourceConnectionServiceInstance( dsDefine.getDataSourceType().name()); dsInfo = dsConnService.parseToDataSourceInfo(dsDefine, securityKey); } catch (DataSourceOperationException e) { logger.error("Fail in Finding datasource define. ", e); throw e; } catch (DataSourceConnectionException e) { logger.error("Fail in parse datasource to datasourceInfo.", e); throw new DataSourceOperationException(e); } List<Cube> cubes = Lists.newArrayList(); for (ExtendArea area : model.getExtendAreaList()) { try { if ((area.getType() != ExtendAreaType.TABLE && area.getType() != ExtendAreaType.LITEOLAP_TABLE && area.getType() != ExtendAreaType.CHART && area.getType() != ExtendAreaType.LITEOLAP_CHART) || area.getType() == ExtendAreaType.PLANE_TABLE || QueryUtils.isFilterArea(area.getType())) { continue; } Cube cube = QueryUtils.getCubeWithExtendArea(model, area); cubes.add(cube); } catch (QueryModelBuildException e) { logger.warn("It seems that logicmodel of area is null. Ingore this area. "); continue; } } if (cubes.size() == 0) { logger.info("cube is empty, don't need to create index!"); return true; } new Thread() { public void run() { MiniCubeConnection connection = MiniCubeDriverManager.getConnection(dsInfo); connection.publishCubes(cubes, dsInfo); } }.start(); return true; }
/** * 修正报表区域模型参数 * * @param request * @param model */ public static Map<String, Object> resetContextParam( final HttpServletRequest request, ReportDesignModel model) { Map<String, Object> rs = Maps.newHashMap(); Collection<ReportParam> params = DeepcopyUtils.deepCopy(model.getParams()).values(); // modify by jiangyichao at 2015-05-19 Collection<PlaneTableCondition> planeTableConditions = DeepcopyUtils.deepCopy(model.getPlaneTableConditions()).values(); if (params.size() == 0 && planeTableConditions.size() == 0) { return rs; } LOG.info("context params ============== " + ContextManager.getParams()); // 当前请求参数 Map<String, String> requestParams = collectRequestParams(params, request); rs.putAll(requestParams); LOG.info("current request params ============== " + requestParams); // TODO 先处理P功能对应的参数 if (params.size() != 0) { params.forEach( param -> { LOG.info("current param define ============== " + param.toString()); if (param.isNeeded() && StringUtils.isEmpty(requestParams.get(param.getName()))) { if (StringUtils.isEmpty(param.getDefaultValue())) { throw new RuntimeException("必要参数未赋值"); } rs.put(param.getElementId(), param.getDefaultValue()); rs.put(param.getName(), param.getDefaultValue()); } else if (!StringUtils.isEmpty(requestParams.get(param.getName()))) { rs.put(param.getElementId(), requestParams.get(param.getName())); } else if (!StringUtils.isEmpty(param.getDefaultValue())) { rs.put(param.getElementId(), param.getDefaultValue()); rs.put(param.getName(), param.getDefaultValue()); } }); } // 处理平面表对应的条件 if (planeTableConditions.size() != 0) { planeTableConditions.forEach( condition -> { LOG.info("current planeTable condition define ============== " + condition.toString()); // 如果请求参数中没有条件对应的参数,则使用默认值对应的参数值 if (StringUtils.isEmpty(requestParams.get(condition.getName()))) { rs.put(condition.getElementId(), condition.getDefaultValue()); rs.put(condition.getName(), condition.getDefaultValue()); } else if (!StringUtils.isEmpty(requestParams.get(condition.getName()))) { // 如果请求参数中有条件对应的参数,则取请求参数中的参数值 // TODO 对时间条件和层级条件做特殊处理 String requestParam = requestParams.get(condition.getName()); // 处理时间条件 // requestParam = // PlaneTableUtils.handleTimeCondition(requestParam); // 处理层级条件 // requestParam = // PlaneTableUtils.handleLayerCondition(requestParam); rs.put(condition.getElementId(), requestParam); } }); } LOG.info("after reset params is : " + rs); return rs; }
/** * 获取扩展区域包含的立方体定义 * * @param reportModel 报表模型 * @param area 扩展区域 * @return 立方体定义 * @throws QueryModelBuildException */ public static Cube getCubeWithExtendArea(ReportDesignModel reportModel, ExtendArea area) throws QueryModelBuildException { Cube oriCube = getCubeFromReportModel(reportModel, area); // 对于可选指标,默认将事实表包含的所有列作为查询条件 if ("true".equals(area.getOtherSetting().get(Constants.CAN_CHANGED_MEASURE))) { Cube rs = transformCube(oriCube); modifyMeasures(rs.getMeasures(), rs); return rs; } Map<String, List<Dimension>> filterDims = collectFilterDim(reportModel); MiniCube cube = new MiniCube(area.getCubeId()); String areaId = area.getId(); LogicModel logicModel = area.getLogicModel(); if (area.getType() == ExtendAreaType.SELECTION_AREA || area.getType() == ExtendAreaType.LITEOLAP_CHART || area.getType() == ExtendAreaType.LITEOLAP_TABLE) { LiteOlapExtendArea liteOlapArea = (LiteOlapExtendArea) reportModel.getExtendById(area.getReferenceAreaId()); logicModel = liteOlapArea.getLogicModel(); areaId = area.getReferenceAreaId(); } if (logicModel == null) { throw new QueryModelBuildException("logic model is empty"); } Item[] items = logicModel.getItems(area.getType() != ExtendAreaType.TABLE); Map<String, Dimension> dimensions = new HashMap<String, Dimension>(); Map<String, Measure> measures = new HashMap<String, Measure>(); for (Item item : items) { OlapElement olapElement = oriCube.getDimensions().get(item.getOlapElementId()); if (olapElement == null) { // 维度不存在或者可能是指标信息 olapElement = oriCube.getMeasures().get(item.getOlapElementId()); if (olapElement != null) { Measure measure = (Measure) olapElement; measures.put(measure.getName(), measure); } } else { MiniCubeDimension dim = (MiniCubeDimension) DeepcopyUtils.deepCopy(olapElement); dim.setLevels(Maps.newLinkedHashMap()); ; ((Dimension) olapElement) .getLevels() .values() .forEach( level -> { level.setDimension(dim); dim.getLevels().put(level.getName(), level); }); dimensions.put(dim.getName(), dim); } } if (area.getType() == ExtendAreaType.LITEOLAP) { /** TODO 把liteOlap中候选的维度和指标加入到items里面 */ Map<String, Item> candDims = ((LiteOlapExtendArea) area).getCandDims(); Schema schema = reportModel.getSchema(); String cubeId = area.getCubeId(); for (String elementId : candDims.keySet()) { OlapElement element = ReportDesignModelUtils.getDimOrIndDefineWithId(schema, cubeId, elementId); MiniCubeDimension dim = (MiniCubeDimension) DeepcopyUtils.deepCopy(element); dim.setLevels(Maps.newLinkedHashMap()); ((Dimension) element) .getLevels() .values() .forEach( level -> { level.setDimension(dim); dim.getLevels().put(level.getName(), level); }); dimensions.put(element.getName(), (Dimension) element); } Map<String, Item> candInds = ((LiteOlapExtendArea) area).getCandInds(); for (String elementId : candInds.keySet()) { OlapElement element = ReportDesignModelUtils.getDimOrIndDefineWithId(schema, cubeId, elementId); if (element instanceof CallbackMeasure) { CallbackMeasure m = DeepcopyUtils.deepCopy((CallbackMeasure) element); String url = ((CallbackMeasure) element).getCallbackUrl(); m.setCallbackUrl(HttpUrlUtils.getBaseUrl(url)); m.setCallbackParams(HttpUrlUtils.getParams(url)); measures.put(m.getName(), m); } else { measures.put(element.getName(), (Measure) element); } } } if (filterDims != null) { List<Dimension> dims = filterDims.get(area.getCubeId()); if (dims != null) { for (Dimension dim : dims) { if (dim != null) { dimensions.put(dim.getName(), dim); } } } // TODO 处理不同cube共用同一查询条件情况 filterDims.forEach( (key, dimArray) -> { if (key != null && !key.equals(area.getCubeId())) { dimArray .stream() .filter( dim -> { return dim instanceof TimeDimension; }) .forEach( dim -> { for (Dimension tmp : oriCube.getDimensions().values()) { if (dim.getName().equals(tmp.getName())) { MiniCubeDimension tmpDim = (MiniCubeDimension) DeepcopyUtils.deepCopy(dim); tmpDim.setLevels((LinkedHashMap<String, Level>) tmp.getLevels()); tmpDim.setFacttableColumn(tmp.getFacttableColumn()); tmpDim.setFacttableCaption(tmp.getFacttableCaption()); dimensions.put(tmpDim.getName(), tmpDim); } } }); } }); } cube.setDimensions(dimensions); modifyMeasures(measures, oriCube); cube.setMeasures(measures); cube.setSource(((MiniCube) oriCube).getSource()); cube.setPrimaryKey(((MiniCube) oriCube).getPrimaryKey()); cube.setId(oriCube.getId() + "_" + areaId); return cube; }
/** * 将查询动作转化成问题模型 * * @param dsDefine * @param queryAction 查询动作 * @return 问题模型 * @throws QueryModelBuildException 构建失败异常 */ public static QuestionModel convert2QuestionModel( DataSourceDefine dsDefine, ReportDesignModel reportModel, QueryAction queryAction, Map<String, Object> requestParams, PageInfo pageInfo, String securityKey) throws QueryModelBuildException { if (queryAction == null) { throw new QueryModelBuildException("query action is null"); } ConfigQuestionModel questionModel = new ConfigQuestionModel(); String areaId = queryAction.getExtendAreaId(); if (StringUtils.isEmpty(areaId)) { throw new QueryModelBuildException("area id is empty"); } ExtendArea area = reportModel.getExtendById(areaId); if (area == null) { throw new QueryModelBuildException("can not get area with id : " + areaId); } Cube cube = getCubeFromReportModel(reportModel, area); if (cube == null) { throw new QueryModelBuildException("can not get cube define in area : " + areaId); } if (area.getType() == ExtendAreaType.PLANE_TABLE) { cube = transformCube(cube); MiniCube miniCube = (MiniCube) cube; DivideTableStrategyVo divideVo = miniCube.getDivideTableStrategyVo(); DivideTableContext divideContext = new DivideTableContext(); DivideTableService divideTableService = null; if (divideVo != null) { switch (divideVo.getCondition()) { case "yyyyMMdd": divideTableService = new DayDivideTableStrategyServiceImpl(); break; case "yyyyMM": divideTableService = new MonthDivideTableStrategyServiceImpl(); break; case "yyyy": divideTableService = new YearDivideTableStrategyServiceImpl(); break; default: throw new UnsupportedOperationException("暂时不支持该分表策略"); } divideContext.setDivideTableService(divideTableService); if (divideContext.getAllFactTableName(divideVo, requestParams) != null) { miniCube.setSource(divideContext.getAllFactTableName(divideVo, requestParams)); } MiniCubeSchema schema = (MiniCubeSchema) reportModel.getSchema(); schema.getCubes().put(miniCube.getId(), miniCube); reportModel.setSchema(schema); } miniCube.setProductLine(dsDefine.getProductLine()); questionModel.setCube(miniCube); } else { cube = getCubeWithExtendArea(reportModel, area); ((MiniCube) cube).setProductLine(dsDefine.getProductLine()); questionModel.setCube(cube); } // 设置轴信息 questionModel.setAxisMetas(buildAxisMeta(reportModel.getSchema(), area, queryAction)); questionModel.setCubeId(area.getCubeId()); // TODO 动态更新cube 针对查询过程中动态添加的属性 需要仔细考虑此处逻辑 Set<Item> tmp = Sets.newHashSet(); tmp.addAll(queryAction.getSlices().keySet()); tmp.addAll(queryAction.getRows().keySet()); try { DataSourceInfo dataSource = DataSourceConnectionServiceFactory.getDataSourceConnectionServiceInstance( dsDefine.getDataSourceType().name()) .parseToDataSourceInfo(dsDefine, securityKey); questionModel.setDataSourceInfo(dataSource); } catch (Exception e) { throw new RuntimeException(e); } OrderDesc orderDesc = queryAction.getOrderDesc(); if (orderDesc != null) { SortType sortType = SortType.valueOf(orderDesc.getOrderType()); String uniqueName = ""; if (DataModelUtils.isMeasure(orderDesc.getName(), cube)) { uniqueName = uniqueName + "[Measure]."; } else { uniqueName = uniqueName + "[Dimension]."; } uniqueName = uniqueName + "[" + orderDesc.getName() + "]"; SortRecord sortRecord = new SortRecord(sortType, uniqueName, orderDesc.getRecordSize()); questionModel.setSortRecord(sortRecord); } // TODO 此处没有考虑指标、维度交叉情况,如后续有指标维度交叉情况,此处需要调整 questionModel.getQueryConditionLimit().setWarningAtOverFlow(false); if (queryAction.isNeedOthers()) { // TODO 需要开发通用工具包 将常量定义到通用工具包中 questionModel.getRequestParams().put("NEED_OTHERS", "1"); } // 设置请求参数信息 if (requestParams != null) { for (String key : requestParams.keySet()) { Object value = requestParams.get(key); if (value != null && value instanceof String) { questionModel.getRequestParams().put(key, (String) value); } } // 设计器中, 设置分页信息 if (requestParams.get(Constants.IN_EDITOR) != null && Boolean.valueOf(requestParams.get(Constants.IN_EDITOR).toString())) { questionModel.setPageInfo(pageInfo); } } if (area.getType() == ExtendAreaType.PLANE_TABLE) { questionModel.setQuerySource("SQL"); // 对于平面表不使用汇总方式 questionModel.setNeedSummary(false); // 设置分页信息 questionModel.setPageInfo(pageInfo); // 针对平面表构建查询条件 Map<String, MetaCondition> conditionsForPlaneTable = QueryConditionUtils.buildQueryConditionsForPlaneTable(reportModel, area, queryAction); questionModel.setQueryConditions(conditionsForPlaneTable); } else { questionModel.setQuerySource("TESSERACT"); // 针对其他情况构建查询条件 Map<String, MetaCondition> conditionsForPivotTable = QueryConditionUtils.buildQueryConditionsForPivotTable(reportModel, area, queryAction); questionModel.setQueryConditions(conditionsForPivotTable); if (queryAction.getDrillDimValues() == null || !queryAction.getDrillDimValues().isEmpty() || queryAction.isChartQuery()) { questionModel.setNeedSummary(false); } else { ExtendAreaType areaType = reportModel.getExtendById(queryAction.getExtendAreaId()).getType(); if (areaType != ExtendAreaType.TABLE) { questionModel.setNeedSummary(false); } else { questionModel.setNeedSummary(needSummary(questionModel)); } } if (questionModel.isNeedSummary() && "false".equals(area.getOtherSetting().get("needSummary"))) { questionModel.setNeedSummary(false); } } questionModel.setUseIndex(true); putSliceConditionIntoParams(queryAction, questionModel); questionModel.setFilterBlank(queryAction.isFilterBlank()); return questionModel; }