Skip to content

Commit

Permalink
Lots of tests for metadata classes, and implement corresponding funct…
Browse files Browse the repository at this point in the history
…ionality in mondrian driver.

Review org.olap4j.type package, and remove/hide several methods.
Add API for creating validator and validating an MDX parse tree.
Test that non-unique axis names cause a validation error.

git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@38 c6a108a4-781c-0410-a6c6-c2d559e19af0
  • Loading branch information
julianhyde committed Nov 13, 2007
1 parent fb680a8 commit 96d3da3
Show file tree
Hide file tree
Showing 54 changed files with 1,743 additions and 376 deletions.
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<property file="${project.location}/build.properties"/>
<property name="project.build.debug" value="on"/>
<property name="name" value="olap4j"/>
<property name="version" value="0.6"/>
<property name="version" value="0.89.3"/>
<property name="dist.name" value="${name}-${version}" />

<!-- properties related to paths -->
Expand Down
66 changes: 48 additions & 18 deletions doc/olap4j_fs.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@
<h1>olap4j Functional Specification</h1>

<p>Authors: Julian Hyde, Barry Klawans<br>
Version: 0.89.2-dev (draft)<br>
Version: 0.89.3-dev (draft)<br>
Revision: $Id$
(<a href="http://olap4j.svn.sourceforge.net/viewvc/olap4j/trunk/doc/olap4j_fs.html?view=log">log</a>)<br>
Last modified: September 21<sup>st</sup>, 2007.</p>
Last modified: November 12<sup>th</sup>, 2007.</p>
<hr noshade="noshade">

