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