上一节,我们总结了动态生成mdx语句,下面,我们重点总结如何生成前端模型。
前端模型(viewGrid/formGrid),我们为前端模型起个名字--表格模型---大致可以理解为描述一个表格,每个数据区单元格,都有一个行、列坐标。
需要注意的是:前端模型(viewGrid/formGrid)是动态的,前端页面收缩、展开节点(对应olap上卷、下钻),其相关属性也会变化。
构建前端模型(viewGrid/formGrid),就是如何从mdx查询结果,生成这个一个前端模型的问题。
/**
* 前端模型
*/
public class viewGrid {
private int axisCount;
private int formId; //对应的分析表单id
//行维度
private int[] rowDims=null;
//列维度
private int[] colDims=null;
// 行列维度成员,这个是根据显示的情况,动态改变的,只有显示在页面上的元素,才在这个数组中存在
private int[][] rowMembers = null; //页面上显示的行维度成员数组,这貌似是最重要的属性了
private int[][] colMembers = null; //页面上显示的行维度成员数组,这貌似是最重要的属性了
// 页面
private int[] pageLayout = null;
// 视点
private int[] vpLayout = null;
// 事实数据
private DataCell[][] factDatas = null;
//form模型,供生成MDX字符串使用
private CommForm formShadow = null;
/*
* rowGroup表示列布局上的分组信息
* 列:
* rowCrgoup={0, 15, 19}表示第一组坐标0~14 ,第二组坐标15~18 ,第三组坐标19~rowGroup.lenght
*/
private int[] rowGroupInfo = null;
private int[] colGroupInfo = null;
//单元格维度位置
private int[] cellDims=null;
...
}
首先我们要理解执行mdx的结果result,它包括如下一些概念:
行、列坐标,由a tuple(元组)形成。
axis & Position:
前面我们提到:a cell is found by specifying a tuple of positions along every axis
cellSet
● Cellset is the set which contains the cell returned by the MDX query.
● Cellset is the set where results are founded.
– Important API methods: getCell, getFilterAxis, getMetadata..
Cell
● Cell is the structure which contains a part of the cellset. Every cell, contains a part of the result we are searching with a MDX query.
● It could be said that cells are as rows in RDBs or documents in a document-oriented DB. This is just a very simple approach, a really simple analogy.
– Important API methods: drillThrough, getValue, isEmpty, isNull,...
CellSetAxis:
CellSetAxis is the axis of a cellset (OK?!!)
● A cell set has the same number of axes as the MDX statement which was executed to produce it.
单元格集具有与生成它的MDX语句相同的轴数。
● Each axis is an ordered collection of members or tuples.
● Each member or tuple on an axis is called Position.
– Important API methods: getPositions, getAxisMetada...
ps:tuples:元组
Position:
●Position is one of the CellSetAxis objects in a CellSet.
● An axis has a particular dimensionality, that is, a set of one or more dimensions which will appear on than axis, and every position on that axis will have a member of each of those dimensions. (Extracted from official API)
– Important API methods: getMembers, getOrdinal...
tuple:
A tuple is a combination of members from one or more dimensions. It is essentially a multidimensional member
tuple本身是个成员,可以是个多维度成员。
tuple用“()”标记。
A tuple can stand for a slice of a cube, where the cube is sliced by each member in the tuple.
理解以上概念,就容易理解如下代码,根据mdx查询结果,构建前端模型:
/**
* @param result
* @param form
* @param o (o instanceOf BgForm表示通过formId创建grid
* o instanceOf FormGrid表示通过grid创建新的grid,即分析表页面切换
* o == null 表示局部下钻调用此方法,不需要对返回的FormGrid行列布局信息做调整)
* @return
*/
private FormGrid buildFormGridByResult(Result result, FormShadow formShadow, int[] pageLayoutOId, Object o) {
StringBuffer rowDimsBuffer=new StringBuffer();
StringBuffer colDimsBuffer=new StringBuffer();
StringBuffer viewDimsBuffer=new StringBuffer(); //存放的是视点维度成员的id字符串,用逗号分隔
FormGrid formGrid = null;
try{
int[] vpLayout = buildViewInfo(formShadow,viewDimsBuffer); //存放的是视点维度成员的id
int[] pageLayout = pageLayoutOId;
if(pageLayoutOId==null){ //如果页面没有选择,则取得第一个元素
pageLayout = buildPageInfo(formShadow);
}
int[][] rowMembers = buildRowsInfo(result, formShadow,rowDimsBuffer);
int[][] colMembers = buildColsInfo(result, formShadow,colDimsBuffer);
DataCell[][] factDatas = buildFactDatas(result, formShadow);
int cubeId = formShadow.getCubeId();
int formId = formShadow.getId();
formGrid = new FormGrid(cubeId, formId, rowMembers, colMembers,
pageLayout, vpLayout, factDatas, formShadow);
formGrid.setAxisCount(result.getAxes().length);
/*
* 这里确定DataCell位置的维度成员id,DataCell 中有 private int[] members = null;....
* 根据这个members *数组,可以定位到一个单元格cell的数据,就是说通过这里的设置,单元格数据和全部相关维度成员建立**了关联关系,他们之间能相互感知
*/
......
/*
* 设置formGrid中关于行、列布局上组的信息
*/
if (o instanceof CommForm) {
/**
*
*通过formId创建grid 的相关处理
*
**/
} else if (o instanceof FormGrid) {
/**
*通过grid创建新的grid,即分析表页面切换 的相关处理
**/
}
}catch (Exception e) {
......
}
return formGrid;
}
建立前端表格模型之行维的完整信息:
/**
* 建立行维的完整信息
* @param result
* @param rowDimsBuffer
* @param form
* @return
*/
private int[][] buildRowsInfo(Result result, FormShadow formShadow, StringBuffer rowDimsBuffer) {
int[][] rowsInfo = null;
try{
Axis colAxis = result.getAxes()[1];
int rowNum = colAxis.getPositions().size();
int colNum = colAxis.getPositions().get(0).size();
rowsInfo = new int[rowNum][colNum];
for (int i = 0; i < rowNum; i++) {
for (int j = 0; j < colNum; j++) {
Member member = colAxis.getPositions().get(i).get(j);
//将mondrian.olap.Member转换成自定义的DimMember
DimMember dimMember = memberConversion(member,formShadow); /
rowsInfo[i][j] = dimMember.getMemberId();
if(i==0 && rowDimsBuffer!=null){
if(j!=colNum-1){
rowDimsBuffer.append(dimMember.getDimension().getId()+",");
}else{
rowDimsBuffer.append(dimMember.getDimension().getId()+"");
}
}
}
}
}catch (Exception e) {
......
}
return rowsInfo;
}
举个例子:
上面代码中:int rowNum = colAxis.getPositions().size(); 行数是78,
int colNum = colAxis.getPositions().get(0).size(); colNum是2;
再举个例子:
上面代码中:int rowNum = colAxis.getPositions().size(); 行数是3,
int colNum = colAxis.getPositions().get(0).size(); colNum是2;
buildRowsInfo方法,就是形成左边行维的完整信息,且把信息存放到int[][]当中。
这里举个执行结果的例子:(每个数字就是一个维度成员id)
[[63176, 67813], [63176, 67826], [63176, 68027], [63177, 67813], [63177, 67826], [63177, 68027], [63178, 67813], [63178, 67826], [63178, 68027], [63179, 67813], [63179, 67826], [63179, 68027], [63180, 67813], [63180, 67826], [63180, 68027], [63181, 67813], [63181, 67826], [63181, 68027], [63182, 67813], [63182, 67826], [63182, 68027], [63183, 68027], [63183, 68028], [63184, 68027], [63184, 68028], [63185, 68027], [63185, 68028], [63186, 68027], [63186, 68028], [63187, 67809], [63190, 67824], [63190, 67825], [63191, 67824], [63191, 67825], [63192, 67824], [63192, 67825], [63193, 67824], [63193, 67825], [63194, 67824], [63194, 67825], [63195, 67824], [63195, 67825], [63196, 67824], [63196, 67825], [63197, 67824], [63197, 67825], [63198, 67824], [63198, 67825], [63199, 67824], [63199, 67825], [63202, 67813], [63202, 67814], [63202, 67819], [63202, 67820], [63202, 67823], [63202, 67826], [63202, 67827], [63203, 67813], [63203, 67814], [63203, 67819], [63203, 67820], [63203, 67823], [63203, 67826], [63203, 67827], [63204, 67813], [63204, 67814], [63204, 67819], [63204, 67820], [63204, 67823], [63204, 67826], [63204, 67827], [63205, 67813], [63205, 67814], [63205, 67819], [63205, 67820], [63205, 67823], [63205, 67826], [63205, 67827]]
除了获取行维度成员的全部明细信息,获取维度信息也是这个函数的作用,结果存放在rowDimsBuffer,其形式如:110,112。
获取列轴上的详细信息:
基本步骤为:遍历每个position---->遍历每个position上的meber(every position on that axis will have a member of each of those dimensions.);取得相关维度放入二维数组,值得注意的是,数组是按【列】【行】形式出差列维详细信息的,具体代码和行维详细信息类似,这里就不展开了。
获取事实数据:
事实数据model:
/**
* 数据单元格
*
*/
public class DataCell {
private int formId;
private int cubeId;
private Object[] factValues = null;
private boolean[] exist = null;
//确定DataCell位置的维度成员id
private int[] members = null;
......
}
a cell is found by specifying a tuple of positions along every axis
/**
*建立事实数据部分
* @param result
* @param form
* @return
*/
private DataCell[][] buildFactDatas(Result result, IcpForm form) {
int rowCount = result.getAxes()[1].getPositions().size();
int colCount = result.getAxes()[0].getPositions().size();
DataCell[][] dataCells = new DataCell[rowCount][colCount / 2];
try{
Cell cell = null;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < colCount; j = j) {
/*
* 在mondrian中,一个结果集的事实数据表格【列】【行】形式
*/
cell_1 = result.getCell(new int[] { j, i });
dataCells[i][j] = cellConversion(new Cell[] { cell}, form);
}
}
}catch (Exception e) {
......
}
return dataCells;
}
DataCell:
datacell中有个重要属性,就是 private int[] members = null; 存放的个一一个cell管理的所有维度成员id,在获取行、列、数据区详细信息后,遍历factDatas,设置members属性,我们通过这个方式,建立cell与相关维度成员间的相互感知。
前端模型viewGrid(FormGrid)其他辅助属性:
private int[] rowGroupInfo = null; private int[] colGroupInfo = null;
(示意图)
这里行信息是:{0, 2},有2个组,就有2个数组元素,3个组就有3个数组元素,以此类推。
0表示第一个组的起始位置,2表示第2组的起始位置,以此类推。
再举个例子 [0, 1, 2, 3, 4, 17],这表示有6个组,数组元素的值就是每组开始位置。
1)rowGroupInfo、colGroupInfo 都是根据后端模型生成的。
2)private int[] rowDims=null; //行维度
3)private int[] colDims=null;//列维度
4)private int[] cellDims=null;//单元格维度位置,每个单元格都有维度成员信息,顺序和这个是一样的?
这些属性,都是为在web层展示做准备。