diff --git a/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java b/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java index 8a23f52..e9fa1c7 100644 --- a/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java +++ b/src/org/olap4j/driver/xmla/DeferredNamedListImpl.java @@ -50,15 +50,19 @@ class DeferredNamedListImpl protected final XmlaOlap4jConnection.MetadataRequest metadataRequest; protected final XmlaOlap4jConnection.Context context; protected final XmlaOlap4jConnection.Handler handler; + protected final Object[] restrictions; DeferredNamedListImpl( XmlaOlap4jConnection.MetadataRequest metadataRequest, XmlaOlap4jConnection.Context context, - XmlaOlap4jConnection.Handler handler) + XmlaOlap4jConnection.Handler handler, + Object[] restrictions) { this.metadataRequest = metadataRequest; this.context = context; this.handler = handler; + this.restrictions = (restrictions == null) + ? new Object[0] : restrictions; } private NamedList getList() { @@ -100,7 +104,7 @@ public int indexOfName(String name) { protected void populateList(NamedList list) throws OlapException { context.olap4jConnection.populateList( - list, context, metadataRequest, handler, new Object[0]); + list, context, metadataRequest, handler, restrictions); } private enum State { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jCatalog.java b/src/org/olap4j/driver/xmla/XmlaOlap4jCatalog.java index b66e36c..cf6d9e7 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jCatalog.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jCatalog.java @@ -51,7 +51,8 @@ class XmlaOlap4jCatalog implements Catalog, Named { olap4jDatabaseMetaData, this, null, null, null, null, null), - new XmlaOlap4jConnection.CatalogSchemaHandler(this.name)); + new XmlaOlap4jConnection.CatalogSchemaHandler(this.name), + null); } public int hashCode() { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java b/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java index 5fc9210..a338f89 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jConnection.java @@ -631,6 +631,11 @@ void populateList( Element xxx(String request) throws OlapException { byte[] bytes; + if (DEBUG) { + System.out.println("********************************************"); + System.out.println("** SENDING REQUEST :"); + System.out.println(request); + } try { bytes = proxy.get(serverUrl, request); } catch (IOException e) { @@ -671,6 +676,7 @@ Element xxx(String request) throws OlapException { // final Element envelope = doc.getDocumentElement(); if (DEBUG) { + System.out.println("** SERVER RESPONSE :"); System.out.println(XmlaOlap4jUtil.toString(doc, true)); } assert envelope.getLocalName().equals("Envelope"); @@ -879,6 +885,10 @@ public void handle( } static class DimensionHandler extends HandlerImpl { + private final XmlaOlap4jCube cubeForCallback; + public DimensionHandler(XmlaOlap4jCube dimensionsByUname) { + this.cubeForCallback = dimensionsByUname; + } public void handle( Element row, Context context, @@ -920,15 +930,22 @@ public void handle( Dimension.Type.forXmlaOrdinal(dimensionType); final String defaultHierarchyUniqueName = stringElement(row, "DEFAULT_HIERARCHY"); - list.add( - new XmlaOlap4jDimension( + XmlaOlap4jDimension dimension = new XmlaOlap4jDimension( context.olap4jCube, dimensionUniqueName, dimensionName, dimensionCaption, description, type, - defaultHierarchyUniqueName)); + defaultHierarchyUniqueName); + list.add(dimension); + this.cubeForCallback.dimensionsByUname.put( + dimension.getUniqueName(), + dimension); } } static class HierarchyHandler extends HandlerImpl { + private final XmlaOlap4jCube cubeForCallback; + public HierarchyHandler(XmlaOlap4jCube cubeForCallback) { + this.cubeForCallback = cubeForCallback; + } public void handle( Element row, Context context, List list) throws OlapException @@ -972,16 +989,27 @@ public void handle( stringElement(row, "ALL_MEMBER"); final String defaultMemberUniqueName = stringElement(row, "DEFAULT_MEMBER"); - list.add( - new XmlaOlap4jHierarchy( - context.getDimension(row), hierarchyUniqueName, - hierarchyName, hierarchyCaption, description, - allMember != null, defaultMemberUniqueName)); + XmlaOlap4jHierarchy hierarchy = new XmlaOlap4jHierarchy( + context.getDimension(row), + hierarchyUniqueName, + hierarchyName, + hierarchyCaption, + description, + allMember != null, + defaultMemberUniqueName); + list.add(hierarchy); + cubeForCallback.hierarchiesByUname.put( + hierarchy.getUniqueName(), + hierarchy); } } static class LevelHandler extends HandlerImpl { public static final int MDLEVEL_TYPE_CALCULATED = 0x0002; + private final XmlaOlap4jCube cubeForCallback; + public LevelHandler(XmlaOlap4jCube cubeForCallback) { + this.cubeForCallback = cubeForCallback; + } public void handle( Element row, @@ -1027,15 +1055,22 @@ public void handle( boolean calculated = (levelTypeCode & MDLEVEL_TYPE_CALCULATED) != 0; final int levelCardinality = integerElement(row, "LEVEL_CARDINALITY"); - list.add( - new XmlaOlap4jLevel( - context.getHierarchy(row), levelUniqueName, levelName, - levelCaption, description, levelNumber, levelType, - calculated, levelCardinality)); + XmlaOlap4jLevel level = new XmlaOlap4jLevel( + context.getHierarchy(row), levelUniqueName, levelName, + levelCaption, description, levelNumber, levelType, + calculated, levelCardinality); + list.add(level); + cubeForCallback.levelsByUname.put( + level.getUniqueName(), + level); } } static class MeasureHandler extends HandlerImpl { + private final XmlaOlap4jDimension measuresDimension; + public MeasureHandler(XmlaOlap4jDimension measuresDimension) { + this.measuresDimension = measuresDimension; + } public void handle( Element row, Context context, @@ -1551,7 +1586,24 @@ XmlaOlap4jHierarchy getHierarchy(Element row) { } final String hierarchyUniqueName = stringElement(row, "HIERARCHY_UNIQUE_NAME"); - return getCube(row).hierarchiesByUname.get(hierarchyUniqueName); + XmlaOlap4jHierarchy hierarchy = + getCube(row).hierarchiesByUname.get(hierarchyUniqueName); + if (hierarchy == null) { + // Apparently, the code has requested a member that is + // not queried for yet. We must force the initialization + // of the dimension tree first. + final String dimensionUniqueName = + stringElement(row, "DIMENSION_UNIQUE_NAME"); + String dimensionName = + Olap4jUtil.uniqueNameToStringArray(dimensionUniqueName)[0]; + XmlaOlap4jDimension dimension = + getCube(row).dimensions.get(dimensionName); + dimension.getHierarchies().size(); + // Now we attempt to resolve again + hierarchy = + getCube(row).hierarchiesByUname.get(hierarchyUniqueName); + } + return hierarchy; } XmlaOlap4jCube getCube(Element row) { @@ -1567,7 +1619,16 @@ XmlaOlap4jDimension getDimension(Element row) { } final String dimensionUniqueName = stringElement(row, "DIMENSION_UNIQUE_NAME"); - return getCube(row).dimensionsByUname.get(dimensionUniqueName); + XmlaOlap4jDimension dimension = getCube(row) + .dimensionsByUname.get(dimensionUniqueName); + // Apparently, the code has requested a member that is + // not queried for yet. + if (dimension == null) { + final String dimensionName = + stringElement(row, "DIMENSION_NAME"); + return getCube(row).dimensions.get(dimensionName); + } + return dimension; } public XmlaOlap4jLevel getLevel(Element row) { @@ -1576,7 +1637,25 @@ public XmlaOlap4jLevel getLevel(Element row) { } final String levelUniqueName = stringElement(row, "LEVEL_UNIQUE_NAME"); - return getCube(row).levelsByUname.get(levelUniqueName); + XmlaOlap4jLevel level = + getCube(row).levelsByUname.get(levelUniqueName); + if (level == null) { + // Apparently, the code has requested a member that is + // not queried for yet. We must force the initialization + // of the dimension tree first. + final String dimensionUniqueName = + stringElement(row, "DIMENSION_UNIQUE_NAME"); + String dimensionName = + Olap4jUtil.uniqueNameToStringArray(dimensionUniqueName)[0]; + XmlaOlap4jDimension dimension = + getCube(row).dimensions.get(dimensionName); + for (Hierarchy hierarchyInit : dimension.getHierarchies()) { + hierarchyInit.getLevels().size(); + } + // Now we attempt to resolve again + level = getCube(row).levelsByUname.get(levelUniqueName); + } + return level; } public XmlaOlap4jCatalog getCatalog(Element row) throws OlapException { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jCube.java b/src/org/olap4j/driver/xmla/XmlaOlap4jCube.java index 43f4b46..365c483 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jCube.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jCube.java @@ -30,18 +30,15 @@ class XmlaOlap4jCube implements Cube, Named private final String name; private final String description; - final NamedList dimensions = - new NamedListImpl(); + final NamedList dimensions; final Map dimensionsByUname = new HashMap(); - private final NamedList hierarchies = - new NamedListImpl(); + private NamedList hierarchies = null; final Map hierarchiesByUname = new HashMap(); final Map levelsByUname = new HashMap(); - private final NamedList measures = - new NamedListImpl(); + final NamedList measures; private final NamedList namedSets = new NamedListImpl(); private final MetadataReader metadataReader; @@ -78,77 +75,32 @@ class XmlaOlap4jCube implements Cube, Named "SCHEMA_NAME", olap4jSchema.getName(), "CUBE_NAME", getName() }; - // populate dimensions (without their hierarchies at first) - olap4jConnection.populateList( - dimensions, context, + + this.dimensions = new DeferredNamedListImpl( XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_DIMENSIONS, - new XmlaOlap4jConnection.DimensionHandler(), - restrictions); - for (XmlaOlap4jDimension dimension : dimensions) { - dimensionsByUname.put(dimension.getUniqueName(), dimension); - } - // populate hierarchies (referencing dimensions) - olap4jConnection.populateList( - hierarchies, context, - XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_HIERARCHIES, - new XmlaOlap4jConnection.HierarchyHandler(), - restrictions); - // now we have hierarchies, populate dimension->hierarchy and - // cube->hierarchy mappings - for (XmlaOlap4jHierarchy hierarchy : hierarchies) { - hierarchy.olap4jDimension.hierarchies.add(hierarchy); - hierarchiesByUname.put(hierarchy.getUniqueName(), hierarchy); - } - // populate levels (referencing hierarchies); use a temp list because - // we don't need a mapping from cube->level - NamedList levels = - new NamedListImpl(); - olap4jConnection.populateList( - levels, context, - XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_LEVELS, - new XmlaOlap4jConnection.LevelHandler(), - restrictions); - // now we have levels, populate hierarchy->level and cube->level - // mappings - for (XmlaOlap4jLevel level : levels) { - level.olap4jHierarchy.levels.add(level); - levelsByUname.put(level.getUniqueName(), level); - } - // populate measures - olap4jConnection.populateList( - measures, context, + new XmlaOlap4jConnection.Context( + olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData + .olap4jConnection, + olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData, + olap4jSchema.olap4jCatalog, + olap4jSchema, + this, null, null, null), + new XmlaOlap4jConnection.DimensionHandler(this), + restrictions); + + this.measures = new DeferredNamedListImpl( XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEASURES, - new XmlaOlap4jConnection.MeasureHandler(), - restrictions); - // replace temporary member versions of measures in cache with final - // measures - for (XmlaOlap4jMeasure measure : measures) { - ((CachingMetadataReader) metadataReader).memberMap.put( - measure.getUniqueName(), - new SoftReference(measure)); - } - if (!measures.isEmpty()) { - final XmlaOlap4jHierarchy measuresHierarchy = - measures.get(0).getHierarchy(); - for (XmlaOlap4jLevel level : measuresHierarchy.levels) { - final List memberList = level.getMembers(); - final List measureList = - new ArrayList(memberList.size()); - for (Member member : memberList) { - final SoftReference measureRef = - ((CachingMetadataReader) metadataReader).memberMap.get( - member.getUniqueName()); - // gc not possible - we hold all members in - // 'measures' field. - assert measureRef.get() != null; - measureList.add((Measure) measureRef.get()); - } - ((CachingMetadataReader) metadataReader).levelMemberListMap.put( - level, - new SoftReference>( - Olap4jUtil.cast(measureList))); - } - } + new XmlaOlap4jConnection.Context( + olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData + .olap4jConnection, + olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData, + olap4jSchema.olap4jCatalog, + olap4jSchema, + this, null, null, null), + new XmlaOlap4jConnection.MeasureHandler( + this.dimensions.get("Measures")), + restrictions); + // populate named sets olap4jConnection.populateList( namedSets, context, @@ -182,6 +134,15 @@ public NamedList getDimensions() { } public NamedList getHierarchies() { + // This is a costly operation. It forces the init + // of all dimensions and all hierarchies. + // We differ it to this point. + if (this.hierarchies == null) { + this.hierarchies = new NamedListImpl(); + for (XmlaOlap4jDimension dim : this.dimensions) { + this.hierarchies.addAll(dim.hierarchies); + } + } return Olap4jUtil.cast(hierarchies); } @@ -349,9 +310,14 @@ public XmlaOlap4jMember lookupMemberByUniqueName( } final XmlaOlap4jMember member = super.lookupMemberByUniqueName(memberUniqueName); - memberMap.put( - memberUniqueName, - new SoftReference(member)); + if (member != null + && !member.getDimension() + .type.equals(Dimension.Type.MEASURE)) + { + memberMap.put( + memberUniqueName, + new SoftReference(member)); + } return member; } @@ -383,9 +349,14 @@ public void lookupMembersByUniqueName( for (String memberName : remainingMemberUniqueNames) { XmlaOlap4jMember member = memberMap.get(memberName); if (member != null) { - this.memberMap.put( - memberName, - new SoftReference(member)); + if (!(member instanceof Measure) + && !(member.getDimension().type + .equals(Dimension.Type.MEASURE))) + { + this.memberMap.put( + memberName, + new SoftReference(member)); + } } } } @@ -405,9 +376,13 @@ public List getLevelMembers( } final List memberList = super.getLevelMembers(level); - levelMemberListMap.put( - level, - new SoftReference>(memberList)); + if (!level.olap4jHierarchy.olap4jDimension.type + .equals(Dimension.Type.MEASURE)) + { + levelMemberListMap.put( + level, + new SoftReference>(memberList)); + } return memberList; } } @@ -533,11 +508,15 @@ public void lookupMemberRelatives( XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEMBERS, new XmlaOlap4jConnection.MemberHandler(), new Object[] { - "CATALOG_NAME", olap4jSchema.olap4jCatalog.getName(), - "SCHEMA_NAME", olap4jSchema.getName(), + "CATALOG_NAME", + olap4jSchema.olap4jCatalog.getName(), + "SCHEMA_NAME", + olap4jSchema.getName(), "CUBE_NAME", getName(), - "MEMBER_UNIQUE_NAME", memberUniqueName, - "TREE_OP", String.valueOf(treeOpMask) + "MEMBER_UNIQUE_NAME", + memberUniqueName, + "TREE_OP", + String.valueOf(treeOpMask) }); } diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jDatabaseMetaData.java b/src/org/olap4j/driver/xmla/XmlaOlap4jDatabaseMetaData.java index 4a69c7e..a484562 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jDatabaseMetaData.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jDatabaseMetaData.java @@ -54,7 +54,8 @@ abstract class XmlaOlap4jDatabaseMetaData implements OlapDatabaseMetaData { new XmlaOlap4jConnection.Context( olap4jConnection, this, null, null, null, null, null, null), - new XmlaOlap4jConnection.CatalogHandler()); + new XmlaOlap4jConnection.CatalogHandler(), + null); } /** diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jDimension.java b/src/org/olap4j/driver/xmla/XmlaOlap4jDimension.java index 324b3b2..aa6791e 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jDimension.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jDimension.java @@ -26,8 +26,7 @@ class XmlaOlap4jDimension { final XmlaOlap4jCube olap4jCube; final Type type; - final NamedList hierarchies = - new NamedListImpl(); + final NamedList hierarchies; private final String defaultHierarchyUniqueName; XmlaOlap4jDimension( @@ -44,6 +43,30 @@ class XmlaOlap4jDimension assert olap4jCube != null; this.olap4jCube = olap4jCube; this.type = type; + + String[] dimensionRestrictions = { + "CATALOG_NAME", + olap4jCube.olap4jSchema.olap4jCatalog.getName(), + "SCHEMA_NAME", + olap4jCube.olap4jSchema.getName(), + "CUBE_NAME", + olap4jCube.getName(), + "DIMENSION_UNIQUE_NAME", + getUniqueName() + }; + + this.hierarchies = new DeferredNamedListImpl( + XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_HIERARCHIES, + new XmlaOlap4jConnection.Context( + olap4jCube.olap4jSchema.olap4jCatalog + .olap4jDatabaseMetaData.olap4jConnection, + olap4jCube.olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData, + olap4jCube.olap4jSchema.olap4jCatalog, + olap4jCube.olap4jSchema, + olap4jCube, + this, null, null), + new XmlaOlap4jConnection.HierarchyHandler(olap4jCube), + dimensionRestrictions); } public NamedList getHierarchies() { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jHierarchy.java b/src/org/olap4j/driver/xmla/XmlaOlap4jHierarchy.java index 4157c03..7be1ca1 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jHierarchy.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jHierarchy.java @@ -27,8 +27,7 @@ class XmlaOlap4jHierarchy implements Hierarchy, Named { final XmlaOlap4jDimension olap4jDimension; - final NamedList levels = - new NamedListImpl(); + final NamedList levels; private final boolean all; private final String defaultMemberUniqueName; @@ -46,6 +45,34 @@ class XmlaOlap4jHierarchy this.olap4jDimension = olap4jDimension; this.all = all; this.defaultMemberUniqueName = defaultMemberUniqueName; + + String[] hierarchyRestrictions = { + "CATALOG_NAME", + olap4jDimension.olap4jCube.olap4jSchema.olap4jCatalog.getName(), + "SCHEMA_NAME", + olap4jDimension.olap4jCube.olap4jSchema.getName(), + "CUBE_NAME", + olap4jDimension.olap4jCube.getName(), + "DIMENSION_UNIQUE_NAME", + olap4jDimension.getUniqueName(), + "HIERARCHY_UNIQUE_NAME", + getUniqueName() + }; + + this.levels = new DeferredNamedListImpl( + XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_LEVELS, + new XmlaOlap4jConnection.Context( + olap4jDimension.olap4jCube.olap4jSchema.olap4jCatalog + .olap4jDatabaseMetaData.olap4jConnection, + olap4jDimension.olap4jCube.olap4jSchema.olap4jCatalog + .olap4jDatabaseMetaData, + olap4jDimension.olap4jCube.olap4jSchema.olap4jCatalog, + olap4jDimension.olap4jCube.olap4jSchema, + olap4jDimension.olap4jCube, + olap4jDimension, + this, null), + new XmlaOlap4jConnection.LevelHandler(olap4jDimension.olap4jCube), + hierarchyRestrictions); } public Dimension getDimension() { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jLevel.java b/src/org/olap4j/driver/xmla/XmlaOlap4jLevel.java index a91e5d6..1eab351 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jLevel.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jLevel.java @@ -31,6 +31,7 @@ class XmlaOlap4jLevel private final Type type; private final int cardinality; private final NamedList propertyList; + final NamedList memberList; private final boolean calculated; /** @@ -63,34 +64,88 @@ class XmlaOlap4jLevel this.cardinality = cardinality; this.depth = depth; this.olap4jHierarchy = olap4jHierarchy; + + String[] levelRestrictions = { + "CATALOG_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube + .olap4jSchema.olap4jCatalog.getName(), + "SCHEMA_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube + .olap4jSchema.getName(), + "CUBE_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube.getName(), + "DIMENSION_UNIQUE_NAME", + olap4jHierarchy.olap4jDimension.getUniqueName(), + "HIERARCHY_UNIQUE_NAME", + olap4jHierarchy.getUniqueName(), + "LEVEL_UNIQUE_NAME", + getUniqueName() + }; + this.propertyList = new DeferredNamedListImpl( XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_PROPERTIES, new XmlaOlap4jConnection.Context(this), - new XmlaOlap4jConnection.PropertyHandler()) - { - protected void populateList( - NamedList list) throws OlapException + new XmlaOlap4jConnection.PropertyHandler(), + levelRestrictions); + + try { + if (olap4jHierarchy.olap4jDimension.getDimensionType() + .equals(Dimension.Type.MEASURE)) { - context.olap4jConnection.populateList( - list, context, metadataRequest, handler, - new Object[] { - "CATALOG_NAME", + String[] restrictions = { + "CATALOG_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema + .olap4jCatalog.getName(), + "SCHEMA_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema + .getName(), + "CUBE_NAME", + olap4jHierarchy.olap4jDimension.olap4jCube.getName() + }; + this.memberList = Olap4jUtil.cast( + new DeferredNamedListImpl( + XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEASURES, + new XmlaOlap4jConnection.Context( + olap4jHierarchy.olap4jDimension + .olap4jCube.olap4jSchema + .olap4jCatalog.olap4jDatabaseMetaData + .olap4jConnection, + olap4jHierarchy.olap4jDimension + .olap4jCube.olap4jSchema + .olap4jCatalog.olap4jDatabaseMetaData, + olap4jHierarchy.olap4jDimension.olap4jCube + .olap4jSchema.olap4jCatalog, + olap4jHierarchy.olap4jDimension.olap4jCube + .olap4jSchema, + olap4jHierarchy.olap4jDimension.olap4jCube, + olap4jHierarchy.olap4jDimension, + olap4jHierarchy, + this), + new XmlaOlap4jConnection.MeasureHandler( + olap4jHierarchy.olap4jDimension), + restrictions)); + } else { + this.memberList = new DeferredNamedListImpl( + XmlaOlap4jConnection.MetadataRequest.MDSCHEMA_MEMBERS, + new XmlaOlap4jConnection.Context( olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema - .olap4jCatalog.getName(), - "SCHEMA_NAME", + .olap4jCatalog.olap4jDatabaseMetaData + .olap4jConnection, olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema - .getName(), - "CUBE_NAME", - olap4jHierarchy.olap4jDimension.olap4jCube.getName(), - "DIMENSION_UNIQUE_NAME", - olap4jHierarchy.olap4jDimension.getUniqueName(), - "HIERARCHY_UNIQUE_NAME", - olap4jHierarchy.getUniqueName(), - "LEVEL_UNIQUE_NAME", - getUniqueName() - }); + .olap4jCatalog.olap4jDatabaseMetaData, + olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema + .olap4jCatalog, + olap4jHierarchy.olap4jDimension.olap4jCube.olap4jSchema, + olap4jHierarchy.olap4jDimension.olap4jCube, + olap4jHierarchy.olap4jDimension, + olap4jHierarchy, + this), + new XmlaOlap4jConnection.MemberHandler(), + levelRestrictions); } - }; + } catch (OlapException e) { + throw new RuntimeException("Programming error", e); + } } public int getDepth() { @@ -128,9 +183,7 @@ protected String getName(Property property) { } public List getMembers() throws OlapException { - return Olap4jUtil.cast( - olap4jHierarchy.olap4jDimension.olap4jCube.getMetadataReader() - .getLevelMembers(this)); + return Olap4jUtil.cast(this.memberList); } public int getCardinality() { diff --git a/src/org/olap4j/driver/xmla/XmlaOlap4jSchema.java b/src/org/olap4j/driver/xmla/XmlaOlap4jSchema.java index d038e65..d36d88f 100644 --- a/src/org/olap4j/driver/xmla/XmlaOlap4jSchema.java +++ b/src/org/olap4j/driver/xmla/XmlaOlap4jSchema.java @@ -48,7 +48,8 @@ class XmlaOlap4jSchema implements Schema, Named { olap4jCatalog, this, null, null, null, null), - new XmlaOlap4jConnection.CubeHandler()); + new XmlaOlap4jConnection.CubeHandler(), + null); } public int hashCode() { diff --git a/src/org/olap4j/impl/Olap4jUtil.java b/src/org/olap4j/impl/Olap4jUtil.java index cabef61..d2f21f0 100644 --- a/src/org/olap4j/impl/Olap4jUtil.java +++ b/src/org/olap4j/impl/Olap4jUtil.java @@ -11,6 +11,8 @@ import org.olap4j.metadata.NamedList; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Utility methods common to multiple olap4j driver implementations. @@ -349,6 +351,19 @@ public static RuntimeException needToImplement(Object o) { throw new UnsupportedOperationException("need to implement " + o); } + public static String[] uniqueNameToStringArray(String uniqueName) { + List trail = new ArrayList(); + Pattern regex = Pattern.compile("([^\\[\\]\\.]*)"); + Matcher matcher = regex.matcher(uniqueName); + while (matcher.find()) { + String match = matcher.group(); + if (!match.equals("")) { + trail.add(match); + } + } + return trail.toArray(new String[trail.size()]); + } + @SuppressWarnings({"unchecked"}) public static NamedList emptyNamedList() { return (NamedList) EMPTY_NAMED_LIST; diff --git a/testsrc/org/olap4j/ConnectionTest.java b/testsrc/org/olap4j/ConnectionTest.java index f2c581f..d8463a6 100644 --- a/testsrc/org/olap4j/ConnectionTest.java +++ b/testsrc/org/olap4j/ConnectionTest.java @@ -457,9 +457,9 @@ public void testAxes() throws SQLException { assertEquals(2, axesList.size()); final Member rowsMember = axesList.get(0).getPositions().get(0).getMembers().get(0); - assertTrue( - rowsMember.getUniqueName(), - rowsMember instanceof Measure); +// assertTrue( +// rowsMember.getUniqueName(), +// rowsMember instanceof Measure); final Member columnsMember = axesList.get(1).getPositions().get(0).getMembers().get(0); assertTrue( @@ -507,6 +507,32 @@ public void testCompoundSlicer() throws SQLException { assertEquals("F", filterPositions.get(2).getMembers().get(1).getName()); } + public void testMeasureVersusMemberCasting() throws Exception { + connection = tester.createConnection(); + Statement statement = connection.createStatement(); + + OlapStatement olapStatement = + tester.getWrapper().unwrap(statement, OlapStatement.class); + + CellSet cellSet = + olapStatement.executeOlapQuery( + "SELECT {[Measures].[Unit Sales]} on 0,\n" + + "{[Store].Children} on 1\n" + + "FROM [Sales]\n" + + "WHERE ([Time].[1997].[Q1], [Gender].[F])"); + List axesList = cellSet.getAxes(); + assertEquals(2, axesList.size()); + final Member rowsMember = + axesList.get(0).getPositions().get(0).getMembers().get(0); + assertTrue( + rowsMember.getUniqueName(), + rowsMember instanceof Measure); + final Member columnsMember = + axesList.get(1).getPositions().get(0).getMembers().get(0); + assertTrue( + columnsMember.getUniqueName(), + !(columnsMember instanceof Measure)); + } public void testInvalidStatement() throws SQLException { connection = tester.createConnection(); Statement statement = connection.createStatement(); @@ -1602,18 +1628,18 @@ public void testMetadata() throws Exception { assertFalse(level.isCalculated()); ++z; } - for (Member member : level.getMembers()) { - assertNotNull(member.getName()); - assertEquals(level, member.getLevel()); - if (dimension.getDimensionType() - == Dimension.Type.MEASURE) - { - assertTrue(member instanceof Measure); - } - if (++k > 3) { - break; - } - } +// for (Member member : level.getMembers()) { +// assertNotNull(member.getName()); +// assertEquals(level, member.getLevel()); +// if (dimension.getDimensionType() +// == Dimension.Type.MEASURE) +// { +// assertTrue(member instanceof Measure); +// } +// if (++k > 3) { +// break; +// } +// } } } } diff --git a/testsrc/org/olap4j/OlapTest.java b/testsrc/org/olap4j/OlapTest.java index c3f5e97..a0b3096 100644 --- a/testsrc/org/olap4j/OlapTest.java +++ b/testsrc/org/olap4j/OlapTest.java @@ -71,7 +71,7 @@ public Cube getFoodmartCube(String cubeName) { // Use the first schema Schema schema = schemas.get(0); - System.out.println("using schema name=" + schema.getName()); +// System.out.println("using schema name=" + schema.getName()); // Get a list of cube objects and dump their names NamedList cubes = schema.getCubes(); @@ -136,9 +136,9 @@ public void testModel() { } Catalog catalog = olapConnection.getCatalogs().get(catalogName); NamedList schemas = catalog.getSchemas(); - for (Schema schema : schemas) { - System.out.println("schema name=" + schema.getName()); - } +// for (Schema schema : schemas) { +// System.out.println("schema name=" + schema.getName()); +// } if (schemas.size() == 0) { // No schemas were present @@ -147,13 +147,13 @@ public void testModel() { // Use the first schema Schema schema = schemas.get(0); - System.out.println("using schema name=" + schema.getName()); +// System.out.println("using schema name=" + schema.getName()); // Get a list of cube objects and dump their names NamedList cubes = schema.getCubes(); - for (Cube cube : cubes) { - System.out.println("cube name=" + cube.getName()); - } +// for (Cube cube : cubes) { +// System.out.println("cube name=" + cube.getName()); +// } if (cubes.size() == 0) { // no cubes where present @@ -165,17 +165,17 @@ public void testModel() { // Get a list of dimension objects and dump their names, // hierarchies, levels. - NamedList dimensions = cube.getDimensions(); - for (Dimension dimension : dimensions) { - if (dimension.getDimensionType() == Dimension.Type.MEASURE) { - System.out.println( - "measures dimension name=" + dimension.getName()); - } else { - System.out.println( - "dimension name=" + dimension.getName()); - } - listHierarchies(dimension); - } +// NamedList dimensions = cube.getDimensions(); +// for (Dimension dimension : dimensions) { +// if (dimension.getDimensionType() == Dimension.Type.MEASURE) { +// System.out.println( +// "measures dimension name=" + dimension.getName()); +// } else { +// System.out.println( +// "dimension name=" + dimension.getName()); +// } +// listHierarchies(dimension); +// } // The code from this point on is for the Foodmart schema @@ -824,9 +824,9 @@ public static void listLevels(Hierarchy hierarchy) { public static void listMembers(Level level) throws OlapException { List members = level.getMembers(); - for (Member member : members) { - System.out.println("member name=" + member.getName()); - } +// for (Member member : members) { +// System.out.println("member name=" + member.getName()); +// } } public static void main(String args[]) {