Skip to content

Commit

Permalink
MONDRIAN: Rearchitect XMLA support; add CatalogLocator (check in on b…
Browse files Browse the repository at this point in the history
…ehalf of Gang Chen).

[git-p4: depot-paths = "//open/mondrian/": change = 4806]
  • Loading branch information
julianhyde committed Dec 23, 2005
1 parent 559834f commit f2de1e1
Show file tree
Hide file tree
Showing 47 changed files with 4,296 additions and 4,589 deletions.
99 changes: 26 additions & 73 deletions src/main/mondrian/olap/DriverManager.java
Expand Up @@ -12,18 +12,13 @@

package mondrian.olap;
import mondrian.rolap.RolapConnection;
import mondrian.resource.MondrianResource;
import mondrian.spi.impl.ServletContextCatalogLocator;

import javax.servlet.ServletContext;
import javax.sql.DataSource;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;

/**
* The basic service for managing a set of OLAP drivers
* The basic service for managing a set of OLAP drivers.
*
* @author jhyde
* @since 15 January, 2002
Expand All @@ -49,69 +44,25 @@ public DriverManager() {
* @return A {@link Connection}
* @post return != null
*/
public static Connection getConnection(String connectString,
ServletContext servletContext,
boolean fresh) {
public static Connection getConnection(
String connectString,
ServletContext servletContext,
boolean fresh) {
Util.PropertyList properties = Util.parseConnectString(connectString);
return getConnection(properties, servletContext, fresh);
}

private static void fixup(Util.PropertyList connectionProperties,
ServletContext servletContext) {
private static void fixup(
Util.PropertyList connectionProperties,
ServletContext servletContext) {
String catalog = connectionProperties.get("catalog");
// If the catalog is an absolute path, it refers to a resource inside
// our WAR file, so replace the URL.
if (catalog != null && catalog.startsWith("/")) {
try {
URL url = servletContext.getResource(catalog);
if (url == null) {
// The catalog does not exist, but construct a feasible
// URL so that the error message makes sense.
url = servletContext.getResource("/");
url = new URL(url.getProtocol(), url.getHost(),
url.getPort(), url.getFile() + catalog.substring(1));
}
if (url != null) {
catalog = url.toString();
connectionProperties.put("catalog", catalog);
}
} catch (MalformedURLException e) {
// Ignore the error
}
}
}

private static Connection getAdomdConnection(String connectString,
boolean fresh) {
try {
Class clazz = Class.forName("Broadbase.mdx.adomd.AdomdConnection");
try {
String sCatalog = null;
Constructor constructor = clazz.getConstructor(
new Class[] {
String.class,
String.class,
Boolean.TYPE
}
);
return (Connection) constructor.newInstance(
new Object[] {
connectString,
sCatalog,
(fresh) ? Boolean.TRUE : Boolean.FALSE
}
);
} catch (IllegalAccessException e) {
throw Util.newInternal(e, "while creating " + clazz);
} catch (NoSuchMethodException e) {
throw Util.newInternal(e, "while creating " + clazz);
} catch (InstantiationException e) {
throw Util.newInternal(e, "while creating " + clazz);
} catch (InvocationTargetException e) {
throw Util.newInternal(e, "while creating " + clazz);
if (servletContext != null) {
final ServletContextCatalogLocator locator =
new ServletContextCatalogLocator(servletContext);
final String newCatalog = locator.locate(catalog);
if (newCatalog.equals(catalog)) {
connectionProperties.put("catalog", catalog);
}
} catch (ClassNotFoundException e) {
throw Util.newInternal(e, "while connecting to " + connectString);
}
}

Expand Down Expand Up @@ -139,11 +90,13 @@ public static Connection getConnection(
* @return A {@link Connection}
* @post return != null
*/
public static Connection getConnection(Util.PropertyList properties,
ServletContext servletContext,
boolean fresh) {
public static Connection getConnection(
Util.PropertyList properties,
ServletContext servletContext,
boolean fresh) {
return getConnection(properties, servletContext, null, fresh);
}

/**
* Creates a connection to a Mondrian OLAP Server.
*
Expand All @@ -159,14 +112,14 @@ public static Connection getConnection(Util.PropertyList properties,
* @return A {@link Connection}
* @post return != null
*/
public static Connection getConnection(Util.PropertyList properties,
ServletContext servletContext,
DataSource dataSource,
boolean fresh) {
public static Connection getConnection(
Util.PropertyList properties,
ServletContext servletContext,
DataSource dataSource,
boolean fresh) {
String provider = properties.get("PROVIDER");
if (!provider.equalsIgnoreCase("mondrian")) {
String connectString = properties.toString();
return getAdomdConnection(connectString, fresh);
throw Util.newError("Provider not recognized: " + provider);
}
if (servletContext != null) {
MondrianProperties.instance().populate(servletContext);
Expand Down
21 changes: 20 additions & 1 deletion src/main/mondrian/olap/Property.java
Expand Up @@ -3,7 +3,7 @@
// 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.
// (C) Copyright 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
Expand Down Expand Up @@ -348,6 +348,25 @@ public class Property extends EnumeratedValues.BasicValue {
public static final Property DATATYPE =
new Property("DATATYPE", TYPE_STRING, DATATYPE_ORDINAL, false, false, true, "The datatype of the cell.");

public static final int DEPTH_ORDINAL = 43;
/**
* Definition of the property which
* holds the level depth of a member.
* Caution: Level depth of members in parent-child hierarchy isn't from their levels.
* It's calculated from the underlying data dynamically.
*/
public static final Property DEPTH =
new Property("DEPTH", TYPE_NUMERIC, DEPTH_ORDINAL, true, true, false, "The level depth of a member");

public static final int DISPLAY_INFO_ORDINAL = 44;
/**
* Definition of the property which
* holds the DISPLAY_INFO required by XML/A
* Caution: This property's value is calculated base on a specified MDX query, so it's value is dynamical at runtime.
*/
public static final Property DISPLAY_INFO =
new Property("DISPLAY_INFO", TYPE_NUMERIC, DISPLAY_INFO_ORDINAL, false, true, false, "Display instruction of a member for XML/A");

/**
* The various property names which define a format string.
*/
Expand Down
9 changes: 9 additions & 0 deletions src/main/mondrian/rolap/RolapLevel.java
Expand Up @@ -240,9 +240,18 @@ RolapProperty[] getRolapProperties() {
String getNullParentValue() {
return nullParentValue;
}

/**
* Returns whether this level is parent-child.
*/
public boolean isParentChild() {
return parentExp != null;
}

MondrianDef.Expression getParentExp() {
return parentExp;
}

MondrianDef.Expression getNameExp() {
return nameExp;
}
Expand Down
24 changes: 14 additions & 10 deletions src/main/mondrian/rolap/RolapNativeSet.java
@@ -1,11 +1,11 @@
/*
//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) 2004-2005 TONBELLER AG
//All Rights Reserved.
//You must accept the terms of that agreement to use this software.
*/
// 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) 2004-2005 TONBELLER AG
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.rolap;

import java.util.ArrayList;
Expand Down Expand Up @@ -37,6 +37,7 @@
*
* @author av
* @since Nov 12, 2005
* @version $Id$
*/
public abstract class RolapNativeSet extends RolapNative {
protected static final Logger LOGGER = Logger.getLogger(RolapNativeSet.class);
Expand Down Expand Up @@ -455,14 +456,17 @@ protected CrossJoinArg[] checkCrossJoinArg(FunDef fun, Exp[] args) {
protected static boolean isSimpleLevel(RolapLevel level) {
RolapHierarchy hier = (RolapHierarchy) level.getHierarchy();
// does not work with ragged hierarchies
if (hier.isRagged())
if (hier.isRagged()) {
return false;
}
// does not work with parent/child
if (level.getParentExp() != null)
if (level.isParentChild()) {
return false;
}
// does not work for measures
if (level.isMeasure())
if (level.isMeasure()) {
return false;
}
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/rolap/RolapSchemaReader.java
Expand Up @@ -128,7 +128,7 @@ public int getMemberDepth(Member member) {
memberDepth -= topLevel.getDepth();
}
return memberDepth;
} else if (((RolapLevel) member.getLevel()).getParentExp() != null) {
} else if (((RolapLevel) member.getLevel()).isParentChild()) {
// For members of parent-child hierarchy, members in the same level may have
// different depths.
int depth = 0;
Expand Down
1 change: 1 addition & 0 deletions src/main/mondrian/rolap/RolapUtil.java
Expand Up @@ -70,6 +70,7 @@ public String toString() {
return "null";
}
};
public static final String sqlNullLiteral = "null";

/**
* Names of classes of drivers we've loaded (or have tried to load).
Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/rolap/SqlConstraintUtils.java
Expand Up @@ -69,7 +69,7 @@ public static void addContextConstraint(SqlQuery sqlQuery, Evaluator e, boolean

String expr = column.getExpression(sqlQuery);
String value = sqlQuery.quote(column.isNumeric(), values[i]);
sqlQuery.addWhere(expr, " = ", value);
sqlQuery.addWhere(expr, RolapUtil.sqlNullLiteral.equals(value) ? " is " : " = ", value);
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/main/mondrian/rolap/SqlMemberSource.java
Expand Up @@ -3,7 +3,7 @@
// 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.
// (C) Copyright 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
Expand Down Expand Up @@ -647,13 +647,14 @@ private RolapLevel getCommonChildLevelForDescendants(List parents) {
if (parentLevel == null) {
parentLevel = (RolapLevel) member.getLevel();
// check for parent/child
if (parentLevel.getParentExp() != null)
if (parentLevel.isParentChild()) {
return null;
}
childLevel = getChildLevel(parentLevel);
if (childLevel == null) {
return null;
}
if (childLevel.getParentExp() != null) {
if (childLevel.isParentChild()) {
return null;
}
} else if (parentLevel != member.getLevel()) {
Expand Down Expand Up @@ -684,7 +685,7 @@ private void getMemberChildren(RolapMember parentMember,
boolean parentChild;
final RolapLevel parentLevel = (RolapLevel) parentMember.getLevel();
RolapLevel childLevel;
if (parentLevel.getParentExp() != null) {
if (parentLevel.isParentChild()) {
sql = makeChildMemberSqlPC(parentMember, jdbcConnection);
parentChild = true;
childLevel = parentLevel;
Expand All @@ -701,7 +702,7 @@ private void getMemberChildren(RolapMember parentMember,
// member is at last level, so can have no children
return;
}
if (childLevel.getParentExp() != null) {
if (childLevel.isParentChild()) {
sql = makeChildMemberSql_PCRoot(parentMember, jdbcConnection);
parentChild = true;
} else {
Expand Down
16 changes: 7 additions & 9 deletions src/main/mondrian/rolap/SqlTupleReader.java
Expand Up @@ -17,8 +17,6 @@

import javax.sql.DataSource;

import org.apache.log4j.Logger;

import mondrian.olap.MondrianDef;
import mondrian.olap.MondrianProperties;
import mondrian.olap.Util;
Expand All @@ -30,19 +28,19 @@
/**
* reads the members of a single level (level.members) or of multiple levels (crossjoin).
* <p>
* Allows the result to be restricted by a {@link mondrian.rolap.sql.TupleConstraint}. So
* Allows the result to be restricted by a {@link mondrian.rolap.sql.TupleConstraint}. So
* the SqlTupleReader can also read Member.Descendants (which is level.members restricted
* to a common parent) and member.children (which is a special case of member.descendants).
* Other constraints, especially for the current slicer or evaluation context, are possible.
*
*
* <p>
* Caching:
* <p>
* When this class reads level.members, it groups the result into parent/children pairs
* <p>
* When this class reads level.members, it groups the result into parent/children pairs
* and puts them into the cache. In order that these can be found later when the
* children of a parent are requested, a matching constraint must be provided for
* children of a parent are requested, a matching constraint must be provided for
* every parent.
*
*
* <ul>
* <li>When reading members from a single level, then the constraint is not required to
* join the fact table in
Expand Down Expand Up @@ -94,7 +92,7 @@ public void open() {
levels = (RolapLevel[]) hierarchy.getLevels();
list = new ArrayList();
levelDepth = level.getDepth();
parentChild = level.getParentExp() != null;
parentChild = level.isParentChild();
// members[i] is the current member of level#i, and siblings[i]
// is the current member of level#i plus its siblings
members = new RolapMember[levels.length];
Expand Down
27 changes: 27 additions & 0 deletions src/main/mondrian/spi/impl/CatalogLocatorImpl.java
@@ -0,0 +1,27 @@
/*
// $Id$
// 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.
// (C) Copyright 2005-2005 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.spi.impl;

import mondrian.spi.CatalogLocator;

/**
* CatalogLocator which returns the catalog URI unchanged.
*
* @author jhyde
* @version $Id$
* @since Dec 22, 2005
*/
public class CatalogLocatorImpl implements CatalogLocator {
public String locate(String catalogPath) {
return catalogPath;
}
}

// End CatalogLocatorImpl.java

0 comments on commit f2de1e1

Please sign in to comment.