rolapschema.java

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

JAVA
1,346
字号
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/RolapSchema.java#53 $
// 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.
// Copyright (C) 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 26 July, 2001
*/

package mondrian.rolap;
import mondrian.olap.*;
import mondrian.olap.Member;
import mondrian.olap.fun.*;
import mondrian.olap.type.Type;
import mondrian.spi.UserDefinedFunction;
import mondrian.rolap.aggmatcher.AggTableManager;
import mondrian.resource.MondrianResource;

import org.apache.log4j.Logger;
import org.eigenbase.xom.*;
import org.eigenbase.xom.Parser;

import javax.sql.DataSource;
import java.io.*;
import java.lang.ref.SoftReference;
import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * A <code>RolapSchema</code> is a collection of {@link RolapCube}s and
 * shared {@link RolapDimension}s. It is shared betweeen {@link
 * RolapConnection}s. It caches {@link MemberReader}s, etc.
 *
 * @see RolapConnection
 * @author jhyde
 * @since 26 July, 2001
 * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapSchema.java#53 $
 **/
public class RolapSchema implements Schema {
    private static final Logger LOGGER = Logger.getLogger(RolapSchema.class);

    private static final int[] schemaAllowed = new int[] {Access.NONE, Access.ALL, Access.ALL_DIMENSIONS};
    private static final int[] cubeAllowed = new int[] {Access.NONE, Access.ALL};
    private static final int[] dimensionAllowed = new int[] {Access.NONE, Access.ALL};
    private static final int[] hierarchyAllowed = new int[] {Access.NONE, Access.ALL, Access.CUSTOM};
    private static final int[] memberAllowed = new int[] {Access.NONE, Access.ALL};

    private String name;
    /**
     * Internal use only.
     */
    private final RolapConnection internalConnection;
    /**
     * Holds cubes in this schema.
     */
    private final Map mapNameToCube;
    /**
     * Maps {@link String shared hierarchy name} to {@link MemberReader}.
     * Shared between all statements which use this connection.
     */
    private final Map mapSharedHierarchyToReader;

    /**
     * Maps {@link String names of shared hierarchies} to {@link
     * RolapHierarchy the canonical instance of those hierarchies}.
     */
    private final Map mapSharedHierarchyNameToHierarchy;
    /**
     * The default role for connections to this schema.
     */
    private Role defaultRole;

    private final String md5Bytes;

    /**
     * A schema's aggregation information
     */
    private AggTableManager aggTableManager;

    /**
     * This is basically a unique identifier for this RolapSchema instance
     * used it its equals and hashCode methods.
     */
    private String key;
    /**
     * Maps {@link String names of roles} to {@link Role roles with those names}.
     */
    private final Map mapNameToRole;
    /**
     * Maps {@link String names of sets} to {@link NamedSet named sets}.
     */
    private final Map mapNameToSet = new HashMap();
    /**
     * Table containing all standard MDX functions, plus user-defined functions
     * for this schema.
     */
    private FunTable funTable;

    private MondrianDef.Schema xmlSchema;

    private RolapSchema(final String key,
                        final Util.PropertyList connectInfo,
                        final DataSource dataSource,
                        final String md5Bytes) {
        this.key = key;
        this.md5Bytes = md5Bytes;
        // the order of the next two lines is important
        this.defaultRole = createDefaultRole();
        this.internalConnection =
            new RolapConnection(connectInfo, this, dataSource);

        this.mapSharedHierarchyNameToHierarchy = new HashMap();
        this.mapSharedHierarchyToReader = new HashMap();
        this.mapNameToCube = new HashMap();
        this.mapNameToRole = new HashMap();
        this.aggTableManager = new AggTableManager(this);
    }

    /**
     * Loads a schema using a dynamic loader.
     *
     * @param dynProcName
     * @param catalogName
     * @param connectInfo
     */
    private RolapSchema(
            final String key,
            final String catalogName,
            final Util.PropertyList connectInfo,
            final String dynProcName,
            final DataSource dataSource) {
        this(key, connectInfo, dataSource, (String) null);

        String catalogStr = null;

        try {
            final URL url = new URL(catalogName);

            final Class clazz = Class.forName(dynProcName);
            final Constructor ctor = clazz.getConstructor(new Class[0]);
            final DynamicSchemaProcessor dynProc =
                    (DynamicSchemaProcessor) ctor.newInstance(new Object[0]);
            catalogStr = dynProc.processSchema(url, connectInfo);

        } catch (Exception e) {
            throw Util.newError(e, "loading DynamicSchemaProcessor "
                    + dynProcName);
        }

        load(catalogName, catalogStr);
    }

    /**
     * Create RolapSchema given the catalog name and string (content) and
     * the connectInfo object.
     *
     * @param catalogName
     * @param catalogStr
     * @param connectInfo
     */
    private RolapSchema(final String key,
                        final String catalogName,
                        final String catalogStr,
                        final Util.PropertyList connectInfo,
                        final DataSource dataSource) {
        this(key, null, catalogName, catalogStr, connectInfo, dataSource);
    }
    /**
     * Create RolapSchema given the MD5 hash, catalog name and string (content)
     * and the connectInfo object.
     *
     * @param md5Bytes may be null
     * @param catalogName
     * @param catalogStr may be null
     * @param connectInfo
     */
    private RolapSchema(final String key,
                        final String md5Bytes,
                        final String catalogName,
                        final String catalogStr,
                        final Util.PropertyList connectInfo,
                        final DataSource dataSource) {
        this(key, connectInfo, dataSource, md5Bytes);

        load(catalogName, catalogStr);
    }

