funutil.java
来自「数据仓库展示程序」· Java 代码 · 共 1,808 行 · 第 1/5 页
JAVA
1,808 行
*/
return member.getHierarchy().getNullMember();
}
Member[] ancestors = member.getAncestorMembers();
final SchemaReader schemaReader = evaluator.getSchemaReader();
Member result = member.getHierarchy().getNullMember();
searchLoop:
for (int i = 0; i < ancestors.length; i++) {
final Member ancestorMember = ancestors[i];
if (targetLevel != null) {
if (ancestorMember.getLevel() == targetLevel) {
if (schemaReader.isVisible(ancestorMember)) {
result = ancestorMember;
break searchLoop;
} else {
result = member.getHierarchy().getNullMember();
break searchLoop;
}
}
} else {
if (schemaReader.isVisible(ancestorMember)) {
distance--;
//
// Make sure that this ancestor is really on the right
// targetLevel. If a targetLevel was specified and at least
// one of the ancestors was hidden, this this algorithm goes
// too far up the ancestor list. It's not a problem, except
// that we need to check if it's happened and return the
// hierarchy's null member instead.
//
// For example, consider what happens with
// Ancestor([Store].[Israel].[Haifa], [Store].[Store State]).
// The distance from [Haifa] to [Store State] is 1, but that
// lands us at the country targetLevel, which is clearly
// wrong.
//
if (distance == 0) {
if (targetLevel == null || ancestorMember.getLevel() == targetLevel) {
result = ancestorMember;
break searchLoop;
} else {
result = member.getHierarchy().getNullMember();
break searchLoop;
}
}
}
}
}
return result;
}
/**
* Compares a pair of members according to their positions in a
* prefix-order (or postfix-order, if <code>post</code> is true) walk
* over a hierarchy.
*
* @param m1 First member
* @param m2 Second member
* @param post Whether to sort in postfix order. If true, a parent will
* sort immediately after its last child. If false, a parent will sort
* immediately before its first child.
* @return -1 if m1 collates before m2,
* 0 if m1 equals m2,
* 1 if m1 collates after m2
*/
public static int compareHierarchically(Member m1,
Member m2,
boolean post) {
if (equals(m1, m2)) {
return 0;
}
while (true) {
int depth1 = m1.getDepth();
int depth2 = m2.getDepth();
if (depth1 < depth2) {
m2 = m2.getParentMember();
if (equals(m1, m2)) {
return post ? 1 : -1;
}
} else if (depth1 > depth2) {
m1 = m1.getParentMember();
if (equals(m1, m2)) {
return post ? -1 : 1;
}
} else {
Member prev1 = m1;
Member prev2 = m2;
m1 = m1.getParentMember();
m2 = m2.getParentMember();
if (equals(m1, m2)) {
return compareSiblingMembers(prev1, prev2);
}
}
}
}
/**
* Compares two members which are known to have the same parent.
*
* First, compare by ordinal.
* This is only valid now we know they're siblings, because
* ordinals are only unique within a parent.
* If the dimension does not use ordinals, both ordinals
* will be -1.
*
* <p>If the ordinals do not differ, compare using regular member
* comparison.
*
* @param m1 First member
* @param m2 Second member
* @return -1 if m1 collates less than m2,
* 1 if m1 collates after m2,
* 0 if m1 == m2.
*/
static int compareSiblingMembers(Member m1, Member m2) {
final int ordinal1 = m1.getOrdinal();
final int ordinal2 = m2.getOrdinal();
return (ordinal1 == ordinal2)
? m1.compareTo(m2)
: (ordinal1 < ordinal2)
? -1
: 1;
/*
if (ordinal1 == ordinal2) {
;
} else if (ordinal1 < ordinal2) {
return -1;
} else if (ordinal1 > ordinal2) {
return 1;
}
return m1.compareTo(m2);
*/
}
/**
* Helper function for {@link mondrian.olap.FunDef#callDependsOn(mondrian.olap.FunCall,
* mondrian.olap.Dimension)} for calls which have a set as the first
* argument and an expression as the second. The call depends upon
* everything <Value Expression> depends upon, except the dimensions of
* <Set>.
*
* @param call Function call
* @param dimension Dimension
* @return Whether call is dependent upon dimension
*/
public static boolean callDependsOnSet(FunCall call, Dimension dimension) {
final Exp[] args = call.getArgs();
if (args[0].dependsOn(dimension)) {
return true;
}
if (args[0].getTypeX().usesDimension(dimension)) {
return false;
}
// If there is no value expression, the value expression is implicit,
// and depends upon all dimensions.
if (args.length == 1) {
return true;
}
for (int i = 1; i < args.length; i++) {
Exp exp = args[i];
if (exp.dependsOn(dimension)) {
return true;
}
}
return false;
}
/**
* Converts an argument to a parameter type.
*/
public static Exp convert(Exp fromExp, int to, Validator validator) {
Exp exp = convert_(fromExp, to, validator);
if (exp == null) {
throw newInternal("cannot convert " + fromExp + " to " + to);
}
return validator.validate(exp, false);
}
private static Exp convert_(Exp fromExp, int to, Validator validator) {
int from = fromExp.getCategory();
if (from == to) {
return fromExp;
}
switch (from) {
case Category.Array:
return null;
case Category.Dimension:
// Seems funny that you can 'downcast' from a dimension, doesn't
// it? But we add an implicit 'CurrentMember', for example,
// '[Time].PrevMember' actually means
// '[Time].CurrentMember.PrevMember'.
switch (to) {
case Category.Hierarchy:
// "<Dimension>.CurrentMember.Hierarchy"
return new FunCall(
"Hierarchy", Syntax.Property, new Exp[]{
new FunCall(
"CurrentMember",
Syntax.Property, new Exp[]{fromExp}
)}
);
case Category.Level:
// "<Dimension>.CurrentMember.Level"
return new FunCall(
"Level", Syntax.Property, new Exp[]{
new FunCall(
"CurrentMember",
Syntax.Property, new Exp[]{fromExp}
)}
);
case Category.Member:
case Category.Tuple:
// "<Dimension>.CurrentMember"
return new FunCall(
"CurrentMember",
Syntax.Property,
new Exp[]{fromExp});
default:
return null;
}
case Category.Hierarchy:
switch (to) {
case Category.Dimension:
// "<Hierarchy>.Dimension"
return new FunCall(
"Dimension",
Syntax.Property,
new Exp[]{fromExp});
default:
return null;
}
case Category.Level:
switch (to) {
case Category.Dimension:
// "<Level>.Dimension"
return new FunCall(
"Dimension",
Syntax.Property,
new Exp[] {fromExp});
case Category.Hierarchy:
// "<Level>.Hierarchy"
return new FunCall(
"Hierarchy",
Syntax.Property,
new Exp[] {fromExp});
default:
return null;
}
case Category.Logical:
return null;
case Category.Member:
switch (to) {
case Category.Dimension:
// "<Member>.Dimension"
return new FunCall(
"Dimension",
Syntax.Property,
new Exp[] {fromExp});
case Category.Hierarchy:
// "<Member>.Hierarchy"
return new FunCall(
"Hierarchy",
Syntax.Property,
new Exp[]{fromExp});
case Category.Level:
// "<Member>.Level"
return new FunCall(
"Level",
Syntax.Property,
new Exp[]{fromExp});
case Category.Tuple:
// Conversion to tuple is trivial: a member is a
// one-dimensional tuple already.
return fromExp;
case Category.Numeric | Category.Constant:
case Category.String | Category.Constant: //todo: assert is a string member
// "<Member>.Value"
return new FunCall(
"Value",
Syntax.Property,
new Exp[]{fromExp});
case Category.Value:
case Category.Numeric:
case Category.String:
return validator.getFunTable().createValueFunCall(fromExp, validator);
default:
return null;
}
case Category.Numeric | Category.Constant:
case Category.Integer | Category.Constant:
switch (to) {
case Category.Value:
case Category.Integer:
case Category.Numeric:
return fromExp;
default:
return null;
}
case Category.Integer:
switch (to) {
case Category.Value:
case Category.Numeric:
return fromExp;
case Category.Numeric | Category.Constant:
case Category.Integer | Category.Constant:
return validator.getFunTable().createValueFunCall(fromExp, validator);
default:
return null;
}
case Category.Numeric:
switch (to) {
case Category.Value:
case Category.Integer:
return fromExp;
case Category.Numeric | Category.Constant:
case Category.Integer | Category.Constant:
return validator.getFunTable().createValueFunCall(fromExp, validator);
default:
return null;
}
case Category.Set:
return null;
case Category.String | Category.Constant:
switch (to) {
case Category.Value:
case Category.String:
return fromExp;
default:
return null;
}
case Category.String:
switch (to) {
case Category.Value:
return fromExp;
case Category.String | Category.Constant:
return validator.getFunTable().createValueFunCall(fromExp, validator);
default:
return null;
}
case Category.Tuple:
switch (to) {
case Category.Value:
// return fromExp;
case Category.Numeric:
case Category.String:
return validator.getFunTable().createValueFunCall(fromExp, validator);
default:
return null;
}
case Category.Value:
return null;
case Category.Symbol:
return null
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?