Skip to content

Commit

Permalink
MONDRIAN: Fix bug in ParallelPeriod when passed a null member.
Browse files Browse the repository at this point in the history
 Add boolean attribute 'visible' to <Measure> and <CalculatedMember>.
 Document its use.

[git-p4: depot-paths = "//open/mondrian/": change = 3132]
  • Loading branch information
julianhyde committed Feb 3, 2005
1 parent be471df commit a991d79
Show file tree
Hide file tree
Showing 9 changed files with 276 additions and 61 deletions.
16 changes: 14 additions & 2 deletions demo/FoodMart.xml
Expand Up @@ -5,7 +5,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.
== (C) Copyright 2000-2004 Kana Software, Inc. and others.
== (C) Copyright 2000-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 @@ -196,9 +196,21 @@ lname
<CalculatedMember
name="Profit"
dimension="Measures"
formula="[Measures].[Store Sales]-[Measures].[Store Cost]">
formula="[Measures].[Store Sales] - [Measures].[Store Cost]">
<CalculatedMemberProperty name="FORMAT_STRING" value="$#,##0.00"/>
</CalculatedMember>
<CalculatedMember
name="Profit last Period"
dimension="Measures"
formula="([Measures].[Profit], ParallelPeriod())"
visible="false"/>
<CalculatedMember
name="Profit growth"
dimension="Measures"
formula="([Measures].[Profit] - [Measures].[Profit last Period]) / [Measures].[Profit last Period]"
visible="true">
<CalculatedMemberProperty name="FORMAT_STRING" value="0.0%"/>
</CalculatedMember>
</Cube>

<Cube name="Warehouse">
Expand Down
74 changes: 55 additions & 19 deletions doc/schema.html
Expand Up @@ -4,7 +4,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-2004 Kana Software, Inc. and others.
== Copyright (C) 2001-2005 Kana Software, Inc. and others.
== All Rights Reserved.
== You must accept the terms of that agreement to use this software.
== jhyde, 24 September, 2002
Expand All @@ -21,7 +21,7 @@

<body>
<h1>How to design a Mondrian schema</h1>
<p>Julian Hyde; last updated December, 2004.</p>
<p>Julian Hyde; last updated February, 2005.</p>
<h2>Contents</h2>
<ol>
<li><a href="#What_is_a_schema">What is a schema?</a></li>
Expand Down Expand Up @@ -204,37 +204,37 @@ <h3><a name="Measures">Measures</a></h3>
&lt;<a href="#XML_Measure">Measure</a> name=&quot;Store Sales&quot; column=&quot;store_sales&quot;
aggregator=&quot;sum&quot; formatString=&quot;#,###.00&quot;/&gt;</pre>
</blockquote>
<p dir="ltr">Each measure (see <a href="#XML_Measure">&lt;Measure&gt;</a>) has a name,
<p>Each measure (see <a href="#XML_Measure">&lt;Measure&gt;</a>) has a name,
a column in the fact table, and an <code>aggregator</code>. The aggregator is usually &quot;sum&quot;,
but &quot;count&quot;, &quot;mix&quot;, &quot;max&quot;, &quot;avg&quot;, and &quot;distinct count&quot; are also allowed;
&quot;distinct count&quot; has some limitations if your cube contains a
<a href="#Parent_child_hierarchies">parent-child hierarchy</a>.</p>

