Skip to content

Commit 49d19e0

Browse files
committed
Remove restriction on number of query axes; Axis used to be an enum, 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
1 parent 43546cc commit 49d19e0

File tree

8 files changed

+223
-92
lines changed

8 files changed

+223
-92
lines changed

src/org/olap4j/Axis.java

+133-38
Original file line numberDiff line numberDiff line change
@@ -24,60 +24,155 @@
2424
* @version $Id$
2525
* @since Oct 23, 2006
2626
*/
27-
public enum Axis {
28-
UNUSED,
29-
FILTER,
30-
COLUMNS,
31-
ROWS,
32-
PAGES,
33-
CHAPTERS,
34-
SECTIONS;
27+
public interface Axis {
3528

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

5236
/**
53-
* Returns localized name for this Axis.
37+
* Returns whether this is the filter (slicer) axis.
5438
*
55-
* @param locale Locale for which to give the name
56-
* @return localized name for this Axis
39+
* @return whether this is the filter axis
5740
*/
58-
public String getCaption(Locale locale) {
59-
// todo: localize
60-
return name();
61-
}
41+
boolean isFilter();
6242

6343
/**
64-
* Returns the axis with a given {@link #axisOrdinal()}.
65-
*
66-
* @param axisOrdinal Axis ordinal
67-
* @return Axis whose {@link #axisOrdinal()} is as given
44+
* @deprecated Will be removed before olap4j 1.0.
6845
*/
69-
public static Axis forOrdinal(int axisOrdinal) {
70-
Axis axis = values()[axisOrdinal + 2];
71-
assert axis.axisOrdinal() == axisOrdinal;
72-
return axis;
46+
public static final Standard UNUSED = null;
47+
48+
/**
49+
* @deprecated Will be removed before olap4j 1.0.
50+
*/
51+
public static final Standard NONE = null;
52+
53+
/**
54+
* Abbreviation for {@link org.olap4j.Axis.Standard#FILTER}.
55+
*/
56+
public static final Standard FILTER = Standard.FILTER;
57+
public static final Standard COLUMNS = Standard.COLUMNS;
58+
public static final Standard ROWS = Standard.ROWS;
59+
public static final Standard PAGES = Standard.PAGES;
60+
public static final Standard SECTIONS = Standard.SECTIONS;
61+
public static final Standard CHAPTERS = Standard.CHAPTERS;
62+
63+
/**
64+
* Enumeration of standard, named axes descriptors.
65+
*/
66+
public enum Standard implements Axis {
67+
/** Filter axis. */
68+
FILTER,
69+
70+
/** COLUMNS axis, also known as X axis and AXIS(0). */
71+
COLUMNS,
72+
73+
/** ROWS axis, also known as Y axis and AXIS(1). */
74+
ROWS,
75+
76+
/** PAGES axis, also known as AXIS(2). */
77+
PAGES,
78+
79+
/** CHAPTERS axis, also known as AXIS(3). */
80+
CHAPTERS,
81+
82+
/** SECTIONS axis, also known as AXIS(4). */
83+
SECTIONS;
84+
85+
public int axisOrdinal() {
86+
return ordinal() - 1;
87+
}
88+
89+
public boolean isFilter() {
90+
return this == FILTER;
91+
}
92+
93+
public String getCaption(Locale locale) {
94+
// TODO: localize
95+
return name();
96+
}
7397
}
7498

75-
private final int axisOrdinal = ordinal() - 2;
99+
class Factory {
100+
private static final Standard[] STANDARD_VALUES = Standard.values();
101+
102+
/**
103+
* Returns the axis with a given {@code axisOrdinal}.
104+
*
105+
* <p>For example, {@code forOrdinal(0)} returns the COLUMNS axis;
106+
* {@code forOrdinal(-1)} returns the SLICER axis;
107+
* {@code forOrdinal(100)} returns AXIS(100).
108+
*
109+
* @param ordinal Axis ordinal
110+
* @return Axis whose ordinal is as given
111+
*/
112+
public static Axis forOrdinal(final int ordinal) {
113+
if (ordinal < -1) {
114+
throw new IllegalArgumentException(
115+
"Axis ordinal must be -1 or higher");
116+
}
117+
if (ordinal + 1 < STANDARD_VALUES.length) {
118+
return STANDARD_VALUES[ordinal + 1];
119+
}
120+
return new Axis() {
121+
public String toString() {
122+
return name();
123+
}
124+
125+
public String name() {
126+
return "AXIS(" + ordinal + ")";
127+
}
128+
129+
public boolean isFilter() {
130+
return false;
131+
}
132+
133+
public int axisOrdinal() {
134+
return ordinal;
135+
}
136+
137+
public String getCaption(Locale locale) {
138+
// TODO: localize
139+
return name();
140+
}
141+
};
142+
}
143+
}
76144

77145
/**
78-
* The largest legal value for {@link #forOrdinal(int)}.
146+
* Returns the ordinal which is to be used for retrieving this axis from
147+
* the {@link org.olap4j.CellSet#getAxes()}, or retrieving its
148+
* coordinate from {@link Cell#getCoordinateList()}.
149+
*
150+
* <p>For example:
151+
* <ul>
152+
* <li>-1 {@link org.olap4j.Axis.Standard#FILTER FILTER}</li>
153+
* <li>0 {@link org.olap4j.Axis.Standard#COLUMNS COLUMNS}</li>
154+
* <li>1 {@link org.olap4j.Axis.Standard#ROWS ROWS}</li>
155+
* <li>2 {@link org.olap4j.Axis.Standard#PAGES PAGES}</li>
156+
* <li>3 {@link org.olap4j.Axis.Standard#CHAPTERS CHAPTERS}</li>
157+
* <li>4 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
158+
* <li>5 {@link org.olap4j.Axis.Standard#SECTIONS SECTIONS}</li>
159+
* <li>6 AXES(6)</li>
160+
* <li>123 AXES(123)</li>
161+
* </ul>
162+
*
163+
* @return ordinal of this axis
164+
*/
165+
int axisOrdinal();
166+
167+
/**
168+
* Returns localized name for this Axis.
169+
*
170+
* <p>Examples: "FILTER", "ROWS", "COLUMNS", "AXIS(10)".
171+
*
172+
* @param locale Locale for which to give the name
173+
* @return localized name for this Axis
79174
*/
80-
public static final int MAX_ORDINAL = SECTIONS.axisOrdinal();
175+
String getCaption(Locale locale);
81176
}
82177

83178
// End Axis.java

src/org/olap4j/driver/xmla/XmlaOlap4jCellSet.java

+6-12
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import org.olap4j.impl.Olap4jUtil;
1414
import static org.olap4j.driver.xmla.XmlaOlap4jUtil.*;
1515
import org.olap4j.metadata.*;
16+
1617
import org.w3c.dom.*;
17-
import org.w3c.dom.ls.*;
1818
import org.xml.sax.SAXException;
1919

2020
import java.io.*;
@@ -178,13 +178,10 @@ void populate() throws OlapException {
178178
final Axis axis = lookupAxis(axisName);
179179
final XmlaOlap4jCellSetAxis cellSetAxis =
180180
new XmlaOlap4jCellSetAxis(this, axis);
181-
switch (axis) {
182-
case FILTER:
181+
if (axis.isFilter()) {
183182
filterAxis = cellSetAxis;
184-
break;
185-
default:
183+
} else {
186184
axisList.add(cellSetAxis);
187-
break;
188185
}
189186
final Element tuplesNode =
190187
findChild(axisNode, MDDATASET_NS, "Tuples");
@@ -431,13 +428,10 @@ private XmlaOlap4jCellSetMetaData createMetaData(Element root)
431428
axis,
432429
hierarchyList,
433430
propertyList);
434-
switch (axis) {
435-
case FILTER:
431+
if (axis.isFilter()) {
436432
filterAxisMetaData = axisMetaData;
437-
break;
438-
default:
433+
} else {
439434
axisMetaDataList.add(axisMetaData);
440-
break;
441435
}
442436
}
443437
final Element cellInfo =
@@ -500,7 +494,7 @@ private Axis lookupAxis(String axisName) {
500494
if (axisName.startsWith("Axis")) {
501495
final Integer ordinal =
502496
Integer.valueOf(axisName.substring("Axis".length()));
503-
return Axis.values()[Axis.COLUMNS.ordinal() + ordinal];
497+
return Axis.Factory.forOrdinal(ordinal);
504498
} else {
505499
return Axis.FILTER;
506500
}

src/org/olap4j/driver/xmla/XmlaOlap4jCellSetAxis.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ class XmlaOlap4jCellSetAxis implements CellSetAxis {
2727
private final List<Position> immutablePositions =
2828
Collections.unmodifiableList(positions);
2929

30+
/**
31+
* Creates an XmlaOlap4jCellSetAxis.
32+
*
33+
* @param olap4jCellSet Cell set
34+
* @param axis Axis identifier
35+
*/
3036
public XmlaOlap4jCellSetAxis(
3137
XmlaOlap4jCellSet olap4jCellSet,
3238
Axis axis)
@@ -45,10 +51,9 @@ public CellSet getCellSet() {
4551

4652
public CellSetAxisMetaData getAxisMetaData() {
4753
final CellSetMetaData cellSetMetaData = olap4jCellSet.getMetaData();
48-
switch (axis) {
49-
case FILTER:
54+
if (axis.isFilter()) {
5055
return cellSetMetaData.getFilterAxisMetaData();
51-
default:
56+
} else {
5257
return cellSetMetaData.getAxesMetaData().get(
5358
axis.axisOrdinal());
5459
}

src/org/olap4j/mdx/parser/impl/DefaultMdxParser.cup

+31-13
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,11 @@ parser code {:
155155
null :
156156
new AxisNode(
157157
filter.getRegion(), false, Axis.FILTER,
158-
Collections.EMPTY_LIST, filter);
158+
Collections.<IdentifierNode>emptyList(), filter);
159159
// sort axes by ordinal
160160
Collections.sort(axisList, new Comparator<AxisNode>() {
161161
public int compare(AxisNode o1, AxisNode o2) {
162-
return o1.getAxis().ordinal() - o2.getAxis().ordinal();
162+
return o1.getAxis().axisOrdinal() - o2.getAxis().axisOrdinal();
163163
}
164164
});
165165
return new SelectNode(
@@ -277,6 +277,8 @@ terminal
277277
CASE,
278278
CAST,
279279
CELL,
280+
CHAPTERS,
281+
COLUMNS,
280282
DIMENSION,
281283
ELSE,
282284
EMPTY,
@@ -291,7 +293,10 @@ terminal
291293
NULL,
292294
ON,
293295
OR,
296+
PAGES,
294297
PROPERTIES,
298+
ROWS,
299+
SECTIONS,
295300
SELECT,
296301
SET,
297302
THEN,
@@ -360,8 +365,9 @@ non terminal IdentifierNode
360365
cube_specification,
361366
member_name,
362367
set_name;
368+
non terminal Axis.Standard
369+
axis_name;
363370
non terminal String
364-
axis_name,
365371
comp_op,
366372
keyword;
367373
non terminal IdentifierNode.Segment
@@ -1431,25 +1437,25 @@ set_name ::= compound_id ;
14311437
// <axis_specification> ::= [NON EMPTY] <set> [<dim_props>] ON <axis_name>
14321438
axis_specification ::=
14331439
non_empty_opt:b expression:s dim_props_opt:dp ON axis_name:a {:
1434-
Axis axis = Axis.valueOf(a.toUpperCase());
14351440
ParseRegion region = createRegion(
14361441
bleft, bright, sleft, sright, dpleft, dpright, aleft, aright);
1437-
RESULT = new AxisNode(region, b, axis, emptyList(dp), s);
1442+
RESULT = new AxisNode(region, b, a, emptyList(dp), s);
14381443
:}
14391444
| non_empty_opt:b expression:s dim_props_opt:dp ON axis_number:n {:
14401445
double d = n.doubleValue();
14411446
int index = (int)d;
14421447

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

1452-
Axis axis = Axis.forOrdinal(index);
1458+
Axis axis = Axis.Factory.forOrdinal(index);
14531459
ParseRegion region = createRegion(
14541460
bleft, bright, sleft, sright, dpleft, dpright, nleft, nright);
14551461
RESULT = new AxisNode(region, b, axis, emptyList(dp), s);
@@ -1476,8 +1482,20 @@ dim_props_opt ::=
14761482
// | SECTIONS
14771483
// | AXIS(<index>)
14781484
axis_name ::=
1479-
identifier:i {:
1480-
RESULT = i.getName();
1485+
COLUMNS {:
1486+
RESULT = Axis.COLUMNS;
1487+
:}
1488+
| ROWS {:
1489+
RESULT = Axis.ROWS;
1490+
:}
1491+
| PAGES {:
1492+
RESULT = Axis.PAGES;
1493+
:}
1494+
| SECTIONS {:
1495+
RESULT = Axis.SECTIONS;
1496+
:}
1497+
| CHAPTERS {:
1498+
RESULT = Axis.CHAPTERS;
14811499
:}
14821500
;
14831501

0 commit comments

Comments
 (0)