<h2><a name="Contents">Contents</a></h2>
Expand Down Expand Up @@ -898,7 +898,7 @@ <h3>2.4. <a name="MDX_query_model">MDX query model</a></h3>
<div class="code">
// Create a query model.<br>
SelectNode query = new SelectNode();<br>
query.setCubeName(<br>
query.setFrom(<br>
&nbsp;&nbsp;&nbsp; new IdentifierNode(<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new
IdentifierNode.Segment(&quot;Sales&quot;)));<br>
Expand Down Expand Up @@ -982,12 +982,36 @@ <h3>2.5. <a name="MDX_parser">MDX parser</a></h3>

<p>Package name: <a class="javadoc" href="api/org/olap4j/type/package-summary.html">org.olap4j.mdx.parser</a></p>

<p>Provides an MDX parser.</p>
<p>Provides an MDX parser and validator.</p>
<p>Parser and validator are both allocated via a parser factory, which is
obtained from a connection:</p>

<div class="code">
OlapConnection connection;<br>
MdxParserFactory parserFactory =<br>
&nbsp;&nbsp;&nbsp; connection.getParserFactory();<br>
MdxParser parser =<br>
&nbsp;&nbsp;&nbsp; parserFactory.createMdxParser(connection);<br>
SelectNode select =<br>
&nbsp;&nbsp;&nbsp; parser.parse(&quot;SELECT FROM [Sales]&quot;);<br>
MdxValidator validator =<br>
&nbsp;&nbsp;&nbsp; parserFactory.createMdxValidator(connection);<br>
select = validator.validate(select);</div>

<p>Parser and validator are not thread-safe (they cannot be used by more than
one thread simultaneously) but they can be re-used for multiple statements.</p>
<p>One of the chief purposes of validation is to assign a type to every
expression within the parse tree. Before validation, any node's
<a class="javadoc" href="api/org/olap4j/mdx/ParseTreeNode.html#getType()">
ParseTreeNode.getType()</a> method may throw an exception, but after validation
the <code>getType()</code> method will return a type. Nodes which are not
expressions do not have types, and will always return <code>null</code>.</p>
<p>Classes:</p>

<ul>
<li><code>MdxParserFactory</code></li>
<li><code>MdxParser</code></li>
<li><a class="javadoc" href="api/org/olap4j/mdx/parser/MdxParserFactory.html">MdxParserFactory</a></li>
<li><a class="javadoc" href="api/org/olap4j/mdx/parser/MdxParser.html">MdxParser</a></li>
<li><a class="javadoc" href="api/org/olap4j/mdx/parser/MdxValidator.html">MdxValidator</a></li>
</ul>

<h3 align="left">2.6. <a name="MDX_type_model">MDX type model</a></h3>
Expand Down Expand Up @@ -1208,13 +1232,15 @@ <h5>2.7.2.4. <a name="Cube">The Cube interface</a></h5>
formula.</p>

<ul>
<li><code>List&lt;Dimension&gt; getDimensions()</code></li>
<li><code>NamedList&lt;Dimension&gt; getDimensions()</code></li>
<li><code>List&lt;Measure&gt; getMeasures()</code></li>
<li><code>NamedList&lt;NamedSet&gt; getSets()</code></li>
<li><code>Schema getSchema()</code></li>
<li><code>String getName()</code></li>
<li><code>List&lt;Locale&gt; getSupportedLocales()</code> (see <a href="#Internationalization">
Internationalization</a>)</li>
<li><code>Member lookupMember(String... nameParts)</code></li>
<li><code>Member lookupMembers(Set&lt;TreeOp&gt; treeOps, String... nameParts)</code></li>
</ul>

<h5>2.7.2.5. <a name="Dimension">The Dimension interface</a></h5>
Expand All @@ -1230,8 +1256,7 @@ <h5>2.7.2.5. <a name="Dimension">The Dimension interface</a></h5>

<ul>
<li><code>String getName()</code></li>
<li><code>List&lt;Hierarchy&gt; getHierarchies()</code></li>
<li><code>List&lt;Member&gt; getRootMembers()</code></li>
<li><code>NamedList&lt;Hierarchy&gt; getHierarchies()</code></li>
<li><code>Dimension.Type getDimensionType()</code></li>
</ul>
<h5>2.7.2.6. <a name="Hierarchy">The Hierarchy interface</a></h5>
Expand All @@ -1244,9 +1269,10 @@ <h5>2.7.2.6. <a name="Hierarchy">The Hierarchy interface</a></h5>
<ul>
<li><code>Dimension getDimension()</code></li>
<li><code>String getName()</code></li>
<li><code>List&lt;Level&gt; getLevels()</code></li>
<li><code>NamedList&lt;Level&gt; getLevels()</code></li>
<li><code>boolean hasAll()</code></li>
<li><code>Member getDefaultMember()</code></li>
<li><code>NamedList&lt;Member&gt; getRootMembers()</code></li>
</ul>
<h5>2.7.2.7. <a name="Level">The Level interface</a></h5>
<p>A <a class="javadoc" href="api/org/olap4j/metadata/Level.html">Level</a>&nbsp;
Expand All @@ -1257,7 +1283,7 @@ <h5>2.7.2.7. <a name="Level">The Level interface</a></h5>
<li><code>int getDepth()</code></li>
<li><code>Hierarchy getHierarchy()</code></li>
<li><code>Level.Type getLevelType()</code></li>
<li><code>List&lt;Property&gt; getProperties()</code></li>
<li><code>NamedList&lt;Property&gt; getProperties()</code></li>
<li><code>List&lt;Member&gt; getMembers()</code></li>
</ul>
<h5>2.7.2.8. <a name="Member">The Member interface</a></h5>
Expand All @@ -1266,10 +1292,11 @@ <h5>2.7.2.8. <a name="Member">The Member interface</a></h5>
MetadataElement</a>) is a data value in an OLAP dimension.</p>
<ul>
<li><code>String getName()</code></li>
<li><code>List&lt;Member&gt; getChildMembers()</code></li>
<li><code>NamedList&lt;Member&gt; getChildMembers()</code></li>
<li><code>Member getParentMember()</code></li>
<li><code>Level getLevel()</code></li>
<li><code>Hierarchy getHierarchy()</code></li>
<li><code>boolean isAll()</code></li>
<li><code>boolean isChildOrEqualTo(Member member)</code></li>
<li><code>boolean isCalculated()</code></li>
<li><code>boolean isCalculatedInQuery()</code></li>
Expand All @@ -1278,11 +1305,12 @@ <h5>2.7.2.8. <a name="Member">The Member interface</a></h5>
<li><code>Object getPropertyValue(Property property)</code></li>
<li><code>String getPropertyFormattedValue(Property property)</code></li>
<li><code>void setProperty(Property property, Object value)</code></li>
<li><code>List&lt;Property&gt; getProperties()</code></li>
<li><code>NamedList&lt;Property&gt; getProperties()</code></li>
<li><code>int getOrdinal()</code></li>
<li><code>boolean isHidden()</code></li>
<li><code>Member getDataMember()</code></li>
</ul>