<p dir="ltr">An optional <code>formatString</code> attribute specifies how the value is to
<p>An optional <code>formatString</code> attribute specifies how the value is to
be printed. Here, we have chosen to output unit sales with no decimal places
(since it is an integer), and store sales with two decimal places (since it is a
currency value). The ',' and '.' symbols are locale-sensitive, so if you were
running in Italian, store sales might appear as &quot;48.123,45&quot;. You can achieve
even more wild effects using <a href="#Format_strings">advanced format strings</a>.</p>
<p dir="ltr">A measure can have a caption attribute to be returned by getCaption() instead of the name.
<p>A measure can have a caption attribute to be returned by getCaption() instead of the name.
Defining a specific caption does make sense if special letters (e.g. &#931; or &#928;) are to be displayed.</p>
<blockquote>
<pre>&lt;<a href="#XML_Measure">Measure</a> name=&quot;Sum X&quot; column=&quot;sum_x&quot; aggregator=&quot;sum&quot; caption=&quot;&amp;#931; X&quot;/&gt;
</blockquote>
<p dir="ltr">Rather than coming from a column, a measure can use a
<p>Rather than coming from a column, a measure can use a
<a href="#Cell_readers">cell reader</a>.</p>
<p dir="ltr">In order to provide a specific formatting of the cell values, a measure can use a
<p>In order to provide a specific formatting of the cell values, a measure can use a
<a href="#Cell_formatter">cell formatter</a>.</p>

<h3 dir="ltr"><a name="Calculated_members">Calculated members</a></h3>
<h3><a name="Calculated_members">Calculated members</a></h3>

<p dir="ltr">Suppose you want to create a measure whose value comes not from a
<p>Suppose you want to create a measure whose value comes not from a
column of the fact table, but from an MDX formula. One way to do this is to use
a WITH MEMBER clause, like this:</p>

<blockquote>

<p dir="ltr"><code>with member [Measures].[Profit] as '[Measures].[Store
<p><code>with member [Measures].[Profit] as '[Measures].[Store
Sales]-[Measures].[Store Cost]',<br>
&nbsp;&nbsp; FORMAT_STRING = '$#,###'<br>
select {[Measures].[Store Sales], [Measures].[Profit]} on columns,<br>
Expand Down Expand Up @@ -270,6 +270,42 @@ <h3 dir="ltr"><a name="Calculated_members">Calculated members</a></h3>
'$#,##0.00')&quot;/&gt;</code></p>
</blockquote>

<p>You can make a calculated member or a measure invisible. If you specify <code>
visible=&quot;false&quot;</code> (the default is &quot;true&quot;) in the <code>&lt;<a href="#XML_Measure">Measure</a>&gt;
or &lt;<a href="#XML_CalculatedMember">CalculatedMember</a>&gt;</code> element,
user-interfaces such as JPivot will notice this property and hide the member.
This is useful if you want to perform calculations in a number of steps, and
hide intermediate steps from end-users. For example, here only &quot;Margin per Sqft&quot;
is visible, and its factors &quot;Store Cost&quot;, &quot;Margin&quot; and &quot;Store Sqft&quot; are hidden:</p>

<blockquote>

<p><code>&lt;<a href="#XML_Measure">Measure</a><br>
&nbsp;&nbsp;&nbsp; name=&quot;Store Cost&quot;<br>
&nbsp;&nbsp;&nbsp; column=&quot;store_cost&quot;<br>
&nbsp;&nbsp;&nbsp; aggregator=&quot;sum&quot;<br>
&nbsp;&nbsp;&nbsp; formatString=&quot;#,###.00&quot;<br>
&nbsp;&nbsp;&nbsp; visible=&quot;false&quot;/&gt;<br>
&lt;<a href="#XML_CalculatedMember">CalculatedMember</a><br>
&nbsp;&nbsp;&nbsp; name=&quot;Margin&quot; <br>
&nbsp;&nbsp;&nbsp; dimension=&quot;Measures&quot; <br>
&nbsp;&nbsp;&nbsp; visible=&quot;false&quot;<br>
&nbsp;&nbsp;&nbsp; formula=&quot;([Measures].[Store Sales] - [Measures].[Store Cost])
/ [Measures].[Store Cost]&quot;/&gt;<br>
&lt;<a href="#XML_CalculatedMember">CalculatedMember</a><br>
&nbsp;&nbsp;&nbsp; name=&quot;Store Sqft&quot; <br>
&nbsp;&nbsp;&nbsp; dimension=&quot;Measures&quot;<br>
&nbsp;&nbsp;&nbsp; visible=&quot;false&quot;<br>
&nbsp;&nbsp;&nbsp; formula='[Store].Properties(&quot;Sqft&quot;)'/&gt;<br>
&lt;<a href="#XML_CalculatedMember">CalculatedMember</a><br>
&nbsp;&nbsp;&nbsp; name=&quot;Margin per Sqft&quot;<br>
&nbsp;&nbsp;&nbsp; dimension=&quot;Measures&quot;<br>
&nbsp;&nbsp;&nbsp; visible=&quot;true&quot;<br>
&nbsp;&nbsp;&nbsp; formula=&quot;[Measures].[Margin] / [Measures].[Store Cost]&quot;&gt;<br>
&nbsp; &lt;<a href="#XML_CalculatedMemberProperty">CalculatedMemberProperty</a> name=&quot;FORMAT_STRING&quot; value=&quot;$#,##0.00&quot;/&gt;<br>
&lt;/<a href="#XML_CalculatedMember">CalculatedMember</a>&gt;</code></p>
</blockquote>

