rolapcube.java

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

JAVA
1,687
字号
    private static MondrianDef.Relation reorder(
            MondrianDef.Relation relation,
            RolapLevel[] levels) {
        // Need at least two levels, with only one level theres nothing to do.
        if (levels.length < 2) {
            return relation;
        }

        Map nodeMap = new HashMap();

        // Create RelNode in top down order (year -> day)
        for (int i = 0; i < levels.length; i++) {
            RolapLevel level = levels[i];

            if (level.isAll()) {
                continue;
            }

            // this is the table alias
            String tableName = level.getTableName();
            if (tableName == null) {
                // punt, no table name
                return relation;
            }
            RelNode rnode = new RelNode(tableName, i);
            nodeMap.put(tableName, rnode);
        }
        if (! validateNodes(relation, nodeMap)) {
            return relation;
        }
        relation = copy(relation);

        // Put lower levels to the left of upper levels
        leftToRight(relation, nodeMap);

        // Move joins to the right side
        topToBottom(relation);

        return relation;
    }

    /**
     * The map has to be validated against the relation because there are
     * certain cases where we do not want to (read: can not) do reordering, for
     * instance, when closures are involved.
     *
     * @param relation
     * @param map
     * @return
     */
    private static boolean validateNodes(MondrianDef.Relation relation, Map map) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;

            RelNode relNode = RelNode.lookup(table, map);
            return (relNode != null);

        } else if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;

            return validateNodes(join.left, map) &&
                validateNodes(join.right, map);

        } else {
            throw Util.newInternal("bad relation type " + relation);
        }

    }

    /**
     * Transforms the Relation moving the tables associated with
     * lower levels (greater level depth, i.e., Day is lower than Month) to the
     * left of tables with high levels.
     *
     * @param relation
     * @param map
     * @return
     */
    private static int leftToRight(MondrianDef.Relation relation, Map map) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;

            RelNode relNode = RelNode.lookup(table, map);
            // Associate the table with its RelNode!!!! This is where this
            // happens.
            relNode.table = table;

            return relNode.depth;

        } else if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;
            int leftDepth = leftToRight(join.left, map);
            int rightDepth = leftToRight(join.right, map);

            // we want the right side to be less than the left
            if (rightDepth > leftDepth) {
                // switch
                String leftAlias = join.leftAlias;
                String leftKey = join.leftKey;
                MondrianDef.Relation left = join.left;
                join.leftAlias = join.rightAlias;
                join.leftKey = join.rightKey;
                join.left = join.right;
                join.rightAlias = leftAlias;
                join.rightKey = leftKey;
                join.right = left;
            }
            // Does not currently matter which is returned because currently we
            // only support structures where the left and right depth values
            // form an inclusive subset of depth values, that is, any
            // node with a depth value between the left or right values is
            // a child of this current join.
            return leftDepth;

        } else {
            throw Util.newInternal("bad relation type " + relation);
        }

    }

    /**
     * Transforms so that all joins have a table as their left child and either
     * a table of child join on the right.
     *
     * @param relation
     */
    private static void topToBottom(MondrianDef.Relation relation) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;
            // nothing

        } else if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;

            while (join.left instanceof MondrianDef.Join) {
                MondrianDef.Join jleft = (MondrianDef.Join) join.left;
                MondrianDef.Relation right = join.right;

                join.right = new MondrianDef.Join(
                        join.leftAlias,
                        join.leftKey,
                        jleft.right,
                        join.rightAlias,
                        join.rightKey,
                        join.right);

                join.left = jleft.left;

                join.rightAlias = jleft.rightAlias;
                join.rightKey = jleft.rightKey;
                join.leftAlias = jleft.leftAlias;
                join.leftKey = jleft.leftKey;
            }
        }

    }

    /**
     * Copies a {@link MondrianDef.Relation}.
     *
     * @param relation
     * @return
     */
    private static MondrianDef.Relation copy(MondrianDef.Relation relation) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;
            return new MondrianDef.Table(table);

        } else if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;

            MondrianDef.Relation left = copy(join.left);
            MondrianDef.Relation right = copy(join.right);

            return new MondrianDef.Join(join.leftAlias, join.leftKey, left,
                        join.rightAlias, join.rightKey, right);

        } else {
            throw Util.newInternal("bad relation type " + relation);
        }
    }

    /**
     * Takes a relation in canonical form and snips off the
     * the tables with the given tableName (or table alias). The matching table
     * only appears once in the relation.
     *
     * @param relation
     * @param tableName
     * @return
     */
    private static MondrianDef.Relation snip(MondrianDef.Relation relation,
                String tableName) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;
            // Return null if the table's name or alias matches tableName
            return ((table.alias != null) && table.alias.equals(tableName))
                ? null
                : (table.name.equals(tableName) ? null : table);

        } else if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;

            // snip left
            MondrianDef.Relation left = snip(join.left, tableName);
            if (left == null) {
                // left got snipped so return the right
                // (the join is no longer a join).
                return join.right;

            } else {
                // whatever happened on the left, save it
                join.left = left;

                // snip right
                MondrianDef.Relation right = snip(join.right, tableName);
                if (right == null) {
                    // right got snipped so return the left.
                    return join.left;

                } else {
                    // save the right, join still has right and left children
                    // so return it.
                    join.right = right;
                    return join;
                }
            }


        } else {
            throw Util.newInternal("bad relation type " + relation);
        }

    }
    //
    ///////////////////////////////////////////////////////////////////////////



    public Member[] getMembersForQuery(String query, List calcMembers) {
        throw new UnsupportedOperationException();
    }

    Member[] getMeasures() {
        Level measuresLevel = dimensions[0].getHierarchies()[0].getLevels()[0];
        return getSchemaReader().getLevelMembers(measuresLevel);
    }

    /**
     * Returns this cube's fact table, null if the cube is virtual.
     * @return
     */
    MondrianDef.Relation getFact() {
        return fact;
    }

    /**
     * Returns whether this cube is virtual. We use the fact that virtual cubes
     * do not have fact tables.
     **/
    public boolean isVirtual() {
        return (fact == null);
    }

    RolapDimension createDimension(MondrianDef.CubeDimension xmlCubeDimension) {
        MondrianDef.Dimension xmlDimension = null;
        final RolapDimension dimension;
        if (xmlCubeDimension instanceof MondrianDef.Dimension) {
            xmlDimension = (MondrianDef.Dimension) xmlCubeDimension;
            dimension = new RolapDimension(schema, this, xmlDimension,
                xmlCubeDimension);
        } else if (xmlCubeDimension instanceof MondrianDef.DimensionUsage) {
            final MondrianDef.DimensionUsage usage =
                (MondrianDef.DimensionUsage) xmlCubeDimension;
            final RolapHierarchy sharedHierarchy =
                ((RolapSchema) schema).getSharedHierarchy(usage.source);
            if (sharedHierarchy == null) {
                throw Util.newInternal("todo: Shared hierarchy '" + usage.source +
                                        "' not found");
            }

            final RolapDimension sharedDimension =
                (RolapDimension) sharedHierarchy.getDimension();
            dimension = sharedDimension.copy(this, usage.name,
                xmlCubeDimension);
        } else {
            throw Util.newInternal("Unexpected subtype, " + xmlCubeDimension);
        }

        dimension.init(this, xmlCubeDimension);
        // add to dimensions array
        final int localOrdinal = dimensions.length;
        this.dimensions = (DimensionBase[])
            RolapUtil.addElement(dimensions, dimension);

        RolapHierarchy hierarchy = (RolapHierarchy) dimension.getHierarchy();
        createUsage(hierarchy, xmlCubeDimension);


        // add to ordinals array
        final int globalOrdinal = dimension.getGlobalOrdinal();
        if (globalOrdinal >= localDimensionOrdinals.length) {
            int[] newLocalDimensionOrdinals = new int[globalOrdinal + 1];
            System.arraycopy(localDimensionOrdinals, 0,
                    newLocalDimensionOrdinals, 0, localDimensionOrdinals.length);
            Arrays.fill(newLocalDimensionOrdinals,
                    localDimensionOrdinals.length,
                    newLocalDimensionOrdinals.length, -1);
            this.localDimensionOrdinals = newLocalDimensionOrdinals;
        }
        Util.assertTrue(localDimensionOrdinals[globalOrdinal] == -1);
        localDimensionOrdinals[globalOrdinal] = localOrdinal;
        registerDimension(dimension);
        return dimension;
    }

    public OlapElement lookupChild(SchemaReader schemaReader, String s) {
        OlapElement oe = null;
        String status = null;
        if (s.equals("Measures")) {
            // A Measure is never aliased, so just get it
            // Note if one calls getUsageByName with "Measures" as the value
            // it will return null so one must either do this or check for
            // a null HierarchyUsage below and disambiguate.
            oe = super.lookupChild(schemaReader, s);

        } else {
            // At this point everything ought to have a HierarchyUsage.
            //
            // If one does not exist (null), then odds are one is using
            // the base/source hierarchy name in a calculated measure
            // for a shared hierarchy - which is not legal.
            // But there are cases where its OK here not to have a
            // usage, i.e., the child is a measure, member or level
            //

⌨️ 快捷键说明

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