<h5>2.7.2.9. <a name="Measure">The Measure interface</a></h5>

<p>A <a class="javadoc" href="api/org/olap4j/metadata/Measure.html">Measure</a>&nbsp;(extends
Expand Down Expand Up @@ -1312,7 +1340,6 @@ <h5>2.7.2.10. <a name="Property">The Property interface</a></h5>
<ul>
<li><code>Datatype getType()</code></li>
<li><code>Scope getScope()</code></li>
<li><code>boolean isInternal()</code></li>
<li><code>enum Scope { MEMBER, CELL }</code></li>
<li><code>enum Datatype { STRING, OTHER, NUMERIC, BOOLEAN }</code></li>
<li><code>enum StandardMemberProperty implements Property { CATALOG_NAME, SCHEMA_NAME, CUBE_NAME, ...
Expand Down Expand Up @@ -3451,8 +3478,9 @@ <h2>Appendix D. <a name="Miscellaneous">Miscellaneous</a></h2>

<h3>D.1. To be specified</h3>

<p>[Method for richer query of members, analogous to OlapDatabaseMetaData.getMembers(). Maybe extend Cube.lookupMember. Something with a treeop.]</p>
<p>[Discuss thread safety of connections, statements, result sets.]</p>
<p>[API for cancelling statements.]</p>
<p>[API for canceling statements.]</p>
<p>[2006/10/20#1. Specification should include compliance levels, like the SQL
specification does. In particular, we will allow providers to comply with a
limited subset of MDX.]</p>
Expand All @@ -3476,10 +3504,12 @@ <h3>D.1. To be specified</h3>
efficiency as a design goal.]</p>
<h3>D.2. Design notes</h3>

<p><a name="JDK">JDK</a>. We are targeting JDK 1.5, and running retroweaver for
<p><a name="JDK">JDK</a>.</p>
<p>We are targeting JDK 1.5, and running retroweaver for
backward compatibility for JDK 1.4. See forum thread:
<a href="http://sourceforge.net/forum/forum.php?thread_id=1560764&amp;forum_id=577988">
olap4j, JDK 1.5 and generics</a>. </p>
olap4j, JDK 1.5 and generics</a>.</p>
<p>We also support JDK 1.6, and with it JDBC 4.0. </p>
<h4>Result sets, random access, and memory usage</h4>
<p>Should result sets return their axes as cursors or collections? Cursors
require less memory, but collections provide an easier programming model.</p>
Expand Down Expand Up @@ -3520,4 +3550,4 @@ <h2>Appendix F. <a name="Change_log">Change log</a></h2>

<hr noshade="noshade">

</body></html>
</body></html>
12 changes: 4 additions & 8 deletions doc/tasks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,19 @@ Specification
Javadoc
-------

* change ant task so it doesn't generate mondrian.olap4j.* or olap4j.test.* or org.olap4j.mdx.parser.impl or package-protected classes (E.g. org.olap4j.mdx.MdxValidator) in public api; remove class OlapTest, class Todo
* remove class OlapTest
* ensure that every public method has a javadoc description, including @param, @return and @throws declarations
* Review olap4j.type package. Document all public methods. Make non-essential methods (E.g. MemberType.forType) package-private. If in doubt, leave it out


Code
----

* fix 4 TODOs in ParserTest
* document/implement Cube.lookupMember


Testing
-------

* Remove site-specifics from test code.
* Ensure that there is a unit test for every method in every public class or interface.
* Write unit test for metadata classes.
* Internationalization test, including Connection.getLocale(), Query.getLocale(), and all methods with Locale methods or results
* Test access control. The metadata (e.g. members & hierarchies) should reflect what the current user/role can see. For example, USA.CA.SF has no children. This test should test every method which returns a metadata element or collection of metadata elements.
* ConnectionTest (428, 8) // todo: test statement with no slicer
Expand All @@ -55,8 +52,7 @@ Testing
* Test methods in OlapResultAxisMetaData (see ConnectionTest.testOlapResultAxisMetaData)
* Test cell and dimension properties (in ConnectionTest, see "todo: submit a query with cell and dimension properties, and make sure the properties appear in the result set")
* Test scrolling (in ConnectionTest, see "todo: submit a query where you ask for different scrolling")
* Test axis name uniqueness (in ConnectionTest, see "test that get error if axes do not have unique names (todo)")


Not in scope for olap4j 0.9
---------------------------

Expand Down
14 changes: 8 additions & 6 deletions src/mondrian/olap4j/AbstractNamedList.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,24 @@
* Partial implementation of {@link org.olap4j.metadata.NamedList}.
*
* <p>Derived class must implement {@link #get(int)} and {@link #size()}, as
* per {@link java.util.AbstractList}.
* per {@link java.util.AbstractList}; and must implement
* {@link #getName(Object)}, to indicate how elements are named.
*
* @see mondrian.olap4j.NamedListImpl
* @see ArrayNamedListImpl
*
* @author jhyde
* @version $Id$
* @since May 25, 2007
*/
abstract class AbstractNamedList<T extends Named>
abstract class AbstractNamedList<T>
extends AbstractList<T>
implements NamedList<T>
{
protected abstract String getName(T t);

public T get(String name) {
for (T t : this) {
if (t.getName().equals(name)) {
if (getName(t).equals(name)) {
return t;
}
}
Expand All @@ -41,13 +44,12 @@ public T get(String name) {
public int indexOfName(String name) {
for (int i = 0; i < size(); ++i) {
T t = get(i);
if (t.getName().equals(name)) {
if (getName(t).equals(name)) {
return i;
}
}
return -1;
}

}

// End AbstractNamedList.java
54 changes: 54 additions & 0 deletions src/mondrian/olap4j/ArrayNamedListImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
// 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) 2007-2007 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.olap4j;

import org.olap4j.metadata.NamedList;

import java.util.ArrayList;

/**
* Implementation of {@link org.olap4j.metadata.NamedList} which uses
* {@link java.util.ArrayList} for storage.
*
* <p>Derived class must implement {@link #getName(Object)}, to indicate how
* elements are named.
*
* @see mondrian.olap4j.NamedListImpl
*
* @author jhyde
* @version $Id: $
* @since Nov 12, 2007
*/
public abstract class ArrayNamedListImpl<T>
extends ArrayList<T>
implements NamedList<T>
{
protected abstract String getName(T t);

public T get(String name) {
for (T t : this) {
if (getName(t).equals(name)) {
return t;
}
}
return null;
}

public int indexOfName(String name) {
for (int i = 0; i < size(); ++i) {
T t = get(i);
if (getName(t).equals(name)) {
return i;
}
}
return -1;
}
}

// End ArrayNamedListImpl.java
7 changes: 2 additions & 5 deletions src/mondrian/olap4j/MondrianOlap4jCellSetAxis.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
package mondrian.olap4j;

import org.olap4j.*;
import org.olap4j.Position;
import org.olap4j.metadata.Hierarchy;
import org.olap4j.metadata.Member;
import org.olap4j.metadata.Property;
import org.olap4j.metadata.*;

import java.util.*;

Expand Down Expand Up @@ -87,7 +84,7 @@ public List<Hierarchy> getHierarchies() {
throw new UnsupportedOperationException();
}

public List<Property> getProperties() {
public NamedList<Property> getProperties() {
throw new UnsupportedOperationException();
}

Expand Down
Loading

0 comments on commit 96d3da3

Please sign in to comment.