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 + -
显示快捷键?