/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// You must accept the terms of that agreement to use this software.
//
// Copyright (C) 2002-2005 Julian Hyde
// Copyright (C) 2005-2011 Pentaho and others
// All Rights Reserved.
//
// jhyde, 3 March, 2002
*/
package mondrian.util;
import mondrian.calc.TupleList;
import mondrian.calc.impl.ArrayTupleList;
import mondrian.olap.*;
import mondrian.olap.fun.FunUtil;
import mondrian.resource.MondrianResource;
import mondrian.rolap.RolapCube;
import java.util.*;
/**
* Utilities for parsing fully-qualified member names, tuples, member lists,
* and tuple lists.
*
* @author jhyde
*/
public class IdentifierParser extends org.olap4j.impl.IdentifierParser {
/**
* Implementation of Builder that resolves segment lists to members.
*/
public static class BuilderImpl extends MemberBuilder {
private final SchemaReader schemaReader;
private final Cube cube;
protected final List<Hierarchy> hierarchyList;
private final boolean ignoreInvalid;
BuilderImpl(
SchemaReader schemaReader,
Cube cube,
List<Hierarchy> hierarchyList)
{
this.schemaReader = schemaReader;
this.cube = cube;
this.hierarchyList = hierarchyList;
final MondrianProperties props = MondrianProperties.instance();
final boolean load = ((RolapCube) cube).isLoadInProgress();
this.ignoreInvalid =
(load
? props.IgnoreInvalidMembers.get()
: props.IgnoreInvalidMembersDuringQuery.get());
}
protected Member resolveMember(Hierarchy expectedHierarchy) {
final List<Id.Segment> mondrianSegmentList =
Util.convert(this.segmentList);
Member member =
(Member) Util.lookupCompound(
schemaReader, cube, mondrianSegmentList, !ignoreInvalid,
Category.Member);
if (member == null) {
assert ignoreInvalid;
if (expectedHierarchy != null) {
return expectedHierarchy.getNullMember();
} else {
// Guess the intended hierarchy from the largest valid
// prefix.
for (int i = mondrianSegmentList.size() - 1; i > 0; --i) {
List<Id.Segment> partialName =
mondrianSegmentList.subList(0, i);
OlapElement olapElement =
schemaReader.lookupCompound(
cube, partialName, false, Category.Unknown);
if (olapElement != null) {
return olapElement.getHierarchy().getNullMember();
}
}
throw MondrianResource.instance().MdxChildObjectNotFound.ex(
Util.implode(mondrianSegmentList),
cube.getQualifiedName());
}
}
if (expectedHierarchy != null
&& member.getHierarchy() != expectedHierarchy)
{
// TODO: better error
throw Util.newInternal("member is of wrong hierarchy");
}
return member;
}
}
/**
* Implementation of Builder that builds a tuple.
*/
public static class TupleBuilder extends BuilderImpl {
protected final List<Member> memberList = new ArrayList<Member>();
public TupleBuilder(
SchemaReader schemaReader,
Cube cube,
List<Hierarchy> hierarchyList)
{
super(schemaReader, cube, hierarchyList);
}
public void memberComplete() {
super.memberComplete();
if (memberList.size() >= hierarchyList.size()) {
throw Util.newInternal("expected ')");
}
final Hierarchy hierarchy = hierarchyList.get(memberList.size());
final Member member = resolveMember(hierarchy);
memberList.add(member);
segmentList.clear();
}
public void tupleComplete() {
if (memberList.size() < hierarchyList.size()) {
throw Util.newInternal("too few members");
}
}
}
/**
* Implementation of Builder that builds a tuple list.
*/
public static class TupleListBuilder extends TupleBuilder {
public final TupleList tupleList;
public TupleListBuilder(
SchemaReader schemaReader, Cube cube, List<Hierarchy> hierarchyList)
{
super(schemaReader, cube, hierarchyList);
tupleList = new ArrayTupleList(hierarchyList.size());
}
public void tupleComplete() {
super.tupleComplete();
if (!FunUtil.tupleContainsNullMember(memberList)) {
tupleList.add(memberList);
}
this.memberList.clear();
}
}
/**
* Implementation of Builder that builds a member list.
*/
public static class MemberListBuilder extends BuilderImpl {
public final List<Member> memberList = new ArrayList<Member>();
public MemberListBuilder(
SchemaReader schemaReader, Cube cube, Hierarchy hierarchy)
{
super(schemaReader, cube, Collections.singletonList(hierarchy));
}
public void memberComplete() {
final Member member = resolveMember(hierarchyList.get(0));
if (!member.isNull()) {
memberList.add(member);
}
segmentList.clear();
}
@Override
public void tupleComplete() {
// nothing to do
}
}
}
// End IdentifierParser.java