    private RolapSchema(final String key,
                        final String catalogName,
                        final Util.PropertyList connectInfo,
                        final DataSource dataSource) {

        this(key, connectInfo, dataSource, null);

        load(catalogName, null);
    }

    public boolean equals(Object o) {
        if (!(o instanceof RolapSchema)) {
            return false;
        }
        RolapSchema other = (RolapSchema) o;
        return other.key.equals(key);
    }
    public int hashCode() {
        return key.hashCode();
    }

    protected Logger getLogger() {
        return LOGGER;
    }

    /**
     * Method called by all constructors to load the catalog into DOM and build
     * application mdx and sql objects.
     *
     * @param catalogName
     * @param catalogStr
     */
    protected void load(String catalogName, String catalogStr) {
        try {
            final Parser xmlParser = XOMUtil.createDefaultParser();

            final DOMWrapper def;
            if (catalogStr == null) {
                URL url = new URL(catalogName);
                def = xmlParser.parse(url);
            } else {
                def = xmlParser.parse(catalogStr);
            }

            xmlSchema = new MondrianDef.Schema(def);

            if (getLogger().isDebugEnabled()) {
                StringWriter sw = new StringWriter(4096);
                PrintWriter pw = new PrintWriter(sw);
                pw.println("RolapSchema.load: dump xmlschema");
                xmlSchema.display(pw, 2);
                pw.flush();
                getLogger().debug(sw.toString());
            }

            load(xmlSchema);

        } catch (MalformedURLException e) {
            throw Util.newError(e, "while parsing catalog " + catalogName);
        } catch (XOMException e) {
            throw Util.newError(e, "while parsing catalog " + catalogName);
        }

        aggTableManager.initialize();
    }

    Role getDefaultRole() {
        return defaultRole;
    }
    MondrianDef.Schema getXMLSchema() {
        return xmlSchema;
    }

    public String getName() {
        Util.assertPostcondition(name != null, "return != null");
        Util.assertPostcondition(name.length() > 0, "return.length() > 0");
        return name;
    }

    private void load(MondrianDef.Schema xmlSchema) {
        this.name = xmlSchema.name;
        if (name == null || name.equals("")) {
            throw Util.newError("<Schema> name must be set");
        }
        // Validate user-defined functions. Must be done before we validate
        // calculated members, because calculated members will need to use the
        // function table.
        final Map mapNameToUdf = new HashMap();
        for (int i = 0; i < xmlSchema.userDefinedFunctions.length; i++) {
            MondrianDef.UserDefinedFunction udf = xmlSchema.userDefinedFunctions[i];
            defineFunction(mapNameToUdf, udf.name, udf.className);
        }
        final RolapSchemaFunctionTable funTable =
                new RolapSchemaFunctionTable(mapNameToUdf.values());
        funTable.init();
        this.funTable = funTable;

        // Validate public dimensions.
        for (int i = 0; i < xmlSchema.dimensions.length; i++) {
            MondrianDef.Dimension xmlDimension = xmlSchema.dimensions[i];
            if (xmlDimension.foreignKey != null) {
                throw MondrianResource.instance()
                        .PublicDimensionMustNotHaveForeignKey.ex(
                                xmlDimension.name);
            }
        }
        for (int i = 0; i < xmlSchema.cubes.length; i++) {
            MondrianDef.Cube xmlCube = xmlSchema.cubes[i];
            if (xmlCube.isEnabled()) {
                RolapCube cube = new RolapCube(this, xmlSchema, xmlCube);
                Util.discard(cube);
            }
        }
        for (int i = 0; i < xmlSchema.virtualCubes.length; i++) {
            MondrianDef.VirtualCube xmlVirtualCube = xmlSchema.virtualCubes[i];
            if (xmlVirtualCube.isEnabled()) {
                RolapCube cube = new RolapCube(this, xmlSchema, xmlVirtualCube);
                Util.discard(cube);
            }
        }
        for (int i = 0; i < xmlSchema.namedSets.length; i++) {
            MondrianDef.NamedSet xmlNamedSet = xmlSchema.namedSets[i];
            mapNameToSet.put(xmlNamedSet.name, createNamedSet(xmlNamedSet));
        }
        for (int i = 0; i < xmlSchema.roles.length; i++) {
            MondrianDef.Role xmlRole = xmlSchema.roles[i];
            Role role = createRole(xmlRole);
            mapNameToRole.put(xmlRole.name, role);
        }
        if (xmlSchema.defaultRole != null) {
            Role role = lookupRole(xmlSchema.defaultRole);
            if (role == null) {
                throw Util.newError("Role '" + xmlSchema.defaultRole + "' not found");
            }
            defaultRole = role;
        }
    }

    private NamedSet createNamedSet(MondrianDef.NamedSet xmlNamedSet) {
        final String formulaString = xmlNamedSet.getFormula();
        final Exp exp;
        try {
            exp = getInternalConnection().parseExpression(formulaString);

⌨️ 快捷键说明

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