001/*
002// $Id: Member.java 482 2012-01-05 23:27:27Z jhyde $
003//
004// Licensed to Julian Hyde under one or more contributor license
005// agreements. See the NOTICE file distributed with this work for
006// additional information regarding copyright ownership.
007//
008// Julian Hyde licenses this file to you under the Apache License,
009// Version 2.0 (the "License"); you may not use this file except in
010// compliance with the License. You may obtain a copy of the License at:
011//
012// http://www.apache.org/licenses/LICENSE-2.0
013//
014// Unless required by applicable law or agreed to in writing, software
015// distributed under the License is distributed on an "AS IS" BASIS,
016// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017// See the License for the specific language governing permissions and
018// limitations under the License.
019*/
020package org.olap4j.metadata;
021
022import org.olap4j.OlapException;
023import org.olap4j.mdx.ParseTreeNode;
024
025import java.util.List;
026
027/**
028 * <code>Member</code> is a data value in an OLAP Dimension.
029 *
030 * @author jhyde
031 * @version $Id: Member.java 482 2012-01-05 23:27:27Z jhyde $
032 * @since Aug 22, 2006
033 */
034public interface Member extends MetadataElement {
035    /**
036     * Returns the children of this Member, indexed by name.
037     *
038     * <p>If access-control is in place, the list does not contain inaccessible
039     * children.
040     *
041     * <p>If the member has no children, returns an empty list: the result is
042     * never null.
043     *
044     * <p>The caller should assume that the list is immutable;
045     * if the caller modifies the list, behavior is undefined.</p>
046     *
047     * @see org.olap4j.OlapDatabaseMetaData#getMembers
048     *
049     * @return children of this member
050     *
051     * @throws OlapException if database error occurs
052     */
053    NamedList<? extends Member> getChildMembers() throws OlapException;
054
055    /**
056     * Returns the number of children this Member has.
057     *
058     * <p>This method has the same effect as
059     * <code>getChildMembers().size()</code>, but is typically less expensive.
060     *
061     * @return number of children
062     *
063     * @throws OlapException if database error occurs
064     */
065    int getChildMemberCount() throws OlapException;
066
067    /**
068     * Returns the parent of this Member, or null if it has no parent.
069     *
070     * @return Parent member, or null if member has no parent
071     */
072    Member getParentMember();
073
074    /**
075     * Returns the Level of this Member.
076     *
077     * <p>Never returns null.</p>
078     *
079     * @return Level which this Member belongs to
080     */
081    Level getLevel();
082
083    /**
084     * Returns the Hierarchy of this Member.
085     *
086     * <p>Never returns null.
087     * Result is always the same as <code>getLevel().getHierarchy()</code>.
088     *
089     * @return Hierarchy which this Member belongs to
090     */
091    Hierarchy getHierarchy();
092
093    /**
094     * Returns the Dimension of this Member.
095     *
096     * <p>Never returns null. Result is always the same as
097     * <code>getLevel().getHierarchy().getDimension()</code>.
098     *
099     * @return Dimension which this Member belongs to
100     */
101    Dimension getDimension();
102
103    /**
104     * Returns the type of this Member.
105     *
106     * <p>Never returns null.</p>
107     *
108     * @return What kind of member this is
109     */
110    Type getMemberType();
111
112    /**
113     * Returns whether this Member represents the aggregation of all members
114     * in its Dimension.
115     *
116     * <p>An 'all' member is always the root of its Hierarchy; that is,
117     * its parent member is the null member, and
118     * {@link Hierarchy#getRootMembers()} returns the 'all'
119     * member and no others. Some hierarchies do not have an 'all' member.
120     *
121     * @see Hierarchy#hasAll()
122     *
123     * @return whether this Member is the 'all' member of its Dimension
124     */
125    boolean isAll();
126
127    /**
128     * Enumeration of types of members.
129     *
130     * <p>The values are as specified by XMLA,
131     * plus the additional {@link #NULL} value not used by XMLA.
132     * For example, XMLA specifies <code>MDMEMBER_TYPE_REGULAR</code> with
133     * ordinal 1, which corresponds to value {@link #REGULAR}.
134     *
135     * <p>The {@link #FORMULA} value takes precedence over {@link #MEASURE}.
136     * For example, if there is a formula (calculated) member on the Measures
137     * dimension, it is listed as <code>FORMULA</code>.
138     */
139    enum Type {
140        UNKNOWN(0),
141        REGULAR(1),
142        ALL(2),
143        MEASURE(3),
144        FORMULA(4),
145        /**
146         * Indicates that this member is its hierarchy's NULL member (such as is
147         * returned by the expression
148         * <code>[Gender]&#46;[All Gender]&#46;PrevMember</code>, for example).
149         */
150        NULL(5);
151
152        private Type(int ordinal) {
153            assert ordinal == ordinal();
154        }
155    }
156
157    /**
158     * Returns whether <code>member</code> is equal to, a child of, or a
159     * descendent of this Member.
160     *
161     * @param member Member
162     * @return Whether the given Member is a descendent of this Member
163     */
164    boolean isChildOrEqualTo(Member member);
165
166    /**
167     * Returns whether this member is calculated using a formula.
168     *
169     * <p>Examples of calculated members include
170     * those defined using a <code>WITH MEMBER</code> clause in an MDX query
171     * ({@link #getMemberType()} will return {@link Type#FORMULA} for these),
172     *  or a calculated member defined in a cube.
173     *
174     * @return Whether this Member is calculated
175     *
176     * @see #isCalculatedInQuery()
177     */
178    boolean isCalculated();
179
180    /**
181     * Returns the solve order of this member in a formula.
182     *
183     * @return solve order of this Member
184     */
185    int getSolveOrder();
186
187    /**
188     * Expression by which this member is derived, if it is a calculated
189     * member. If the member is not calulated, returns null.
190     *
191     * @return expression for this member
192     */
193    ParseTreeNode getExpression();
194
195    /**
196     * Returns array of all members which are ancestor to <code>this</code>.
197     *
198     * @return ancestor Members
199     */
200    List<Member> getAncestorMembers();
201
202    /**
203     * Returns whether this member is computed from a <code>WITH MEMBER</code>
204     * clause in an MDX query. (Calculated members can also be calculated in a
205     * cube.)
206     *
207     * @return Whether this member is calculated in a query
208     *
209     * @see #isCalculated()
210     */
211    boolean isCalculatedInQuery();
212
213    /**
214     * Returns the value of a given property.
215     *
216     * <p>Returns null if the property is not set.</p>
217     *
218     * <p>Every member has certain system properties such as "name" and
219     * "caption" (the full list is described in the
220     * {@link org.olap4j.metadata.Property.StandardMemberProperty}
221     * enumeration), as well as extra properties defined for its Level
222     * (see {@link Level#getProperties()}).</p>
223     *
224     * @param property Property
225     *
226     * @return formatted value of the given property
227     *
228     * @see #getPropertyFormattedValue(Property)
229     *
230     * @throws OlapException if database error occurs
231     */
232    Object getPropertyValue(Property property) throws OlapException;
233
234    /**
235     * Returns the formatted value of a given property.
236     *
237     * <p>Returns null if the property is not set.</p>
238     *
239     * <p>Every member has certain system properties such as "name" and
240     * "caption" (the full list is described in the
241     * {@link org.olap4j.metadata.Property.StandardMemberProperty}
242     * enumeration), as well as extra properties defined for its Level
243     * (see {@link Level#getProperties()}).</p>
244     *
245     * @param property Property
246     *
247     * @return formatted value of the given property
248     *
249     * @see #getPropertyValue(Property)
250     *
251     * @throws OlapException if database error occurs
252     */
253    String getPropertyFormattedValue(Property property) throws OlapException;
254
255    /**
256     * Sets a property of this member to a given value.
257     *
258     * <p>Every member has certain system properties such as "name" and
259     * "caption" (the full list is described in the
260     * {@link org.olap4j.metadata.Property.StandardMemberProperty}
261     * enumeration), as well as extra properties defined for its Level
262     * (see {@link Level#getProperties()}).</p>
263     *
264     * @param property property
265     *
266     * @param value Property value
267     *
268     * @throws OlapException if the value not valid for this property
269     *   (for example, a String value assigned to a Boolean property)
270     */
271    void setProperty(Property property, Object value) throws OlapException;
272
273    /**
274     * Returns the definitions of the properties this member may have.
275     *
276     * <p>For many providers, properties are defined against a Level, so result
277     * of this method will be identical to
278     * <code>member.getLevel().{@link Level#getProperties() getProperties}()</code>.
279     *
280     * @return properties of this Member
281     */
282    NamedList<Property> getProperties();
283
284    /**
285     * Returns the ordinal of the member.
286     *
287     * @return ordinal of this Member
288     */
289    int getOrdinal();
290
291    /**
292     * Returns whether this member is 'hidden', as per the rules which define
293     * a ragged hierarchy.
294     *
295     * @return whether this member is a hidden member of a ragged hierarchy
296     */
297    boolean isHidden();
298
299    /**
300     * Returns the depth of this member.
301     *
302     * <p>In regular hierarchies, this is as the same as the level's depth,
303     * but in parent-child and ragged hierarchies the value may be
304     * different.</p>
305     *
306     * @return depth of this Member
307     */
308    int getDepth();
309
310    /**
311     * Returns the system-generated data member that is associated with a
312     * non-leaf member of a dimension.
313     *
314     * <p>Returns this member if this member is a leaf member, or if the
315     * non-leaf member does not have an associated data member.</p>
316     *
317     * @return system-generated data member
318     */
319    Member getDataMember();
320
321    /**
322     * Enumeration of tree operations which can be used when querying
323     * members.
324     *
325     * <p>Some of the values are as specified by XMLA.
326     * For example, XMLA specifies MDTREEOP_CHILDREN with ordinal 1,
327     * which corresponds to the value {@link #CHILDREN}.
328     *
329     * @see org.olap4j.OlapDatabaseMetaData#getMembers
330     */
331    public enum TreeOp implements XmlaConstant {
332        /**
333         * Tree operation which returns only the immediate children.
334         */
335        CHILDREN(
336            1,
337            "Tree operation which returns only the immediate children."),
338
339        /**
340         * Tree operation which returns members on the same level.
341         */
342        SIBLINGS(
343            2,
344            "Tree operation which returns members on the same level."),
345
346        /**
347         * Tree operation which returns only the immediate parent.
348         */
349        PARENT(
350            4,
351            "Tree operation which returns only the immediate parent."),
352
353        /**
354         * Tree operation which returns itself in the list of returned rows.
355         */
356        SELF(
357            8,
358            "Tree operation which returns itself in the list of returned "
359            + "rows."),
360
361        /**
362         * Tree operation which returns all of the descendants.
363         */
364        DESCENDANTS(
365            16,
366            "Tree operation which returns all of the descendants."),
367
368        /**
369         * Tree operation which returns all of the ancestors.
370         */
371        ANCESTORS(
372            32,
373            "Tree operation which returns all of the ancestors.");
374
375        private final int xmlaOrdinal;
376        private String description;
377
378        private static final Dictionary<TreeOp> DICTIONARY =
379            DictionaryImpl.forClass(TreeOp.class);
380
381        /**
382         * Per {@link org.olap4j.metadata.XmlaConstant}, returns a dictionary
383         * of all values of this enumeration.
384         *
385         * @return Dictionary of all values
386         */
387        public static Dictionary<TreeOp> getDictionary() {
388            return DICTIONARY;
389        }
390
391        private TreeOp(int xmlaOrdinal, String description) {
392            this.xmlaOrdinal = xmlaOrdinal;
393            this.description = description;
394        }
395
396        public String xmlaName() {
397            return "MDTREEOP_" + name();
398        }
399
400        public String getDescription() {
401            return description;
402        }
403
404        public int xmlaOrdinal() {
405            return xmlaOrdinal;
406        }
407    }
408}
409
410// End Member.java