package com.ycsoft.report.query.cube.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.ycsoft.commons.exception.ReportException; import com.ycsoft.commons.helper.StringHelper; import com.ycsoft.report.bean.RepCube; import com.ycsoft.report.query.cube.CellType; import com.ycsoft.report.query.cube.CubeDataSet; import com.ycsoft.report.query.cube.CubeHeadCell; import com.ycsoft.report.query.cube.CubeExec; import com.ycsoft.report.query.cube.Dimension; import com.ycsoft.report.query.cube.DimensionRolap; import com.ycsoft.report.query.cube.DimensionType; import com.ycsoft.report.query.cube.Measure; import com.ycsoft.report.query.cube.graph.CubeGraph; import com.ycsoft.report.query.key.Impl.QueryKeyValue; /** * cube实现类 * */ public class Cube implements CubeExec { /** * 横向维清单 */ private List<Dimension> crosswiseDimensions = new ArrayList<Dimension>();; /** * 纵向维清单 */ private List<Dimension> verticalDimensions = new ArrayList<Dimension>(); /** * 维容器 */ Map<Dimension, DimensionRolap> dimconMap = new HashMap<Dimension, DimensionRolap>(); /** * 有效度量清单 */ private List<Measure> measures = new ArrayList<Measure>(); private Map<String,Measure> meaMap=new HashMap<String,Measure>(); /** * 表头属性 */ private CubeHeadCell[] headcells; public Cube(List<RepCube> repcubelist) throws ReportException { for (RepCube repcube : repcubelist) { if (repcube.getColumn_type().equals(DimensionType.crosswise.name())) { DimensionContainer dimcon = new DimensionContainer(repcube); dimconMap.put(dimcon.getDim(), dimcon); crosswiseDimensions.add(dimcon.getDim()); } else if (repcube.getColumn_type().equals(DimensionType.vertical.name())) { DimensionContainer dimcon = new DimensionContainer(repcube); dimconMap.put(dimcon.getDim(), dimcon); verticalDimensions.add(dimcon.getDim()); } else if(repcube.getColumn_type().equals(DimensionType.measure.name())){ Measure mea = new MeasureImpl(repcube); measures.add(mea); this.meaMap.put(mea.getColumnCode(), mea); } else{ throw new ReportException(repcube.getColumn_type()+": rep_cube.column_type is undefined."); } } } /** * cube执行计算得到Olap数据体 */ public CubeDataSet execute(CubeDataSet t) throws ReportException { t.setCube(this); t.assembleCubeDataSet(); this.headcells=t.getBaseHeadCells(); t.execute(); return t; } /** * 图形计算 */ public CubeGraph executeGraph(CubeDataSet t, CubeGraph graph) throws ReportException { //标题等设置 Measure mea= this.meaMap.get(graph.getMeasure()); if(mea==null) throw new ReportException(graph.getGraphType().getDesc()+":mea is undefind"); graph.getGraphData().setYtitle(mea.getColumnText()); StringBuilder subtitle=new StringBuilder(); subtitle.append("维:"); if(graph.getCrossDimension()!=null){ DimensionRolap rolap= this.dimconMap.get(graph.getCrossDimension()); if(rolap==null) throw new ReportException(graph.getCrossDimension().getId()+" is undefind in cube."); String level_name=rolap.getDim().getLevel(rolap.getLevel()).getName(); subtitle.append(rolap.getName()).append("(").append(level_name).append("),"); graph.getGraphData().setXtitle(level_name); } if(graph.getVertDimension()!=null){ DimensionRolap rolap= this.dimconMap.get(graph.getVertDimension()); if(rolap==null) throw new ReportException(graph.getVertDimension().getId()+" is undefind in cube."); String level_name=rolap.getDim().getLevel(rolap.getLevel()).getName(); subtitle.append(rolap.getName()).append("(") .append(level_name).append("),"); graph.getGraphData().setXtitle(level_name); } subtitle.append("指标:").append(mea.getColumnText()).append("_").append(mea.getCalculation()); graph.getGraphData().setSubtitle(subtitle.toString()); //组装图形数据源 t.assembleGraphDataSet(graph); return t.graph(graph); } /** * cube预览,主要是提供Olap表头效果查看 */ public List<CubeHeadCell[]> preview(List<DimensionRolap> dimrolaps,List<Measure> mealist) throws ReportException { //CubeSqlContainer sqlcon=assembleSql(dimrolaps,mealist); //return this.createOlapHead(sqlcon.getBaseHeadCells(), dimrolaps,mealist); return null; } /** * 验证cube的配置是否正确 * @throws ReportException */ public String validate(CubeDataSet t) throws ReportException { if(this.measures.size()<=0) return "error:no measure."; if(this.verticalDimensions.size()>1) return "error:verticalDimension >1 "; t.setCube(this); t.assembleCubeDataSet(); return t.validate(); } public List<DimensionRolap> getDimensionRolaps() { List<DimensionRolap> list=new ArrayList<DimensionRolap>(); for(Dimension dim:this.crosswiseDimensions){ list.add(this.dimconMap.get(dim)); } for(Dimension dim:this.verticalDimensions){ list.add(this.dimconMap.get(dim)); } for(DimensionRolap dimcon: this.dimconMap.values()){ if(!dimcon.isUsesign()) list.add(dimcon); } return list; } public List<Measure> getMeasures() { return this.measures; } /** * 展开一个维度 * level+1 */ public void expandDimension(Dimension dim) { DimensionContainer dimrolap= (DimensionContainer)this.dimconMap.get(dim); if(dimrolap!=null&&dimrolap.getLevel()<dimrolap.getDim().getLevelNum()){ dimrolap.setLevel(dimrolap.getLevel()+1); } } /** * 收缩一个维度 * level-1 */ public void shrinkDimension(Dimension dim) { DimensionContainer dimrolap= (DimensionContainer)this.dimconMap.get(dim); if(dimrolap!=null&&dimrolap.getLevel()>1){ dimrolap.setLevel(dimrolap.getLevel()-1); } } /** * 维度切片 * 指定层切片 * @throws ReportException */ public void slicesDimension(Dimension dim,Integer level,String...values) throws ReportException { DimensionContainer dimcon=(DimensionContainer)this.dimconMap.get(dim); if(dimcon==null) throw new ReportException("dim is null or undefined in cube."); if(values==null||values.length==0){ dimcon.setSlices_level(null); dimcon.setSlices_value(null); }else{ for(String o:values){ if(o==null||o.equals("")) throw new ReportException(o+":values[i] is null"); if(!DimensionLevelValueManage.getDimLevelValueMap(dimcon.getDim().getLevel(level)).containsKey(o)){ throw new ReportException(o+":values[i] is not in dimlevel_valuelist."); } } dimcon.setSlices_level(level); dimcon.setSlices_value(values); } } /** * 维度层级自定义排序 */ public void sortDimension(Dimension dim, Map<Integer,String[]> sortmap)throws ReportException { DimensionContainer dimcon=(DimensionContainer)this.dimconMap.get(dim); if(dimcon==null) throw new ReportException("dim is null or undefined in cube."); dimcon.setLevel_sort_map(sortmap); } public DimensionRolap getDimensionRolap(Dimension dim) { return this.dimconMap.get(dim); } public void selectDimension(Dimension vertdim,Dimension... dims) throws ReportException { Map<Dimension,Boolean> map=new HashMap<Dimension,Boolean>(); if(dims!=null&&dims.length>0){ for(Dimension dim:dims){ map.put(dim, false); if(!this.dimconMap.containsKey(dim)) throw new ReportException(dim.getId()+": dim is null or undefiend in cube"); } this.crosswiseDimensions.clear(); for(Dimension dim:dims){ if(!dim.equals(vertdim)) this.crosswiseDimensions.add(dim); } }else{ this.crosswiseDimensions.clear(); } if(vertdim!=null){ if(!this.dimconMap.containsKey(vertdim)) throw new ReportException(vertdim.getId()+": dim is undefiend in cube"); map.put(vertdim, true); this.verticalDimensions.clear(); this.verticalDimensions.add(vertdim); }else{ this.verticalDimensions.clear(); } for(DimensionRolap o: this.dimconMap.values()){ DimensionContainer con=(DimensionContainer)o; if(map.containsKey(con.getDim())){ con.setUsesign(true); con.setVerticalsign(map.get(o.getDim())); }else{ con.setUsesign(false); con.setVerticalsign(false); //不使用的维度,清空切片内容 this.slicesDimension(con.getDim(),null); } } } /** * 顺序 使用+未使用 */ public List<Measure> getDefaultMeasures() { List<Measure> list=new ArrayList<Measure>(); Map<String,String> map=new HashMap<String,String>(); list.addAll(this.measures); for(Measure mea:this.measures){ map.put(mea.getColumnCode(), null); } for(String key:this.meaMap.keySet()){ if(!map.containsKey(key)){ list.add(this.meaMap.get(key)); } } return list; } public void selectMeasure(String... meas) throws ReportException { if(meas==null||meas.length==0) throw new ReportException("error:meas.size<1"); List<Measure> list=new ArrayList<Measure>(); for(String mea:meas){ if(this.meaMap.containsKey(mea)){ list.add(this.meaMap.get(mea)); }else{ throw new ReportException(mea+":mea is undefined in cube."); } } this.measures=list; } public void configDimensionTotal(Dimension dim, Integer... levels) throws ReportException { DimensionContainer rolap=(DimensionContainer) this.dimconMap.get(dim); if(rolap==null) throw new ReportException("dim is null or undefined in cube"); if(levels!=null&&levels.length>0){ for(Integer o:levels){ if(o==null) throw new ReportException("level is null"); if(o>rolap.getDim().getLevelNum()||o<1) throw new ReportException("level>dim.levelnum or level<1."); } } rolap.setLevelTotal(levels); } public List<CubeHeadCell[]> getCubeHead() throws ReportException { return createOlapHead(this.headcells,this.getDimensionRolaps(),this.measures); } /** * 创建维度表头层 * 最外层,最高层表头 * @param headcells * @return */ private CubeHeadCell[] createDimHead(CubeHeadCell[] headcells){ List<CubeHeadCell> dimcelllist=new ArrayList<CubeHeadCell>(); CubeHeadCellImpl dimcell=null; for(CubeHeadCell cell:headcells){ if(dimcell==null||StringHelper.isEmpty(cell.getDim())||!dimcell.getDim().equals(cell.getDim())){ //维不同 dimcell=new CubeHeadCellImpl(cell); dimcell.setId(null); dimcell.setName(dimcell.getDim()==null?"":DimensionManage.getDimension(dimcell.getDim()).getName()); dimcell.setRowspan(1); /** * 判断哪些按钮要显示 */ if(StringHelper.isEmpty(dimcell.getDim())){ dimcell.setShow_expand(false); dimcell.setShow_shrink(false); dimcell.setShow_slices(false); }else{ dimcell.setShow_expand(true); dimcell.setShow_shrink(true); dimcell.setShow_slices(true); dimcell.setShow_sort(true); DimensionRolap rolap=this.dimconMap.get(DimensionManage.getDimension(dimcell.getDim())); if(rolap.getLevel()==1) dimcell.setShow_shrink(false); if(rolap.getLevel()==rolap.getDim().getLevelNum()) dimcell.setShow_expand(false); } dimcelllist.add(dimcell); }else { //维相同 dimcell.setColspan(dimcell.getColspan()+cell.getColspan()); } } return dimcelllist.toArray(new CubeHeadCell[dimcelllist.size()]); } /** * 递归生成完整表头 * 表头类型:横向维 层头(dim_type=crosswise); * 纵向维 数据头(dim_type=vertical); * 纵向维 合计头(dim_type=vertical,cell_type=group,level=哪层分组合计); * 指标维 头(dim_type=measures)不会处理到 * 1.存在度量维头 返回 * 2.存在纵向维头,如果pid=null 返回 * 3.多个指标判断 * * 参数 level_index 第几层表头(不含维度层) level_index<=1退出 * 参数 headcells 当前表头行 * 返回 CubeHeadCell[] 上一级表头行 * @param headcells * @return */ private void recursionCreateHead(List<CubeHeadCell[]> headlist,CubeHeadCell[] headcells,int level_index,Dimension verticalDim){ if(level_index<=1){ //表头层计算结束,套上维度头层 headlist.add(this.createDimHead(headcells)); return; } //计算目标层 表头 List<CubeHeadCell> nextlist=new ArrayList<CubeHeadCell>(); //计算数据头表头取值map Map<String,QueryKeyValue> verticalnextmap=DimensionLevelValueManage.getDimLevelValueMap(verticalDim.getLevel(level_index-1)); CubeHeadCellImpl nextcell=null; Map<Object,String> vertmap=new HashMap<Object,String>(); Map<Integer,Map<Object,String>> vertgroupmap=new HashMap<Integer,Map<Object,String>>(); for(CubeHeadCell cell:headcells){ if(DimensionType.crosswise.equals(cell.getDim_type())){ //横向维 层头 nextcell=new CubeHeadCellImpl(cell); nextcell.setRowspan(nextcell.getRowspan()+1); cell.setRowspan(0); cell.setColspan(0); nextlist.add(nextcell); }else if(CellType.group.equals(cell.getCell_type())){ //纵向维 合计头 if(level_index==cell.getLevel()){ //当前分组合计 nextcell.setColspan(nextcell.getColspan()+cell.getColspan()); }else{ //非当前 行和列合并 if(!vertgroupmap.containsKey(cell.getLevel())){ vertgroupmap.put(cell.getLevel(), new HashMap<Object,String>()); } if(vertgroupmap.get(cell.getLevel()).containsKey(cell.getPid())){ //列合并 nextcell.setColspan(nextcell.getColspan()+cell.getColspan()); }else{ vertgroupmap.get(cell.getLevel()).put(cell.getPid(), null); nextcell=new CubeHeadCellImpl(cell); nextcell.setName("合计"); //行合并 nextcell.setRowspan(nextcell.getRowspan()+1); nextlist.add(nextcell); } cell.setRowspan(0); cell.setColspan(0); } }else{ //纵向维 数据头 if(vertmap.containsKey(cell.getPid())){ nextcell.setColspan(nextcell.getColspan()+cell.getColspan()); }else{ vertmap.put(cell.getPid(), null); nextcell=new CubeHeadCellImpl(cell); QueryKeyValue vo=verticalnextmap.get(cell.getPid().toString()); nextcell.setId(vo.getId()); nextcell.setName(vo.getName()); nextcell.setPid(vo.getPid()); nextlist.add(nextcell); } } } CubeHeadCell[] nextcells=nextlist.toArray(new CubeHeadCell[nextlist.size()]); recursionCreateHead(headlist,nextcells,level_index-1,verticalDim); headlist.add(nextcells); } /** * 组装多级报表头 * 列隐藏未处理和能否隐藏未处理 * @throws ReportException */ private List<CubeHeadCell[]> createOlapHead(CubeHeadCell[] headcells,List<DimensionRolap> dimrolaps,List<Measure> measures) throws ReportException { CubeHeadCell[] copyheadcells=new CubeHeadCell[headcells.length]; for(int i=0;i<headcells.length;i++){ copyheadcells[i]=new CubeHeadCellImpl(headcells[i]); } //判断层数 int index_max=0; List<CubeHeadCell[]> celllist=new ArrayList<CubeHeadCell[]>(); DimensionRolap vertrolap=null; for(DimensionRolap dimrolap : dimrolaps){ if(dimrolap.isUsesign()&&dimrolap.isVerticalsign()) vertrolap=dimrolap; } if(vertrolap!=null){ index_max=vertrolap.getLevel(); if(measures.size()>1) index_max++; this.recursionCreateHead(celllist, copyheadcells, index_max, vertrolap.getDim()); }else{ index_max=1; this.recursionCreateHead(celllist, copyheadcells, index_max, null); //return celllist; } celllist.add(copyheadcells); return celllist; } }