📄 resultbase.java
字号:
/*
* ====================================================================
* This software is subject to the terms of the Common Public License
* Agreement, available at the following URL:
* http://www.opensource.org/licenses/cpl.html .
* Copyright (C) 2003-2004 TONBELLER AG.
* All Rights Reserved.
* You must accept the terms of that agreement to use this software.
* ====================================================================
*
*
*/
package com.tonbeller.jpivot.olap.query;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import com.tonbeller.jpivot.core.Model;
import com.tonbeller.jpivot.olap.model.Axis;
import com.tonbeller.jpivot.olap.model.Cell;
import com.tonbeller.jpivot.olap.model.Member;
import com.tonbeller.jpivot.olap.model.Position;
import com.tonbeller.jpivot.olap.model.Result;
import com.tonbeller.jpivot.olap.model.Visitor;
import com.tonbeller.jpivot.util.CubeIndexIterator;
/**
* base class for both Mondrian and XMLA result
*/
public abstract class ResultBase implements Result {
private static String[] specialProps = { "arrow"};
protected List axesList;
protected List aCells;
protected Axis slicer;
protected Model model;
boolean overflow = false;
// c'tor
public ResultBase(Model model) {
aCells = new ArrayList();
axesList = new ArrayList();
this.model = model;
}
/**
* After the result was gotten, handle special measures, which are
* "invisible". Their meaning is a property for "another" cell, eg.
* [Measures].[Unit Sales_arrow] is the "arrow" property for
* [Measures].[Unit Sales]
*/
void processSpecialProps() {
}
/**
* @see com.tonbeller.jpivot.olap.model.Result#getAxes()
*/
public abstract Axis[] getAxes();
/**
* Returns the slicer.
*
* @return Slicer Axis
* @see com.tonbeller.jpivot.olap.model.Result#getSlicer()
*/
public Axis getSlicer() {
return slicer;
}
/**
* Returns the cells.
*
* @return List of cells
* @see com.tonbeller.jpivot.olap.model.Result#getCells()
*/
public List getCells() {
return aCells;
}
/**
* perform hierarchize not resorting siblings under parent
*
* this method is not fully tested we cannot use Result hierarchize, because
* by Quax navigation the prerequisits are not given Example (Customers
* Products): if by Quax navigation (CA, Drink) USA.children is split into
* {OR, WA) * Drink {CA} * { Drink + Drink.Children) CA would then come
* later in the result. Therefore : MDX hierarchize is needed
*/
public void hierarchize(int iAxis) {
List posList = ((Axis) axesList.get(iAxis)).getPositions();
int nDim = axesList.size();
int indexForAxis = nDim - 1 - iAxis;
int[] ni = new int[nDim];
int[] iFull = new int[nDim];
for (int i = 0; i < nDim; i++) {
ni[i] = ((Axis) axesList.get(i)).getPositions().size() - 1;
}
int[] iSlice = new int[nDim - 1];
CubeIndexIterator cubit = null;
if (nDim > 1) {
full2slice(ni, iSlice, iAxis);
cubit = new CubeIndexIterator(iSlice, false);
}
// assign the cells
// c00 c01 c02 ... c0n
// c10 c11 c12 ... c1n
// ...
// cm0 cm1 cm2 ... cmn
// cell ordinal of cell [i,k] = c[i*(n+1) +k]
// n+1 = position size of axis 0 (columns)
// m+1 = position size of axis 1 (rows)
// iAxis=0 position=0 : c00, c10, ... cm0
// iAxis=0 position=1 : c01, c11, ... cm1
// iAxis=1 position=0 : c00, c01, ... c0n
// iAxis=1 position=1 : c10, c11, ... c1n
// for each position of iAxis we will get the slice
// of cells for the "other" axes
int iPos = 0;
int nDimension = 0;
for (Iterator iter = posList.iterator(); iter.hasNext(); iPos++) {
PositionBase pos = (PositionBase) iter.next();
if (nDimension == 0)
nDimension = pos.getMembers().length;
pos.number = iPos;
if (pos.cellList == null)
pos.cellList = new ArrayList();
else
pos.cellList.clear();
if (nDim > 1) {
cubit.reset();
while (true) {
int[] iCurrent = cubit.next();
if (iCurrent == null)
break;
slice2full(iCurrent, iFull, indexForAxis, iPos);
int ii = lindex(iFull, ni);
pos.cellList.add(aCells.get(ii));
}
} else {
// nDim <= 1
pos.cellList.add(aCells.get(iPos));
}
}
// sort
posList = sortPosList(posList, 0, nDim);
// rewrite cell list
int nc = aCells.size();
aCells.clear();
for (int i = 0; i < nc; i++)
aCells.add(null);
iPos = 0;
for (Iterator iter = posList.iterator(); iter.hasNext(); iPos++) {
PositionBase posBase = (PositionBase) iter.next();
if (nDim > 1) {
cubit.reset();
for (Iterator iterator = posBase.cellList.iterator(); iterator.hasNext();) {
Object cellObj = iterator.next();
int[] iCurrent = cubit.next();
if (iCurrent == null)
break;
slice2full(iCurrent, iFull, indexForAxis, iPos);
int ii = lindex(iFull, ni);
aCells.set(ii, cellObj);
}
} else {
// nDim <= 1
Object cellObj = posBase.cellList.get(0);
aCells.set(iPos, cellObj);
}
posBase.cellList.clear();
}
}
/**
*
* @param posList
* @param iDim
* @param nDim
* @return
*/
private List sortPosList(List posList, final int iDim, int nDim) {
printPosList(posList, new PrintWriter(System.out), "Start sortPosList " + iDim);
if (posList.size() < 2)
return posList;
// collect members and assign first occurrence prio
final Map firstOcc = new HashMap();
int k = 0;
for (Iterator iter = posList.iterator(); iter.hasNext(); k++) {
PositionBase posb = (PositionBase) iter.next();
posb.parent = null;
Member m = posb.getMembers()[iDim];
if (!firstOcc.containsKey(m))
firstOcc.put(m, new Integer(k));
}
// first step
// sort by level and original position to assure
// that any child follows its parent
Collections.sort(posList, new Comparator() {
public int compare(Object o1, Object o2) {
// compare two positions
Position pos1 = (Position) o1;
Position pos2 = (Position) o2;
Member a1 = pos1.getMembers()[iDim];
Member a2 = pos2.getMembers()[iDim];
// if it is on different level, the descendant is higher
// otherwise - decide by original index
int level1 = ((MDXLevel) a1.getLevel()).getDepth();
int level2 = ((MDXLevel) a2.getLevel()).getDepth();
if (level1 == level2) {
return ((PositionBase) pos1).number - ((PositionBase) pos2).number;
} else {
return level1 - level2;
}
}
});
// second step
// establish parent child dependencies
int i = 0;
Outerloop: for (Iterator iter = posList.iterator(); iter.hasNext(); i++) {
PositionBase posb = (PositionBase) iter.next();
if (!iter.hasNext())
break;
MDXMember m = (MDXMember) posb.getMembers()[iDim];
int iLevel = ((MDXLevel) m.getLevel()).getDepth();
ListIterator lit = posList.listIterator(i + 1);
InnerLoop: while (lit.hasNext()) {
PositionBase posb2 = (PositionBase) lit.next();
if (posb2.parent != null)
continue;
MDXMember m2 = (MDXMember) posb2.getMembers()[iDim];
int iLevel2 = ((MDXLevel) m2.getLevel()).getDepth();
if (iLevel2 <= iLevel)
continue InnerLoop;
if (iLevel2 > iLevel + 1)
break InnerLoop;
// here iLevel2 = iLevel +1
if (m.getUniqueName().equals(m2.getParentUniqueName()))
posb2.parent = posb;
}
}
// third step
// sort by hierarchy and member first ocurrence
Collections.sort(posList, new Comparator() {
public int compare(Object o1, Object o2) {
// compare two positions
PositionBase pos1 = (PositionBase) o1;
PositionBase pos2 = (PositionBase) o2;
Member a1 = pos1.getMembers()[iDim];
Member a2 = pos2.getMembers()[iDim];
if (a1.equals(a2)) { return pos1.number - pos2.number; }
// if a1 and a2 are descendant, the descendant is higher
int level1 = ((MDXLevel) a1.getLevel()).getDepth();
int level2 = ((MDXLevel) a2.getLevel()).getDepth();
PositionBase par1 = null;
PositionBase par2 = null;
PositionBase parb = null;
if (level1 < level2) {
// a2 is possibly descendant of a1
parb = pos2;
for (int j = 0; j < level2 - level1; j++) {
if (parb != null)
parb = parb.parent;
}
if (parb != null) {
Member ab = parb.getMembers()[iDim];
if (ab.equals(a1))
return -1; // a2 is descendant of a1, a2 is higher
}
par1 = pos1;
par2 = parb;
} else if (level1 > level2) {
// a1 is possibly descendant of a2
parb = pos1;
for (int j = 0; j < level1 - level2; j++) {
if (parb != null)
parb = parb.parent;
}
if (parb != null) {
Member ab = parb.getMembers()[iDim];
if (ab.equals(a2))
return 1; // a1 is descendant of a2, a1 is higher
}
par1 = parb;
par2 = pos2;
} else {
// level1 = level2
par1 = pos1;
par2 = pos2;
}
// pos1 and pos2 are on equal level
if (par1 == null || par2 == null)
return pos1.number - pos2.number; // should not occur
// go up until we come to a common ancestor or null
Member apar1 = par1.getMembers()[iDim];
Member apar2 = par2.getMembers()[iDim];
PositionBase p1 = par1.parent;
PositionBase p2 = par2.parent;
while (p1 != null && p2 != null) {
Member ap1 = p1.getMembers()[iDim];
Member ap2 = p2.getMembers()[iDim];
if (ap1.equals(ap2))
break;
par1 = p1;
par2 = p2;
p1 = par1.parent;
p2 = par2.parent;
if (p1 == null || p2 == null)
break;
apar1 = ap1;
apar2 = ap2;
}
int retcode = ((Integer) firstOcc.get(apar1)).intValue()
- ((Integer) firstOcc.get(apar2)).intValue();
return retcode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -