Search in sources :

Example 1 with KeySegment

use of org.olap4j.mdx.KeySegment in project mondrian by pentaho.

the class Util method lookupCompound.

/**
 * Resolves a name such as
 * '[Products].[Product Department].[Produce]' by resolving the
 * components ('Products', and so forth) one at a time.
 *
 * @param schemaReader Schema reader, supplies access-control context
 * @param parent Parent element to search in
 * @param names Exploded compound name, such as {"Products",
 *   "Product Department", "Produce"}
 * @param failIfNotFound If the element is not found, determines whether
 *   to return null or throw an error
 * @param category Type of returned element, a {@link Category} value;
 *   {@link Category#Unknown} if it doesn't matter.
 *
 * @pre parent != null
 * @post !(failIfNotFound && return == null)
 *
 * @see #parseIdentifier(String)
 */
public static OlapElement lookupCompound(SchemaReader schemaReader, OlapElement parent, List<Id.Segment> names, boolean failIfNotFound, int category, MatchType matchType) {
    Util.assertPrecondition(parent != null, "parent != null");
    if (LOGGER.isDebugEnabled()) {
        StringBuilder buf = new StringBuilder(64);
        buf.append("Util.lookupCompound: ");
        buf.append("parent.name=");
        buf.append(parent.getName());
        buf.append(", category=");
        buf.append(Category.instance.getName(category));
        buf.append(", names=");
        quoteMdxIdentifier(names, buf);
        LOGGER.debug(buf.toString());
    }
    // (cubes and queries both have them).
    switch(category) {
        case Category.Member:
        case Category.Unknown:
            Member member = schemaReader.getCalculatedMember(names);
            if (member != null) {
                return member;
            }
    }
    // Likewise named set.
    switch(category) {
        case Category.Set:
        case Category.Unknown:
            NamedSet namedSet = schemaReader.getNamedSet(names);
            if (namedSet != null) {
                return namedSet;
            }
    }
    // Now resolve the name one part at a time.
    for (int i = 0; i < names.size(); i++) {
        OlapElement child;
        Id.NameSegment name;
        if (names.get(i) instanceof Id.NameSegment) {
            name = (Id.NameSegment) names.get(i);
            child = schemaReader.getElementChild(parent, name, matchType);
        } else if (parent instanceof RolapLevel && names.get(i) instanceof Id.KeySegment && names.get(i).getKeyParts().size() == 1) {
            // The following code is for SsasCompatibleNaming=false.
            // Continues the very limited support for key segments in
            // mondrian-3.x. To be removed in mondrian-4, when
            // SsasCompatibleNaming=true is the only option.
            final Id.KeySegment keySegment = (Id.KeySegment) names.get(i);
            name = keySegment.getKeyParts().get(0);
            final List<Member> levelMembers = schemaReader.getLevelMembers((Level) parent, false);
            child = null;
            for (Member member : levelMembers) {
                if (((RolapMember) member).getKey().toString().equals(name.getName())) {
                    child = member;
                    break;
                }
            }
        } else {
            name = null;
            child = schemaReader.getElementChild(parent, name, matchType);
        }
        // last child
        if (child instanceof Member && !matchType.isExact() && !Util.equalName(child.getName(), name.getName())) {
            Member bestChild = (Member) child;
            for (int j = i + 1; j < names.size(); j++) {
                List<Member> childrenList = schemaReader.getMemberChildren(bestChild);
                Sorter.hierarchizeMemberList(childrenList, false);
                if (matchType == MatchType.AFTER) {
                    bestChild = childrenList.get(0);
                } else {
                    bestChild = childrenList.get(childrenList.size() - 1);
                }
                if (bestChild == null) {
                    child = null;
                    break;
                }
            }
            parent = bestChild;
            break;
        }
        if (child == null) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Util.lookupCompound: " + "parent.name=" + parent.getName() + " has no child with name=" + name);
            }
            if (!failIfNotFound) {
                return null;
            } else if (category == Category.Member) {
                throw MondrianResource.instance().MemberNotFound.ex(quoteMdxIdentifier(names));
            } else {
                throw MondrianResource.instance().MdxChildObjectNotFound.ex(name.toString(), parent.getQualifiedName());
            }
        }
        parent = child;
        if (matchType == MatchType.EXACT_SCHEMA) {
            matchType = MatchType.EXACT;
        }
    }
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("Util.lookupCompound: " + "found child.name=" + parent.getName() + ", child.class=" + parent.getClass().getName());
    }
    switch(category) {
        case Category.Dimension:
            if (parent instanceof Dimension) {
                return parent;
            } else if (parent instanceof Hierarchy) {
                return parent.getDimension();
            } else if (failIfNotFound) {
                throw Util.newError("Can not find dimension '" + implode(names) + "'");
            } else {
                return null;
            }
        case Category.Hierarchy:
            if (parent instanceof Hierarchy) {
                return parent;
            } else if (parent instanceof Dimension) {
                return parent.getHierarchy();
            } else if (failIfNotFound) {
                throw Util.newError("Can not find hierarchy '" + implode(names) + "'");
            } else {
                return null;
            }
        case Category.Level:
            if (parent instanceof Level) {
                return parent;
            } else if (failIfNotFound) {
                throw Util.newError("Can not find level '" + implode(names) + "'");
            } else {
                return null;
            }
        case Category.Member:
            if (parent instanceof Member) {
                return parent;
            } else if (failIfNotFound) {
                throw MondrianResource.instance().MdxCantFindMember.ex(implode(names));
            } else {
                return null;
            }
        case Category.Unknown:
            assertPostcondition(parent != null, "return != null");
            return parent;
        default:
            throw newInternal("Bad switch " + category);
    }
}
Also used : RolapCubeDimension(mondrian.rolap.RolapCubeDimension) RolapLevel(mondrian.rolap.RolapLevel) NameSegment(org.olap4j.mdx.NameSegment) ConcatenableList(mondrian.util.ConcatenableList) ArrayList(java.util.ArrayList) AbstractList(java.util.AbstractList) List(java.util.List) RolapLevel(mondrian.rolap.RolapLevel) KeySegment(org.olap4j.mdx.KeySegment) RolapMember(mondrian.rolap.RolapMember)

Aggregations

AbstractList (java.util.AbstractList)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 RolapCubeDimension (mondrian.rolap.RolapCubeDimension)1 RolapLevel (mondrian.rolap.RolapLevel)1 RolapMember (mondrian.rolap.RolapMember)1 ConcatenableList (mondrian.util.ConcatenableList)1 KeySegment (org.olap4j.mdx.KeySegment)1 NameSegment (org.olap4j.mdx.NameSegment)1