Skip to content

Commit

Permalink
Remove restriction on number of query axes; Axis used to be an enum, …
Browse files Browse the repository at this point in the history
…is now an interface.

Deprecated Axis.UNUSED and Axis.NONE.


git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@145 c6a108a4-781c-0410-a6c6-c2d559e19af0
  • Loading branch information
julianhyde committed Feb 20, 2009
1 parent 43546cc commit 49d19e0
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 92 deletions.
171 changes: 133 additions & 38 deletions src/org/olap4j/Axis.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,155 @@
* @version $Id$
* @since Oct 23, 2006
*/
public enum Axis {
UNUSED,
FILTER,
COLUMNS,
ROWS,
PAGES,
CHAPTERS,
SECTIONS;
public interface Axis {

/**
* Returns the ordinal which is to be used for retrieving this axis from
* the {@link org.olap4j.CellSet#getAxes()}, or retrieving its
* coordinate from {@link Cell#getCoordinateList()}.
* Returns the name of this axis, e.g. "COLUMNS", "SLICER", "AXIS(17)".
*
* <p>The axis ordinal is two less than the {@link #ordinal} value which
* every <code>enum</code> value possesses. Hence, {@link #UNUSED} is -2
* and {@link #FILTER} is -1 (because they are not treated the same as the
* other axes), {@link #COLUMNS} is 0, {@link #ROWS} is 1, and so forth.
*
* @return Axis ordinal
* @return Name of the axis
*/
public int axisOrdinal() {
return axisOrdinal;
}
String name();

/**
* Returns localized name for this Axis.
* Returns whether this is the filter (slicer) axis.
*
* @param locale Locale for which to give the name
* @return localized name for this Axis
* @return whether this is the filter axis
*/
public String getCaption(Locale locale) {
// todo: localize
return name();
}
boolean isFilter();

/**
* Returns the axis with a given {@link #axisOrdinal()}.
*
* @param axisOrdinal Axis ordinal
* @return Axis whose {@link #axisOrdinal()} is as given
* @deprecated Will be removed before olap4j 1.0.
*/
public static Axis forOrdinal(int axisOrdinal) {
Axis axis = values()[axisOrdinal + 2];
assert axis.axisOrdinal() == axisOrdinal;
return axis;
public static final Standard UNUSED = null;

/**
* @deprecated Will be removed before olap4j 1.0.
*/
public static final Standard NONE = null;

/**
* Abbreviation for {@link org.olap4j.Axis.Standard#FILTER}.
*/
public static final Standard FILTER = Standard.FILTER;
public static final Standard COLUMNS = Standard.COLUMNS;
public static final Standard ROWS = Standard.ROWS;
public static final Standard PAGES = Standard.PAGES;
public static final Standard SECTIONS = Standard.SECTIONS;
public static final Standard CHAPTERS = Standard.CHAPTERS;

/**
* Enumeration of standard, named axes descriptors.
*/
public enum Standard implements Axis {
/** Filter axis. */
FILTER,

/** COLUMNS axis, also known as X axis and AXIS(0). */
COLUMNS,

/** ROWS axis, also known as Y axis and AXIS(1). */
ROWS,

/** PAGES axis, also known as AXIS(2). */
PAGES,

/** CHAPTERS axis, also known as AXIS(3). */
CHAPTERS,

/** SECTIONS axis, also known as AXIS(4). */
SECTIONS;

public int axisOrdinal() {
return ordinal() - 1;
}

public boolean isFilter() {
return this == FILTER;
}

public String getCaption(Locale locale) {
// TODO: localize
return name();
}
}

private final int axisOrdinal = ordinal() - 2;
class Factory {
private static final Standard[] STANDARD_VALUES = Standard.values();

/**
* Returns the axis with a given {@code axisOrdinal}.
*
* <p>For example, {@code forOrdinal(0)} returns the COLUMNS axis;
* {@code forOrdinal(-1)} returns the SLICER axis;
* {@code forOrdinal(100)} returns AXIS(100).
*
* @param ordinal Axis ordinal
* @return Axis whose ordinal is as given
*/
public static Axis forOrdinal(final int ordinal) {
if (ordinal < -1) {
throw new IllegalArgumentException(
"Axis ordinal must be -1 or higher");
}
if (ordinal + 1 < STANDARD_VALUES.length) {
return STANDARD_VALUES[ordinal + 1];
}
return new Axis() {
public String toString() {
return name();
}

public String name() {
return "AXIS(" + ordinal + ")";
}

public boolean isFilter() {
return false;
}

public int axisOrdinal() {
return ordinal;
}

public String getCaption(Locale locale) {
// TODO: localize
return name();
}
};
}
}

/**
* The largest legal value for {@link #forOrdinal(int)}.
* Returns the ordinal which is to be used for retrieving this axis from
* the {@link org.olap4j.CellSet#getAxes()}, or retrieving its
* coordinate from {@link Cell#getCoordinateList()}.
*
* <p>For example:
* <ul>
* <li>-1 {@link org.olap4j.Axis.Standard#FILTER FILTER}</li>
* <li>0 {@link org.olap4j.Axis.Standard#COLUMNS COLUMNS}</li>
* <li>1 {@link org.olap4j.Axis.Standard#ROWS ROWS}</li>
* <li>2 {@link org.olap4j.Axis.Standard#PAGES PAGES}</li>
* <li>3 {@link org.olap4j.Axis.Standard#CHAPTERS CHAPTERS}</li>
* <li>4 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
* <li>5 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
* <li>6 AXES(6)</li>
* <li>123 AXES(123)</li>
* </ul>
*
* @return ordinal of this axis
*/
int axisOrdinal();

/**
* Returns localized name for this Axis.
*
* <p>Examples: "FILTER", "ROWS", "COLUMNS", "AXIS(10)".
*
* @param locale Locale for which to give the name
* @return localized name for this Axis
*/
public static final int MAX_ORDINAL = SECTIONS.axisOrdinal();
String getCaption(Locale locale);
}

// End Axis.java
18 changes: 6 additions & 12 deletions src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import org.olap4j.impl.Olap4jUtil;
import static org.olap4j.driver.xmla.XmlaOlap4jUtil.*;
import org.olap4j.metadata.*;

import org.w3c.dom.*;
import org.w3c.dom.ls.*;
import org.xml.sax.SAXException;

import java.io.*;
Expand Down Expand Up @@ -178,13 +178,10 @@ void populate() throws OlapException {
final Axis axis = lookupAxis(axisName);
final XmlaOlap4jCellSetAxis cellSetAxis =
new XmlaOlap4jCellSetAxis(this, axis);
switch (axis) {
case FILTER:
if (axis.isFilter()) {
filterAxis = cellSetAxis;
break;
default:
} else {
axisList.add(cellSetAxis);
break;
}
final Element tuplesNode =
findChild(axisNode, MDDATASET_NS, "Tuples");
Expand Down Expand Up @@ -431,13 +428,10 @@ private XmlaOlap4jCellSetMetaData createMetaData(Element root)
axis,
hierarchyList,
propertyList);
switch (axis) {
case FILTER:
if (axis.isFilter()) {
filterAxisMetaData = axisMetaData;
break;
default:
} else {
axisMetaDataList.add(axisMetaData);
break;
}
}
final Element cellInfo =
Expand Down Expand Up @@ -500,7 +494,7 @@ private Axis lookupAxis(String axisName) {
if (axisName.startsWith("Axis")) {
final Integer ordinal =
Integer.valueOf(axisName.substring("Axis".length()));
return Axis.values()[Axis.COLUMNS.ordinal() + ordinal];
return Axis.Factory.forOrdinal(ordinal);
} else {
return Axis.FILTER;
}
Expand Down
11 changes: 8 additions & 3 deletions src/org/olap4j/driver/xmla/XmlaOlap4jCellSetAxis.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ class XmlaOlap4jCellSetAxis implements CellSetAxis {
private final List<Position> immutablePositions =
Collections.unmodifiableList(positions);

/**
* Creates an XmlaOlap4jCellSetAxis.
*
* @param olap4jCellSet Cell set
* @param axis Axis identifier
*/
public XmlaOlap4jCellSetAxis(
XmlaOlap4jCellSet olap4jCellSet,
Axis axis)
Expand All @@ -45,10 +51,9 @@ public CellSet getCellSet() {

public CellSetAxisMetaData getAxisMetaData() {
final CellSetMetaData cellSetMetaData = olap4jCellSet.getMetaData();
switch (axis) {
case FILTER:
if (axis.isFilter()) {
return cellSetMetaData.getFilterAxisMetaData();
default:
} else {
return cellSetMetaData.getAxesMetaData().get(
axis.axisOrdinal());
}
Expand Down
44 changes: 31 additions & 13 deletions src/org/olap4j/mdx/parser/impl/DefaultMdxParser.cup
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ parser code {:
null :
new AxisNode(
filter.getRegion(), false, Axis.FILTER,
Collections.EMPTY_LIST, filter);
Collections.<IdentifierNode>emptyList(), filter);
// sort axes by ordinal
Collections.sort(axisList, new Comparator<AxisNode>() {
public int compare(AxisNode o1, AxisNode o2) {
return o1.getAxis().ordinal() - o2.getAxis().ordinal();
return o1.getAxis().axisOrdinal() - o2.getAxis().axisOrdinal();
}
});
return new SelectNode(
Expand Down Expand Up @@ -277,6 +277,8 @@ terminal
CASE,
CAST,
CELL,
CHAPTERS,
COLUMNS,
DIMENSION,
ELSE,
EMPTY,
Expand All @@ -291,7 +293,10 @@ terminal
NULL,
ON,
OR,
PAGES,
PROPERTIES,
ROWS,
SECTIONS,
SELECT,
SET,
THEN,
Expand Down Expand Up @@ -360,8 +365,9 @@ non terminal IdentifierNode
cube_specification,
member_name,
set_name;
non terminal Axis.Standard
axis_name;
non terminal String
axis_name,
comp_op,
keyword;
non terminal IdentifierNode.Segment
Expand Down Expand Up @@ -1431,25 +1437,25 @@ set_name ::= compound_id ;
// <axis_specification> ::= [NON EMPTY] <set> [<dim_props>] ON <axis_name>
axis_specification ::=
non_empty_opt:b expression:s dim_props_opt:dp ON axis_name:a {:
Axis axis = Axis.valueOf(a.toUpperCase());
ParseRegion region = createRegion(
bleft, bright, sleft, sright, dpleft, dpright, aleft, aright);
RESULT = new AxisNode(region, b, axis, emptyList(dp), s);
RESULT = new AxisNode(region, b, a, emptyList(dp), s);
:}
| non_empty_opt:b expression:s dim_props_opt:dp ON axis_number:n {:
double d = n.doubleValue();
int index = (int)d;

// Legal axis ordinals run from 0 (COLUMS) to 4 (SECTIONS),
// inclusive.
if (index < 0 || index != d || index > Axis.MAX_ORDINAL) {
// AxisOrdinal values go from -2 to 4 for standard axis, but higher
// ordinals are allowed. The negative values represent
// special cases, so are ignored.
if (index < 0 || index != d) {
throw new MdxParseException(
createRegion(nleft, nright),
"Invalid axis specification. The axis number must be an integer between 0 and " +
Axis.MAX_ORDINAL + ", but it was " + d + ".");
"Invalid axis specification. The axis number must be a " +
"non-negative integer, but it was " + d + ".");
}

Axis axis = Axis.forOrdinal(index);
Axis axis = Axis.Factory.forOrdinal(index);
ParseRegion region = createRegion(
bleft, bright, sleft, sright, dpleft, dpright, nleft, nright);
RESULT = new AxisNode(region, b, axis, emptyList(dp), s);
Expand All @@ -1476,8 +1482,20 @@ dim_props_opt ::=
// | SECTIONS
// | AXIS(<index>)
axis_name ::=
identifier:i {:
RESULT = i.getName();
COLUMNS {:
RESULT = Axis.COLUMNS;
:}
| ROWS {:
RESULT = Axis.ROWS;
:}
| PAGES {:
RESULT = Axis.PAGES;
:}
| SECTIONS {:
RESULT = Axis.SECTIONS;
:}
| CHAPTERS {:
RESULT = Axis.CHAPTERS;
:}
;

Expand Down
Loading

0 comments on commit 49d19e0

Please sign in to comment.