descendantsfundef.java

来自「数据仓库展示程序」· Java 代码 · 共 177 行

JAVA
177
字号
/*
// $Id: //open/mondrian/src/main/mondrian/olap/fun/DescendantsFunDef.java#6 $
// 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 2004-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.olap.fun;

import mondrian.olap.*;
import mondrian.resource.MondrianResource;

import java.util.List;
import java.util.ArrayList;

/**
 * Definition of the <code>DESCENDANTS</code> MDX function.
 */
class DescendantsFunDef extends FunDefBase {
    private final boolean self;
    private final boolean before;
    private final boolean after;
    private final boolean depthSpecified;
    private final int depthLimit;

    public DescendantsFunDef(
            FunDef dummyFunDef,
            int flag,
            boolean depthSpecified,
            int depthLimit) {
        super(dummyFunDef);

        this.self = FunUtil.checkFlag(flag, Flags.SELF, true);
        this.after = FunUtil.checkFlag(flag, Flags.AFTER, true);
        this.before = FunUtil.checkFlag(flag, Flags.BEFORE, true);
//      leaves = FunUtil.checkFlag(flag, Flags.LEAVES, true);
        this.depthSpecified = depthSpecified;
        this.depthLimit = depthLimit;
    }

    public Object evaluate(Evaluator evaluator, Exp[] args) {
        Member member = getMemberArg(evaluator, args, 0, true);
        List result = new ArrayList();
        final SchemaReader schemaReader = evaluator.getSchemaReader();
        if (depthSpecified) {
            descendantsByDepth(member, result, schemaReader,
                    depthLimit, before, self, after);
        } else {
            final Level level = args.length > 1
                ?  getLevelArg(evaluator, args, 1, true)
                : member.getLevel();
            schemaReader.getMemberDescendants(member, result,
                    level, before, self, after);
        }

        hierarchize(result, false);

        return result;
    }

    private static void descendantsByDepth(Member member,
                                           List result,
                                           final SchemaReader schemaReader,
                                           final int depthLimitFinal,
                                           final boolean before,
                                           final boolean self,
                                           final boolean after) {
        Member[] children = {member};
        for (int depth = 0;; ++depth) {
            if (depth == depthLimitFinal) {
                if (self) {
                    addAll(result, children);
                }
                if (!after) {
                    break; // no more results after this level
                }
            } else if (depth < depthLimitFinal) {
                if (before) {
                    addAll(result, children);
                }
            } else {
                if (after) {
                    addAll(result, children);
                } else {
                    break; // no more results after this level
                }
            }

            children = schemaReader.getMemberChildren(children);
            if (children.length == 0) {
                break;
            }
        }
    }

    /**
     * Enumeration of the flags allowed to the <code>DESCENDANTS</code>
     * function.
     */
    static class Flags extends EnumeratedValues {
        static final Flags instance = new Flags();
        private Flags() {
            super(
                new String[] {
                    "SELF", "AFTER", "BEFORE", "BEFORE_AND_AFTER",
                    "SELF_AND_AFTER", "SELF_AND_BEFORE","SELF_BEFORE_AFTER",
                    "LEAVES"},
                new int[] {
                    SELF, AFTER, BEFORE, BEFORE_AND_AFTER,
                    SELF_AND_AFTER, SELF_AND_BEFORE, SELF_BEFORE_AFTER,
                    LEAVES});
        }
        public static final int SELF = 1;
        public static final int AFTER = 2;
        public static final int BEFORE = 4;
        public static final int BEFORE_AND_AFTER = BEFORE | AFTER;
        public static final int SELF_AND_AFTER = SELF | AFTER;
        public static final int SELF_AND_BEFORE = SELF | BEFORE;
        public static final int SELF_BEFORE_AFTER = SELF | BEFORE | AFTER;
        public static final int LEAVES = 8;
    }

    /**
     * Resolves calls to the <code>DESCENDANTS</code> function.
     */
    static class Resolver extends MultiResolver {
        public Resolver() {
            super("Descendants",
                "Descendants(<Member>[, <Level>[, <Desc_flag>]])",
                "Returns the set of descendants of a member at a specified level, optionally including or excluding descendants in other levels.",
                new String[]{"fxm", "fxml", "fxmly", "fxmn", "fxmny"});
        }

        protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
            int depthLimit = -1; // unlimited
            boolean depthSpecified = false;
            int flag = Flags.SELF;
            if (args.length == 1) {
                depthLimit = -1;
                flag = Flags.SELF_BEFORE_AFTER;
            }
            if (args.length >= 2) {
                if (args[1] instanceof Literal) {
                    Literal literal = (Literal) args[1];
                    if (literal.getValue() instanceof Number) {
                        Number number = (Number) literal.getValue();
                        depthLimit = number.intValue();
                        depthSpecified = true;
                    }
                }
            }
            if (args.length >= 3) {
                flag = FunUtil.getLiteralArg(args, 2, Flags.SELF,
                    Flags.instance, dummyFunDef);
            }

            if (FunUtil.checkFlag(flag, Flags.LEAVES, true)) {
                // LEAVES isn't supported
                throw MondrianResource.instance().LeavesNotSupported.ex();
            }
            final int depthLimitFinal = depthLimit < 0
                ?  Integer.MAX_VALUE
                : depthLimit;
            final int flagFinal = flag;
            final boolean depthSpecifiedFinal = depthSpecified;
            return new DescendantsFunDef(dummyFunDef, flagFinal,
                depthSpecifiedFinal, depthLimitFinal);
        }

        public String[] getReservedWords() {
            return Flags.instance.getNames();
        }
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?