<h3><a name="Dimensions,_Hierarchies,_Levels">Dimensions, Hierarchies, Levels</a></h3>
<p>The Gender dimension consists of a single hierarchy, which has just one
level.</p>
Expand Down Expand Up @@ -867,17 +903,17 @@ <h3><a name="Member_properties">Member properties</a></h3><p>Member properties a
&nbsp;&nbsp;&nbsp; &lt;<a href="#XML_Parameter">Parameter</a> name=&quot;expression&quot; value=&quot;not used&quot;/&gt;
&nbsp; &lt;/<a href="#XML_Hierarchy">Hierarchy</a>&gt;
&lt;/<a href="#XML_Dimension">Dimension</a>&gt;
</pre></blockquote><h3><a name="Cell_readers">Cell readers</a></h3><p dir="ltr">Not implemented yet. Syntax would be something like</p><blockquote>
<pre dir="ltr">&lt;<a href="#XML_Measure">Measure</a> name=&quot;name&quot; cellReaderClass=&quot;com.foo.MyCellReader&quot;&gt;</pre></blockquote><p>and the class &quot;com.foo.MyCellReader&quot; would have to implement <code>
</pre></blockquote><h3><a name="Cell_readers">Cell readers</a></h3><p>Not implemented yet. Syntax would be something like</p><blockquote>
<pre>&lt;<a href="#XML_Measure">Measure</a> name=&quot;name&quot; cellReaderClass=&quot;com.foo.MyCellReader&quot;&gt;</pre></blockquote><p>and the class &quot;com.foo.MyCellReader&quot; would have to implement <code>
<a href="http://mondrian.sourceforge.net/api/mondrian/olap/CellReader.html">
interface mondrian.olap.CellReader</a></code>.</p><h3><a name="Cell_formatter">Cell formatter</a></h3><p dir="ltr">A cell formatter attribute demotes a java class to format the cell value
interface mondrian.olap.CellReader</a></code>.</p><h3><a name="Cell_formatter">Cell formatter</a></h3><p>A cell formatter attribute demotes a java class to format the cell value
being displayed by
<code><a href="http://mondrian.sourceforge.net/api/mondrian/olap/Cell.html#getFormattedValue()">getFormattedValue()</a></code>.</p><blockquote>
<pre dir="ltr">&lt;<a href="#XML_Measure">Measure</a> name=&quot;name&quot; formatter=&quot;com.foo.MyCellFormatter&quot;/&gt;</pre></blockquote><p>The class &quot;com.foo.MyCellFormatter&quot; would have to implement <code>
<pre>&lt;<a href="#XML_Measure">Measure</a> name=&quot;name&quot; formatter=&quot;com.foo.MyCellFormatter&quot;/&gt;</pre></blockquote><p>The class &quot;com.foo.MyCellFormatter&quot; would have to implement <code>
<a href="http://mondrian.sourceforge.net/api/mondrian/olap/CellFormatter.html">
interface mondrian.olap.CellFormatter</a></code>.</p><h3><a name="Member_formatter">Member formatter</a></h3><p>A member formatter attribute demotes a java class to format a member's display value
returned by <code><a href="http://mondrian.sourceforge.net/api/mondrian/olap/Member.html#getCaption()">getCaption()</a></code>.</p><blockquote>
<pre dir="ltr">&lt;<a href="#XML_Level">Level</a> column=&quot;column&quot; name=&quot;name&quot; formatter=&quot;com.foo.MyMemberFormatter&quot;/&gt;</pre></blockquote><p>The class &quot;com.foo.MyMemberFormatter&quot; would have to implement <code>
<pre>&lt;<a href="#XML_Level">Level</a> column=&quot;column&quot; name=&quot;name&quot; formatter=&quot;com.foo.MyMemberFormatter&quot;/&gt;</pre></blockquote><p>The class &quot;com.foo.MyMemberFormatter&quot; would have to implement <code>
<a href="http://mondrian.sourceforge.net/api/mondrian/olap/MemberFormatter.html">
interface mondrian.olap.MemberFormatter</a></code>.</p><h3><a name="I18n">Internationalization</a></h3><p>Internationalized applications based on Mondrian could use multiple, language dependent schemas.<br/>
If so, the MDX statements would be language dependent too. This might be more difficult to maintain.<br/>
Expand All @@ -899,7 +935,7 @@ <h3><a name="Member_properties">Member properties</a></h3><p>Member properties a
you might use <code>caption</code>, <code>allMemberCaption</code>, <code>measuresCaption</code> attributes as follows.

