formula.java
来自「数据仓库展示程序」· Java 代码 · 共 349 行
JAVA
349 行
/*
// $Id: //open/mondrian/src/main/mondrian/olap/Formula.java#23 $
// 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.
// (C) Copyright 2000-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 1 March, 2000
*/
package mondrian.olap;
import mondrian.olap.type.*;
import mondrian.resource.MondrianResource;
import java.io.PrintWriter;
/**
* A <code>Formula</code> is a clause in an MDX query which defines a Set or a
* Member.
**/
public class Formula extends QueryPart {
/** name of set or member **/
private final String[] names;
/** defining expression **/
private ExpBase exp;
// properties/solve order of member
private final MemberProperty[] memberProperties;
/**
* <code>true</code> is this is a member, <code>false</code> if it is a
* set.
*/
private final boolean isMember;
private Member mdxMember;
private NamedSet mdxSet;
/**
* Constructs formula specifying a set.
*/
public Formula(String[] names, Exp exp) {
this(false, names, (ExpBase) exp, new MemberProperty[0], null, null);
createElement(null);
}
/**
* Constructs a formula specifying a member.
*/
public Formula(
String[] names, Exp exp, MemberProperty[] memberProperties) {
this(true, names, (ExpBase) exp, memberProperties, null, null);
}
private Formula(
boolean isMember,
String[] names,
ExpBase exp,
MemberProperty[] memberProperties,
Member mdxMember,
NamedSet mdxSet) {
this.isMember = isMember;
this.names = names;
this.exp = exp;
this.memberProperties = memberProperties;
this.mdxMember = mdxMember;
this.mdxSet = mdxSet;
assert !(!isMember && mdxMember != null);
assert !(isMember && mdxSet != null);
}
public Object clone()
{
return new Formula(
isMember,
names,
(ExpBase) exp.clone(),
MemberProperty.cloneArray(memberProperties),
mdxMember,
mdxSet);
}
static Formula[] cloneArray(Formula[] x) {
Formula[] x2 = new Formula[x.length];
for (int i = 0; i < x.length; i++) {
x2[i] = (Formula) x[i].clone();
}
return x2;
}
/**
* Resolves identifiers into objects.
*
* @param validator Validation context to resolve the identifiers in this
* formula
*/
void accept(Validator validator) {
final boolean scalar = isMember;
exp = (ExpBase) validator.validate(exp, scalar);
String id = Util.quoteMdxIdentifier(names);
final Type type = exp.getTypeX();
if (isMember) {
if (!TypeUtil.canEvaluate(type)) {
throw MondrianResource.instance().MdxMemberExpIsSet.ex(id);
}
} else {
if (!TypeUtil.isSet(type)) {
throw MondrianResource.instance().MdxSetExpNotSet.ex(id);
}
}
for (int i = 0; i < memberProperties.length; i++) {
validator.validate(memberProperties[i]);
}
// Get the format expression from the property list, or derive it from
// the formula.
if (isMember) {
Exp formatExp = getFormatExp();
if (formatExp != null) {
mdxMember.setProperty(Property.FORMAT_EXP.name, formatExp);
}
}
}
/**
* Creates the {@link Member} or {@link NamedSet} object which this formula
* defines.
*/
void createElement(Query q) {
// first resolve the name, bit by bit
if (isMember) {
if (mdxMember != null) {
return;
}
OlapElement mdxElement = q.getCube();
final SchemaReader schemaReader = q.getSchemaReader(true);
for (int i = 0; i < names.length; i++) {
OlapElement parent = mdxElement;
mdxElement = schemaReader.getElementChild(parent, names[i]);
// Don't try to look up the member which the formula is
// defining. We would only find one if the member is overriding
// a member at the cube or schema level, and we don't want to
// change that member's properties.
if (mdxElement == null || i == names.length - 1) {
// this part of the name was not found... define it
Level level;
Member parentMember = null;
if (parent instanceof Member) {
parentMember = (Member) parent;
level = parentMember.getLevel().getChildLevel();
} else {
Hierarchy hierarchy = parent.getHierarchy();
if (hierarchy == null) {
throw MondrianResource.instance().MdxCalculatedHierarchyError.ex(
Util.quoteMdxIdentifier(names));
}
level = hierarchy.getLevels()[0];
}
Member mdxMember = level.getHierarchy().createMember(
parentMember, level, names[i], this);
mdxElement = mdxMember;
}
}
this.mdxMember = (Member) mdxElement;
} else {
// don't need to tell query... it's already in query.formula
Util.assertTrue(
names.length == 1, "set names must not be compound");
mdxSet = new SetBase(names[0], exp);
}
}
public Object[] getChildren() {
Object[] children = new Object[1 + memberProperties.length];
children[0] = exp;
System.arraycopy(memberProperties, 0,
children, 1, memberProperties.length);
return children;
}
public void replaceChild(int ordinal, QueryPart with)
{
Util.assertTrue(ordinal == 0);
exp = (ExpBase) with;
}
public void unparse(PrintWriter pw)
{
if (isMember) {
pw.print("member ");
mdxMember.unparse(pw);
} else {
pw.print("set ");
pw.print(Util.quoteMdxIdentifier(names));
}
pw.print(" as '");
exp.unparse(pw);
pw.print("'");
if (memberProperties != null) {
for (int i = 0; i < memberProperties.length; i++) {
pw.print(", ");
memberProperties[i].unparse(pw);
}
}
}
public boolean isMember() {
return isMember;
}
public NamedSet getNamedSet() {
return mdxSet;
}
String[] getNames() {
return names;
}
/** Returns this formula's name. */
public String getName() {
return (isMember)
? mdxMember.getName()
: mdxSet.getName();
}
/** Returns this formula's caption. */
public String getCaption() {
return (isMember)
? mdxMember.getCaption()
: mdxSet.getName();
}
/**
* Changes the last part of the name to <code>newName</code>. For example,
* <code>[Abc].[Def].[Ghi]</code> becomes <code>[Abc].[Def].[Xyz]</code>;
* and the member or set is renamed from <code>Ghi</code> to
* <code>Xyz</code>.
**/
void rename(String newName)
{
String oldName = getElement().getName();
Util.assertTrue(
this.names[this.names.length - 1].equalsIgnoreCase(oldName));
this.names[this.names.length - 1] = newName;
if (isMember) {
mdxMember.setName(newName);
} else {
mdxSet.setName(newName);
}
}
/** Returns the unique name of the member or set. */
String getUniqueName() {
return (isMember)
? mdxMember.getUniqueName()
: mdxSet.getUniqueName();
}
OlapElement getElement() {
return (isMember)
? (OlapElement) mdxMember
: (OlapElement) mdxSet;
}
public Exp getExpression() {
return exp;
}
private Exp getMemberProperty(String name) {
return MemberProperty.get(memberProperties, name);
}
/**
* Returns the Member. (Not valid if this formula defines a set.)
*
* @pre isMember()
* @post return != null
*/
public Member getMdxMember() {
return mdxMember;
}
/**
* Returns the solve order. (Not valid if this formula defines a set.)
*
* @pre isMember()
* @post return != null
*/
public int getSolveOrder() {
Exp exp = getMemberProperty(Property.SOLVE_ORDER.name);
if (exp != null) {
final Type type = exp.getTypeX();
if (type instanceof NumericType) {
return ((Literal) exp).getIntValue();
}
}
return 0;
}
/**
* Deduces a formatting expression for this calculated member. First it
* looks for properties called "format", "format_string", etc. Then it looks
* inside the expression, and returns the formatting expression for the
* first member it finds.
*/
private Exp getFormatExp() {
// If they have specified a format string (which they can do under
// several names) reutrn that.
for (int i = 0; i < Property.FORMAT_PROPERTIES.length; i++) {
Exp formatExp = getMemberProperty(Property.FORMAT_PROPERTIES[i]);
if (formatExp != null) {
return formatExp;
}
}
// Choose a format appropriate to the expression.
// For now, only do it for integers.
final Type type = exp.getTypeX();
if (type instanceof DecimalType) {
int scale = ((DecimalType) type).getScale();
String formatString = "#,##0";
if (scale > 0) {
formatString = formatString + ".";
while (scale-- > 0) {
formatString = formatString + "0";
}
}
return Literal.createString(formatString);
}
// Burrow into the expression. If we find a member, use its format
// string.
// TODO: Obsolete this code.
Walker walker = new Walker(exp);
while (walker.hasMoreElements()) {
final Object o = walker.nextElement();
if (o instanceof Member) {
Exp formatExp = (Exp) ((Member) o).getPropertyValue(
Property.FORMAT_EXP.name);
if (formatExp != null) {
return formatExp;
}
}
}
return null;
}
}
// End Formula.java
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?