rankfundef.java

来自「数据仓库展示程序」· Java 代码 · 共 468 行 · 第 1/2 页

JAVA
468
字号
            }
            return new Double(j + 1); // 1-based
        }
    }

    /**
     * Expression which evaluates an expression to form a list of tuples,
     * evaluates a scalar expression at each tuple, then sorts the list of
     * values. The result is a value of type {@link SortResult}, and can be
     * used to implement the <code>Rank</code> function efficiently.
     */
    private static class SortExp extends ExpBase {
        private final Exp listExp;
        private final Exp sortExp;

        public SortExp(Exp listExp, Exp sortExp) {
            this.listExp = listExp;
            this.sortExp = sortExp;
        }

        public Object clone() {
            return this;
        }

        public int getCategory() {
            throw new UnsupportedOperationException();
        }

        public Type getTypeX() {
            // white lie -- the answer is not important
            return new NumericType();
        }

        public Exp accept(Validator validator) {
            return this;
        }

        public boolean dependsOn(Dimension dimension) {
            // Similar dependency pattern to ORDER function (qv).
            // Depends upon everything listExp and sortExp depend upon, except
            // the dimensions of listExp.
            if (listExp.dependsOn(dimension)) {
                return true;
            }
            if (listExp.getTypeX().usesDimension(dimension)) {
                return false;
            }
            return sortExp.dependsOn(dimension);
        }

        public Object evaluate(Evaluator evaluator) {
            // Create a new evaluator so we don't corrupt the given one.
            final Evaluator evaluator2 = evaluator.push();
            // Construct an array containing the value of the expression
            // for each member.
            List members = (List) listExp.evaluate(evaluator2);
            if (members == null) {
                return new SortResult(true, null);
            }
            RuntimeException exception = null;
            Object[] values = new Object[members.size()];
            int j = 0;
            for (int i = 0; i < members.size(); i++) {
                final Object o = members.get(i);
                if (o instanceof Member) {
                    Member member = (Member) o;
                    evaluator2.setContext(member);
                } else {
                    evaluator2.setContext((Member[]) o);
                }
                final Object value = sortExp.evaluateScalar(evaluator2);
                if (value instanceof RuntimeException) {
                    if (exception == null) {
                        exception = (RuntimeException) value;
                    }
                } else if (value == Util.nullValue) {
                    ;
                } else {
                    values[j++] = value;
                }
            }
            // If there were exceptions, quit now... we'll be back.
            if (exception != null) {
                return exception;
            }
            // If the array is shorter than we expected (because of null
            // values) truncate it.
            if (j < members.size()) {
                final Object[] oldValues = values;
                values = new Object[j];
                System.arraycopy(oldValues, 0, values, 0, j);
            }
            // Sort the array.
            FunUtil.sortValuesDesc(values);
            return new SortResult(false, values);
        }
    }

    /**
     * Holder for the result of sorting a set of values.
     *
     * <p>todo: More optimal representation if a lot of the values are the
     * same.
     */
    private static class SortResult {
        /**
         * Whether the list of tuples was empty.
         * If this is the case, the rank will always be null.
         *
         * <p>It's possible for there to be a positive number of tuples, all
         * of whose values are null, in which case, empty will be false but
         * values will be empty.
         */
        final boolean empty;
        /**
         * Values in sorted order. Null values are not present: they would
         * be at the end, anyway.
         */
        final Object[] values;

        public SortResult(boolean empty, Object[] values) {
            this.empty = empty;
            this.values = values;
        }

        public void print(PrintWriter pw) {
            if (empty) {
                pw.println("SortResult: empty");
            } else {
                pw.println("SortResult {");
                for (int i = 0; i < values.length; i++) {
                    if (i > 0) {
                        pw.println(",");
                    }
                    Object value = values[i];
                    pw.print(value);
                }
                pw.println("}");
            }
            pw.flush();
        }
    }

    /**
     * Expression which evaluates an expression to form a list of tuples.
     * The result is a value of type {@link RankedList}, or null if the list
     * is empty.
     */
    private static class RankedListExp extends ExpBase {
        private final Exp listExp;

        public RankedListExp(Exp listExp) {
            this.listExp = listExp;
        }

        public Object clone() {
            return this;
        }

        public int getCategory() {
            return listExp.getCategory();
        }

        public Type getTypeX() {
            return listExp.getTypeX();
        }

        public Exp accept(Validator validator) {
            return this;
        }

        public boolean dependsOn(Dimension dimension) {
            return listExp.dependsOn(dimension);
        }

        public Object evaluate(Evaluator evaluator) {
            // Construct an array containing the value of the expression
            // for each member.
            List members = (List) listExp.evaluate(evaluator);
            if (members == null) {
                return null;
            }
            return new RankedList(members);
        }
    }

    /**
     * Data structure which contains a list and can return the position of an
     * element in the list in O(log N).
     */
    static class RankedList {
        Map map = new HashMap();

        RankedList(List members) {
            for (int i = 0; i < members.size(); i++) {
                Object o = (Object) members.get(i);
                final Object key;
                if (o instanceof Member) {
                    key = o;
                } else if (o instanceof Member[]) {
                    key = Arrays.asList((Member []) o);
                } else {
                    throw Util.newInternal("bad member/tuple " + o);
                }
                final Object value = map.put(key, new Integer(i));
                if (value != null) {
                    // The list already contained a value for this key -- put
                    // it back.
                    map.put(key, value);
                }
            }
        }

        int indexOf(Member m) {
            return indexOf((Object) m);
        }

        int indexOf(Member[] tuple) {
            return indexOf(Arrays.asList(tuple));
        }

        private int indexOf(Object o) {
            Integer integer = (Integer) map.get(o);
            if (integer == null) {
                return -1;
            } else {
                return integer.intValue();
            }
        }
    }
}

// End RankFunDef.java

⌨️ 快捷键说明

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