<blockquote>
<pre dir="ltr">&lt;<a href="#XML_Schema">Schema</a> measuresCaption=&quot;${MEASURESCAPTION}&quot;&gt;</pre><pre dir="ltr">&lt;<a href="#XML_Dimension">Dimension</a> name=&quot;Gender&quot; foreignKey=&quot;customer_id&quot; caption=&quot;${GENDER}&quot;&gt;</pre><pre dir="ltr">&lt;<a href="#XML_Hierarchy">Hierarchy</a> hasAll=&quot;true&quot; allMemberName=&quot;All Genders&quot; primaryKey=&quot;customer_id&quot; allMemberCaption=&quot;${ALLGENDER}&quot;&gt;</pre><pre dir="ltr">&lt;<a href="#XML_Level">Level</a> name=&quot;Gender&quot; column=&quot;gender&quot; uniqueMembers=&quot;true&quot; caption=&quot;${GENDER}&quot;&gt;</pre><pre dir="ltr">&lt;<a href="#XML_Measure">Measure</a> name=&quot;Unit Sales&quot; column=&quot;unit_sales&quot; caption=&quot;${UNITSALES}&quot;&gt;</pre></blockquote>A hierarchy with no <code>caption</code> defined would inherit the <code>caption</code> attribute from the dimension parent.
<pre>&lt;<a href="#XML_Schema">Schema</a> measuresCaption=&quot;${MEASURESCAPTION}&quot;&gt;</pre><pre>&lt;<a href="#XML_Dimension">Dimension</a> name=&quot;Gender&quot; foreignKey=&quot;customer_id&quot; caption=&quot;${GENDER}&quot;&gt;</pre><pre>&lt;<a href="#XML_Hierarchy">Hierarchy</a> hasAll=&quot;true&quot; allMemberName=&quot;All Genders&quot; primaryKey=&quot;customer_id&quot; allMemberCaption=&quot;${ALLGENDER}&quot;&gt;</pre><pre>&lt;<a href="#XML_Level">Level</a> name=&quot;Gender&quot; column=&quot;gender&quot; uniqueMembers=&quot;true&quot; caption=&quot;${GENDER}&quot;&gt;</pre><pre>&lt;<a href="#XML_Measure">Measure</a> name=&quot;Unit Sales&quot; column=&quot;unit_sales&quot; caption=&quot;${UNITSALES}&quot;&gt;</pre></blockquote>A hierarchy with no <code>caption</code> defined would inherit the <code>caption</code> attribute from the dimension parent.
</p>
<h2><a name="Access_control">Access-control</a></h2><p>You've got all this great data, but you don't everyone to be able to read all
of it. You can define an access-control profile, called a Role, as part of the
Expand Down Expand Up @@ -971,13 +1007,13 @@ <h2><a name="Access_control">Access-control</a></h2><p>You've got all this great
Role</a> for more details), or look
one up using the method
<a href="http://mondrian.sourceforge.net/api/mondrian/olap/Schema.html#lookupRole(java.lang.String)">
Schema.lookupRole(String)</a>.</li></ol><h2><a name="Other_stuff">Other stuff</a></h2><h3 dir="ltr"><a name="Format_strings">Format strings</a></h3><p dir="ltr">Format strings use Visual Basic formatting syntax, see
Schema.lookupRole(String)</a>.</li></ol><h2><a name="Other_stuff">Other stuff</a></h2><h3><a name="Format_strings">Format strings</a></h3><p>Format strings use Visual Basic formatting syntax, see
<a href="http://mondrian.sourceforge.net/api/mondrian/olap/Format.html">class
mondrian.olap.Format</a> for more details. </p>

<p dir="ltr">A measure's format string is usually a fixed string, but it really
<p>A measure's format string is usually a fixed string, but it really
an expression, which is evaluated in the same context as the cell. You can
therefore change the formatting of a cell depending upon the cell's value.</p><p dir="ltr"><i>todo</i>: example of expression format string to do
therefore change the formatting of a cell depending upon the cell's value.</p><p><i>todo</i>: example of expression format string to do
traffic-lighting</p><h2><a name="Appendix_A_XML_elements">Appendix A: XML elements</a></h2><table border="2" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber2">
<tr>
<th>Element</th><th>Description</th></tr><tr>
Expand Down
17 changes: 14 additions & 3 deletions src/main/mondrian/olap/Mondrian.xml
Expand Up @@ -5,7 +5,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-2004 Kana Software, Inc. and others.
== Copyright (C) 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 @@ -546,8 +546,6 @@ Revision is $Id$
A string being displayed instead of the name.
</Doc>
</Attribute>


</Element>

<Element type="Measure">
Expand Down Expand Up @@ -583,6 +581,13 @@ Revision is $Id$
A string being displayed instead of the name.
</Doc>
</Attribute>
<Attribute name="visible" type="Boolean" required="false">
<Doc>
Whether this member is visible in the user-interface.
Default true.
</Doc>
</Attribute>
<Array name="memberProperties" type="CalculatedMemberProperty" min="0"/>
</Element>

<Element type="CalculatedMember">
Expand Down Expand Up @@ -612,6 +617,12 @@ Revision is $Id$
Name of the dimension which this member belongs to.
</Doc>
</Attribute>
<Attribute name="visible" type="Boolean" required="false">
<Doc>
Whether this member is visible in the user-interface.
Default true.
</Doc>
</Attribute>
<Array name="memberProperties" type="CalculatedMemberProperty" min="0"/>
</Element>

Expand Down
8 changes: 7 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-2003 Kana Software, Inc. and others.
// Copyright (C) 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 @@ -48,6 +48,12 @@ public abstract class Property {
public static final String PROPERTY_FORMATTED_VALUE = "FORMATTED_VALUE";
/** Cell property for XML/A. */
public static final String PROPERTY_FORMAT_STRING = "FORMAT_STRING";
/**
* Name of the system property which determines whether to show a member
* (especially a measure or calculated member) in a user interface such as
* JPivot.
*/
public static final String PROPERTY_VISIBLE = "$visible";
/**
* A list of the names of properties which have special meaning to the
* Mondrian system.
Expand Down
9 changes: 6 additions & 3 deletions src/main/mondrian/olap/fun/FunUtil.java
Expand Up @@ -563,7 +563,7 @@ static void toPercent (List members, HashMap mapMemberToValue) {
if (o instanceof Number) {
double d = ((Number) o).doubleValue();
mapMemberToValue.put(
member,
member,
new Double(d / total * (double) 100));
}
}
Expand Down Expand Up @@ -908,8 +908,8 @@ private static Object _var(SetWrapper sw, boolean biased) {
stdev += Math.pow((((Double) sw.v.get(i)).doubleValue() - avg),2);
}
int n = sw.v.size();
if (!biased) {
n--;
if (!biased) {
n--;
}
return new Double(stdev / (double) n);
}
Expand Down Expand Up @@ -1132,6 +1132,9 @@ static List memberRange(Evaluator evaluator, Member startMember, Member endMembe
* <code>ancestorMember</code> as <code>member</code> is under its parent.
*/
static Member cousin(SchemaReader schemaReader, Member member, Member ancestorMember) {
if (ancestorMember.isNull()) {
return ancestorMember;
}
if (member.getHierarchy() != ancestorMember.getHierarchy()) {
throw MondrianResource.instance().newCousinHierarchyMismatch(
member.getUniqueName(), ancestorMember.getUniqueName());
Expand Down

0 comments on commit a991d79

Please sign in to comment.