Skip Headers
Oracle® OLAP Java API Developer's Guide
11g Release 2 (11.2)

Part Number E10795-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

5 Understanding Source Objects

This chapter introduces Source objects, which you use to specify a query. With a Source, you specify the data that you want to retrieve from the data store and the analytical or other operations that you want to perform on the data. Chapter 6, "Making Queries Using Source Methods", provides examples of using Source objects. Using Template objects to make modifiable queries is discussed in Chapter 10, "Creating Dynamic Queries".

This chapter includes the following topics:

Overview of Source Objects

After you have used the classes in the oracle.olapi.metadata.mdm package to get MdmSource objects that represent OLAP metadata measures and dimensions, you can get Source objects from them. You can also create other Source objects with methods of a DataProvider. You can then use the Source objects to create a query that specifies the data that you want to retrieve from the database. To retrieve the data, you create a Cursor for the Source.

With the methods of a Source, you can specify selections of dimension or measure values and specify operations on the elements of the Source, such as mathematical calculations, comparisons, and ordering, adding, or removing elements of a query. The Source class has a few basic methods and many shortcut methods that use one or more of the basic methods. The most complex basic methods are the join(Source joined, Source comparison, int comparisonRule, boolean visible) method and the recursiveJoin(Source joined, Source comparison, Source parent, int comparisonRule, boolean parentsFirst, boolean parentsRestrictedToBase, int maxIterations, boolean visible) method. The many other signatures of the join and recursiveJoin methods are shortcuts for certain operations of the basic methods.

In this chapter, the information about the join method applies equally to the recursiveJoin method, except where otherwise noted. With the join method, you can select elements of a Source and, most importantly, you can relate the elements of one Source to those of another Source. For example, to specify the dimension members that retrieving the data of a measure requires, you use a join method to relate the dimension to the measure.

A Source has certain characteristics, such as a type and a data type, and it sometimes has one or more inputs or outputs. This chapter describes these concepts. It also describes the different kinds of Source objects and how you get them, the join method and other Source methods, and how you use those methods to specify a query.

Kinds of Source Objects

The kinds of Source objects that you use to specify data and to perform analysis, and the ways that you get them, are the following:

The Source class has the following subclasses:

These subclasses have different data types and implement Source methods that require those data types. Each subclass also implements methods unique to it, such as the implies method of a BooleanSource or the indexOf method of a StringSource.

Characteristics of Source Objects

A Source has a data type and a type, a Source identification (ID), and a SourceDefinition. This topic describes these concepts. Some Source objects have one or more inputs or outputs. Those complex concepts are discussed in "Inputs and Outputs of a Source". Some Source objects have an associated Model object, which is discussed in "Model Objects and Source Objects".

Data Type of a Source

The FundamentalMetadataObject class represents the data type of the elements of an MdmSource. The data type of a Source is represented by a fundamental Source. For example, a BooleanSource has elements that have Java boolean values. The data type of a BooleanSource is the fundamental Source that represents OLAP Java API Boolean values.

To get the fundamental Source that represents the data type of a Source, call the getDataType method of the Source. You can also get a fundamental Source by calling the getSource method of a FundamentalMetadataObject.

Example 5-1 demonstrates getting the fundamental Source for the OLAP Java API String data type, the Source for the data type of an MdmPrimaryDimension, and the Source for the data type of the Source for the MdmPrimaryDimension, and comparing them to verify that they are all the same object. In the example, dp is the DataProvider and mdmProdDim is the MdmPrimaryDimension for the Product dimension.

Example 5-1 Getting the Data Type of a Source

FundamentalMetadataProvider fmp = dp.getFundamentalMetadataProvider();
FundamentalMetadataObject fmoStringDataType = fmp.getStringDataType();
Source stringDataTypeSource = fmoStringDataType.getSource();
FundamentalMetadataObject fmoMdmProdDimDataType =
                                               mdmProdDim.getDataType();
Source mdmProdDimDataTypeSource = fmoMdmProdDimDataType.getSource();
Source prodDim = mdmProdDim.getSource();
Source prodDimDataTypeSource = prodDim.getDataType();
if(stringDataTypeSource == prodDimDataTypeSource &&
   mdmProdDimDataTypeSource == prodDimDataTypeSource) 
  println("The Source objects for the data types are the same.");
else
  println("The Source objects for the data types are not the same.");

The example displays the following:

The Source objects for the data types are the same.

Type of a Source

Along with a data type, a Source has a type, which is the Source from which the elements of the Source are drawn. The type of a Source determines whether the join method can match the Source to an input of another Source. The only Source that does not have a type is the fundamental Source for the OLAP Java API Value data type, which represents the set of all values, and from which all other Source objects ultimately descend.

The type of a fundamental Source is the data type of the Source. The type of a list or range Source is the data type of the values of the elements of the list or range Source.

The type of a primary Source is one of the following:

  • The fundamental Source that represents the data type of the values of the elements of the primary Source. For example, the Source returned by getSource method of a typical MdmMeasure is the fundamental Source that represents the set of all OLAP Java API number values.

  • The Source for the MdmSource of which the MdmSource of the primary Source is a component. For example, the type of the Source returned by the getSource method of an MdmLevelHierarchy is the Source for the MdmPrimaryDimension of which the hierarchy is a component.

The type of a derived Source is one of the following:

  • The base Source, which is the Source whose method returned the derived Source. A Source returned by the alias, extract, join, recursiveJoin, or value methods, or one of their shortcuts, has the base Source as the type. An exception is the derived Source returned by the distinct method, whose type is the type of the base Source rather than the base Source itself.

  • A fundamental Source. Methods such as position and count return a Source the type of which is the fundamental Source for the OLAP Java API Integer data type. Methods that make comparisons, such as eq, le, and so on, return a Source the type of which is the fundamental Source for the Boolean data type. Methods that perform aggregate functions, such as the NumberSource methods total and average, return as the type of the Source a fundamental Source that represents the function.

You can find the type by calling the getType method of a Source.

A Source derived from another Source is a subtype of the Source from which it is derived. You can use the isSubtypeOf method to determine if a Source is a subtype of another Source.

For example, in Example 5-2 the myList object is a list Source. The example uses myList to select values from prodHier, a Source for the default MdmLevelHierarchy of the MdmPrimaryDimension for the Product dimension. In the example, dp is the DataProvider.

Example 5-2 Using the isSubtypeOf Method

Source myList = dp.createListSource(new String[] {
                                     "PRODUCT_PRIMARY::FAMILY::LTPC",
                                     "PRODUCT_PRIMARY::FAMILY::DTPC",
                                     "PRODUCT_PRIMARY::FAMILY::ACC",
                                     "PRODUCT_PRIMARY::FAMILY::MON"});
Source prodSel = prodHier.selectValues(myList);
if (prodSel.isSubtypeOf(prodHier))
  println("prodSel is a subtype of prodHier.");
else
  println("prodSel is not a subtype of prodHier.");

Because prodSel is a subtype of prodHier, the condition in the if statement is true and the example displays the following:

prodSel is a subtype of prodHier.

The type of both myList and prodHier is the fundamental String Source. The type of prodSel is prodHier because the elements of prodSel are derived from the elements of prodHier.

The supertype of a Source is the type of the type of a Source, and so on, up through the types to the Source for the fundamental Value data type. For example, the fundamental Value Source is the type of the fundamental String Source, which is the type of prodHier, which is the type of prodSel. The fundamental Value Source and the fundamental String Source are both supertypes of prodSel. The prodSel Source is a subtype of prodHier, and of the fundamental String Source, and of the fundamental Value Source.

Source Identification and SourceDefinition of a Source

A Source has an identification, an ID, which is a String that uniquely identifies it during the current connection to the database. You can get the identification by calling the getID method of a Source. For example, the following code gets the identification of the Source for the MdmPrimaryDimension for the Product dimension and displays the value.

println("The Source ID of prodDim is " + prodDim.getID());

The preceding code displays the following:

The Source ID of prodDim is Hidden..GLOBAL.PRODUCT_AWJ

The text displayed by Example 5-9 has several examples of Source identifications.

Each Source has a SourceDefinition object, which records information about the Source. The different kinds of Source objects have different kinds of SourceDefinition objects. For example, the fundamental Source for an MdmPrimaryDimension has an MdmSourceDefinition, which is a subclass of HiddenDefinition, which is a subclass of SourceDefinition.

The SourceDefinition of a Source that is produced by a call to the join method is an instance of the JoinDefinition class. From a JoinDefinition you can get information about the parameters of the join operation that produced the Source, such as the base Source, the joined Source, the comparison Source, the comparison rule, and the value of the visible parameter.

Inputs and Outputs of a Source

The inputs and the outputs of a Source are complex and powerful aspects of the class. This section describes the concepts of inputs and outputs and provides examples of how they are related.

Inputs of a Source

A Source that has inputs is a dimensioned Source. An input of a Source is also a Source. An input indicates that the values of the dimensioned Source depend upon an unspecified set of values of the input. A Source that matches to the input provides the values that the input requires. You match an input to a dimensioned Source by using the join method. For information on how to match a Source to an input, see "Matching a Source To an Input".

Certain Source objects always have one or more inputs. They are the Source objects for the MdmDimensionedObject subclasses MdmMeasure and MdmAttribute. They have inputs because the values of a measure or attribute are specified by the values of their dimensions. The inputs of the Source for the measure or attribute are the Source objects for the dimensions of the measure or the attribute. Before you can retrieve the data for a measure or an attribute, you must match each input to a Source that provides the required values.

Some Source methods produce a Source that has an input. You can produce a Source that has an input by using the extract, position, or value methods. These methods provide a means of producing a Source whose elements are a subset of the elements of another Source. A Source produced by one of these methods has the base Source as an input.

For example, in the following code, the base Source is prodHier. The value method produces prodHierValues, which has prodHier as an input.

Source prodHierValues = prodHier.value();

The input provides the means to select values from prodHier, as demonstrated by Example 5-2. The selectValues method in Example 5-2 is a shortcut for the following join method.

Source prodSel = prodHier.join(prodHier.value(),
                                 myList,
                                 Source.COMPARISON_RULE_SELECT,
                                 false);

The parameters of the join method specify the elements of the base Source that appear in the resulting Source. In the example, the joined parameter is the Source produced by the prodHier.value() method. The resulting unnamed Source has prodHier as an input. The input is matched by the base of the join method, which is also prodHier. The result of the join operation, prodSel, has the values of prodHier that match the values of prodHier that are in the comparison Source, myList.

If the joined Source were prodHier and not the Source produced by prodHier.value(), then the comparison would be between the Source object itself and the values of the comparison Source and not between the values of the Source and the values of the comparison Source. Because the joined Source object does not match any of the values of the comparison Source, the result of the join method would have all of the elements of prodHier instead of having only the values of prodHier that are specified by the values of the joined Source that match the values of the comparison Source as specified by the comparison rule.

The input of a Source produced by the position or value method, and an input intrinsic to an MdmDimensionedObject, are regular inputs. A regular input causes the join method, when it matches a Source to the input, to compare the values of the comparison Source to the values of the Source that has the input rather than to the input Source itself.

The input of a Source produced by the extract method is an extraction input. An extraction input differs from a regular input in that, when a value of the Source that has the extraction input is a Source, the join method extracts the values of the Source that is a value of the Source that has the input. The join method then compares the values of the comparison Source to the extracted values rather than to the Source itself.

A Source can have from zero to many inputs. You can get all of the inputs of a Source by calling the getInputs method, the regular inputs by calling the getRegularInputs method, and the extraction inputs by calling the getExtractionInputs method. Each of those methods returns a Set of Source objects.

Outputs of a Source

The join method returns a Source that has the elements of the base Source that are specified by the parameters of the method. If the value of the visible parameter is true, then the joined Source becomes an output of the returned Source. An output of a Source returned by the join method has the elements of the joined Source that specify the elements of the returned Source. An output is a means of identifying the elements of the joined Source that specify the elements of the Source that has the output.

A Source can have from zero to many outputs. You can get the outputs of a Source by calling the getOutputs method, which returns a List of Source objects.

A Source with more than one output has one or more elements for each set of the elements of the outputs. For example, a Source that represents a measure that has had all of the inputs matched, and has had the Source objects that match the inputs turned into outputs, has a single type element for each set of the elements of the outputs because each data value of the measure is identified by a unique set of the values of the dimensions. A Source that represents dimension values that are selected by some operation performed on the data of a measure, however, might have more than one element for each set of the elements of the outputs. An example is a Source that represents product values that have unit costs greater than a certain amount. Such a Source might have several products for each time period that have a unit cost greater than the specified amount.

Example 5-3 produces a selection of the elements of shipHier, which is a Source for a hierarchy of a dimension of customer values. The customers are grouped by a shipment origination and destination hierarchy.

Example 5-3 Using the join Method To Produce a Source Without an Output

Source custValuesToSelect = dp.createListSource(new String[]
                                    {"SHIPMENTS::REGION::AMER",
                                     "SHIPMENTS::REGION::EMEA"});
Source shipHierValues = shipHier.value();
Source custSel = shipHier.join(shipHierValues, 
                               custValuesToSelect,
                               Source.COMPARISON_RULE_SELECT, 
                               false);

The shipHierValues Source has an input of shipHier. In the join method in the example, the base Source, shipHier, matches the input of the joined Source, shipHierValues because the base and the input are the same object. The join method selects the elements of the base shipHier whose values match the values of the joined shipHier that are specified by the comparison Source, custValuesToSelect. The method produces a Source, custSel, that has only the selected elements of shipHier. Because the visible parameter is false, the joined Source is not an output of custSel. The custSel Source therefore has only two elements, the values of which are SHIPMENTS::REGION::AMER and SHIPMENTS::REGION::EMEA.

You produce a Source that has an output by specifying true as the visible parameter to the join method. Example 5-4 joins the Source objects for the dimension selections from Example 5-2 and Example 5-3 to produce a Source, custSelByProdSel, that has one output. The custSelByProdSel Source has the elements from custSel that are specified by the elements of prodSel.

The comparison Source is an empty Source, which has no elements and which is the result of the getEmptySource method of the DataProvider, dp. The comparison rule value, COMPARISON_RULE_REMOVE, selects only the elements of prodSel that are not in the comparison Source. Because the comparison Source has no elements, all of the elements of the joined Source are selected. Each of the elements of the joined Source specify all of the elements of the base Source. The resulting Source, custSelByProdSel, therefore has all of the elements of custSel.

Because the visible parameter is true in Example 5-4, prodSel is an output of custSelByProdSel. Therefore, for each element of the output, custSelByProdSel has the elements of custSel that are specified by that element of the output. Because the custSel and prodSel are both simple lists of dimension values, the result is the cross product of the elements of both Source objects.

Example 5-4 Using the join Method To Produce a Source With an Output

Source custSelByProdSel = custSel.join(prodSel,
                                       dp.getEmptySource(),
                                       Source.COMPARISON_RULE_REMOVE,
                                       true);

To actually retrieve the data specified by custSelByProdSel, you must create a Cursor for it. Such a Cursor contains the values shown in the following table, which has headings added that indicate that the values from the output, prodSel, are in the left column and the values from the elements of the custSelByProdSel Source, which are derived from the type, custSel, are in the right column.

Output Values                   Type Values
-----------------------------   ------------------------
PRODUCT_PRIMARY::FAMILY::DTPC   SHIPMENTS::REGION::AMER
PRODUCT_PRIMARY::FAMILY::DTPC   SHIPMENTS::REGION::EMEA
PRODUCT_PRIMARY::FAMILY::LTPC   SHIPMENTS::REGION::AMER
PRODUCT_PRIMARY::FAMILY::LTPC   SHIPMENTS::REGION::EMEA
PRODUCT_PRIMARY::FAMILY::MON    SHIPMENTS::REGION::AMER
PRODUCT_PRIMARY::FAMILY::MON    SHIPMENTS::REGION::EMEA
PRODUCT_PRIMARY::FAMILY::ACC    SHIPMENTS::REGION::AMER
PRODUCT_PRIMARY::FAMILY::ACC    SHIPMENTS::REGION::EMEA

The custSelByProdSel Source has two type elements, and the output of the custSelByProdSel has four elements. The number of elements of custSelByProdSel is eight because for this Source, each output element specifies the same set of two type elements.

Each join operation that specifies a visible parameter of true adds an output to the list of outputs of the resulting Source. For example, if a Source has two outputs and you call one of the join methods that produces an output, then the Source that results from the join operation has three outputs. You can get the outputs of a Source by calling the getOutputs method, which returns a List of Source objects.

Example 5-5 demonstrates joining a measure to selections from the dimensions of the measure, thus matching to the inputs of the measure Source objects that provide the required elements. Because the last two join methods match the dimension selections to the inputs of the measure, the resulting Source does not have any inputs. Because the visible parameter in those joins is true, the last join method produces a Source that has two outputs.

Example 5-5 gets the Source for the measure of unit costs. That Source, unitCost, has two inputs, which are the primary Source objects for the Time and Product dimensions, which are the dimensions of Unit Cost. The example gets the Source objects for hierarchies of the dimensions, which are subtypes of the Source objects for the dimensions. It produces selections of the hierarchies and then joins those selections to the measure. The result, unitCostSel, specifies the unit costs of the selected products at the selected times.

Example 5-5 Using the join Method To Match Source Objects To Inputs

Source unitCost = mdmUnitCost.getSource();
Source calendar = mdmCalendar.getSource();
Source prodHier = mdmProdHier.getSource();
Source timeSel = calendar.join(calendar.value(),
                               dp.createListSource(new String[]
                                             {"CALENDAR_YEAR::MONTH::2000.05",
                                              "CALENDAR_YEAR::MONTH::2001.05"}),
                               Source.COMPARISON_RULE_SELECT,
                               false);
Source prodSel = prodHier.join(prodHier.value(),
                               dp.createListSource(new String[]
                                        {"PRODUCT_PRIMARY::ITEM::ENVY STD",
                                         "PRODUCT_PRIMARY::ITEM::ENVY EXE",
                                         "PRODUCT_PRIMARY::ITEM::ENVY ABM"}),
                               Source.COMPARISON_RULE_SELECT,
                               false);
Source unitCostSel = unitCost.join(timeSel,
                                   dp.getEmptySource(),
                                   Source.COMPARISON_RULE_REMOVE,
                                   true)
                             .join(prodSel, 
                                   dp.getEmptySource(),
                                   Source.COMPARISON_RULE_REMOVE,
                                   true);

The unnamed Source that results from joining timeSel to unitCost has one output, which is timeSel. Joining prodSel to that unnamed Source produces unitCostSel, which has two outputs, timeSel and prodSel. The unitCostSel Source has the elements from the type, unitCost, that are specified by the outputs.

A Cursor for unitCostSel contains the following, displayed as a table with headings added that indicate the structure of the Cursor. A Cursor has the same structure as the associated Source. The unit cost values are formatted as dollar values.

Output 1                        Output 2               Type
           Values                          Values               Values
-------------------------------  ----------------------------  --------
PRODUCT_PRIMARY::ITEM::ENVY ABM  CALENDAR_YEAR::MONTH::2000.05  2847.47
PRODUCT_PRIMARY::ITEM::ENVY ABM  CALENDAR_YEAR::MONTH::2001.05  2819.85
PRODUCT_PRIMARY::ITEM::ENVY STD  CALENDAR_YEAR::MONTH::2000.05  2897.40
PRODUCT_PRIMARY::ITEM::ENVY STD  CALENDAR_YEAR::MONTH::2001.05  2376.73
PRODUCT_PRIMARY::ITEM::ENVY EXE  CALENDAR_YEAR::MONTH::2000.05  3238.36
PRODUCT_PRIMARY::ITEM::ENVY EXE  CALENDAR_YEAR::MONTH::2001.05  3015.90

Output 1 has the values from prodSel, output 2 has the values from timeSel, and the type values are the values from unitCost that are specified by the output values.

Because these join operations are performed by most OLAP Java API applications, the API provides shortcuts for these and many other join operations. Example 5-6 uses shortcuts for the join operations in Example 5-5 to produce the same result.

Example 5-6 Using Shortcuts

Source unitCost = mdmUnitCost.getSource();
StringSource calendar = (StringSource) mdmCalendar.getSource();
StringSource prodHier =(StringSource) mdmProdHier.getSource();
Source timeSel = calendar.selectValues(new String[]
                                       {"CALENDAR_YEAR::MONTH::2000.05",
                                        "CALENDAR_YEAR::MONTH::2001.05"}),
Source prodSel = prodHier.selectValues(new String[]
                                        {"PRODUCT_PRIMARY::ITEM::ENVY STD",
                                         "PRODUCT_PRIMARY::ITEM::ENVY EXE",
                                         "PRODUCT_PRIMARY::ITEM::ENVY ABM"}),
Source unitCostSel = unitCost.join(timeSel).join(prodSel);

Matching a Source To an Input

In a join operation, a Source-to-input match occurs only between the base Source and the joined Source. A Source matches an input if one of the following conditions is true.

  1. The Source is the same object as the input or it is a subtype of the input.

  2. The Source has an output that is the same object as the input or the output is a subtype of the input.

  3. The output has an output that is the same object as the input or is a subtype of the input.

The join operation looks for the conditions in the order in the preceding list. It searches the list of outputs of the Source recursively, looking for a match to the input. The search ends with the first matching Source. An input can match with only one Source, and two inputs cannot match with the same Source.

When a Source matches an input, the result of the join method has the elements of the base that match the elements specified by the parameters of the method. You can determine if a Source matches another Source, or an output of the other Source, by passing the Source to the findMatchFor method of the other Source.

When a Source matches an input, the resulting Source does not have that input. Matching a Source to an input does not affect the outputs of the base Source or the joined Source. If a base Source has an output that matches the input of the joined Source, the resulting Source does not have the input but it does have the output.

If the base Source or the joined Source in a join operation has an input that is not matched in the operation, then the unmatched input is an input of the resulting Source.

The comparison Source of a join method does not participate in the input matching. If the comparison Source has an input, then that input is not matched and the Source returned by the join method has that same input.

Example 5-7 demonstrates a base Source matching the input of the joined Source in a join operation. The example uses the position method to produce a Source that has an input, and then uses the join method to match the base of the join operation to the input of the joined Source.

Example 5-7 Matching the Base Source to an Input of the Joined Source

Source myList = dp.createListSource(new String[]
                                    {"PRODUCT_PRIMARY::FAMILY::LTPC",
                                     "PRODUCT_PRIMARY::FAMILY::DTPC",
                                     "PRODUCT_PRIMARY::FAMILY::ACC",
                                     "PRODUCT_PRIMARY::FAMILY::MON"});
Source pos = dp.createListSource(new int[] {2, 4});
Source myListPos = myList.position();
Source myListSel = myList.join(myListPos,
                               pos,
                               Source.COMPARISON_RULE_SELECT,
                               false);

In Example 5-7, the position method returns myListPos, which has the elements of myList and which has myList as an input. The join method matches the base myList to the input of the joined Source, myListPos.

The comparison Source, pos, specifies the positions of the elements of myListPos to match to the positions of the elements of myList. The elements of the resulting Source, myListSel, are the elements of myList whose positions match those specified by the parameters of the join method.

A Cursor for myListSel has the following values.

PRODUCT_PRIMARY::FAMILY::DTPC
PRODUCT_PRIMARY::FAMILY::MON

If the visible parameter in Example 5-7 were true instead of false, then the result would have elements from myList and an output of myListPos. A Cursor for myListSel in that case would have the following values, displayed as a table with headings added that indicate the output and type values.

Output            Type
Values           Values
------  -------------------------
  2     PRODUCT_PRIMARY::FAMILY::DTPC
  4     PRODUCT_PRIMARY::FAMILY::MON

Example 5-8 demonstrates matching outputs of the joined Source to two inputs of the base Source. In the example, units is a Source for an MdmMeasure. It has as inputs the primary Source objects for the Time, Product, Customer, and Channel dimensions.

The DataProvider is dp, and prodHier, shipHier, calendar, and chanHier are the Source objects for the default hierarchies of the Product, Customer, Time, and Channel dimensions, respectively. Those Source objects are subtypes of the Source objects for the dimensions that are the inputs of units.

The join method of prodHier in the first line of Example 5-8 results in prodSel, which specifies selected product values. In that method, the joined Source is the result of the value method of prodHier. The joined Source has the same elements as prodHier, and it has prodHier as an input. The comparison Source is the list Source that is the result of the createListSource method of the DataProvider.

The base Source of the join method, prodHier, matches the input of the joined Source. Because prodHier is the input of the joined Source, the Source returned by the join method has only the elements of the base, prodHier, that match the elements of the joined Source that appear in the comparison Source. Because the visible parameter value is false, the resulting Source does not have the joined Source as an output. The next three similar join operations in Example 5-8 result in selections for the other three dimensions.

The join method of timeSel has custSel as the joined Source. The comparison Source is the result of the getEmptySource method, so it has no elements. The comparison rule specifies that the elements of the joined Source that are present in the comparison Source do not appear in the resulting Source. Because the comparison Source has no elements, all of the elements of the joined Source are selected. The true value for the visible parameter causes the joined Source to be an output of the Source returned by the join method. The returned Source, custSelByTime, has the selected elements of the Customer dimension and has timeSel as an output.

The join method of prodSel has custSelByTime as the joined Source. It produces prodByCustByTime, which has the selected elements from the Product dimension and has custSelByTime as an output. Example 5-8 then joins the dimension selections to the units Source.

The dimension selections are subtypes of the Source objects that are the inputs of units, and therefore the selections match the inputs of units. The input for the Product dimension is matched by prodByCustByTime because prodByCustByTime is a subtype of prodSel, which is a subtype of prodHier. The input for the Customer dimension is matched by the custSelByTime, which is the output of prodByCustByTime.

The custSelByTime Source is a subtype of custSel, which is a subtype of shipHier. The input for the times dimension is matched by timeSel, which is the output of custSelByTime. The timeSel Source is a subtype of calendar.

Example 5-8 Matching an Input of the Base Source to an Output of the Joined Source

Source prodSel = prodHier.join(prodHier.value(),
                               dp.createListSource(new String[]
                                     {"PRODUCT_PRIMARY::FAMILY::DTPC",
                                      "PRODUCT_PRIMARY::FAMILY::LTPC"}),
                               Source.COMPARISON_RULE_SELECT, 
                               false);
Source custSel = shipHier.join(shipHier.value(),
                               dp.createListSource(new String[]
                                    {"SHIPMENTS::REGION::EMEA",
                                     "SHIPMENTS::REGION::AMER"}),
                               Source.COMPARISON_RULE_SELECT,
                               false);
Source timeSel =  calendar.join(calendar.value(),
                                dp.createConstantSource(
                                               "CALENDAR_YEAR::YEAR::CY2001"),
                                Source.COMPARISON_RULE_SELECT, 
                                false);
Source chanSel = chanHier.join(chanHier.value(),
                                dp.createConstantSource(
                                      "CHANNEL_PRIMARY::CHANNEL::INT"),
                                Source.COMPARISON_RULE_SELECT, 
                                false);

Source custSelByTime = custSel.join(timeSel, 
                                    dp.getEmptySource(),
                                    Source.COMPARISON_RULE_REMOVE,
                                    true);
Source prodByCustByTime = prodSel.join(custSelByTime,
                                       dp.getEmptySource(),
                                       Source.COMPARISON_RULE_REMOVE,
                                       true);

Source selectedUnits = units.join(prodByCustByTime, 
                                  dp.getEmptySource(),
                                  Source.COMPARISON_RULE_REMOVE,
                                  true)
                            .join(promoSel, 
                                  dp.getEmptySource(),
                                  Source.COMPARISON_RULE_REMOVE,
                                  true ),
                            .join(chanSel, 
                                  dp.getEmptySource(),
                                  Source.COMPARISON_RULE_REMOVE,
                                  true);

A Cursor for selectedUnits contains the following values, displayed in a crosstab format with column headings and formatting added. The table has only the local values of the dimension elements. The first two lines are the page edge values of the crosstab, which are the values of the chanSel output of selectedUnits, and the value of timeSel, which is an output of the prodByCustByTime output of selectedUnits. The row edge values of the crosstab are the customer values in the left column, and the column edge values are the products values that head the middle and right columns.

The crosstab has only the local value portion of the unique values of the dimension elements. The measure values are the units sold values specified by the selected dimension values.

INT
CY2001
             Products
            -----------
Customers   DTPC   LTPC
---------   ----   ----
AMER        1748   846
EMEA         439   215

The following table has the same results except that the dimension element values are replaced by the short descriptions of those values.

Internet
2001
                           Products
               -------------------------
Customers      Desktop PCs   Portable PCs
-------------  -----------   ------------
North America      1748           846
Europe              439           215

To demonstrate turning inputs into outputs, Example 5-9 uses units, which is the Source for the Units measure, and defaultHiers, which is an ArrayList of the Source objects for the default hierarchies of the dimensions of the measure. The example gets the inputs and outputs of the Source for the measure. It displays the Source identifications of the Source for the measure and for the inputs of the Source. The inputs of the Source for the measure are the Source objects for the MdmPrimaryDimension objects that are the dimensions of the measure.

Example 5-9 next displays the number of inputs and outputs of the Source for the measure. Using the join(Source joined) method, which produces a Source that has the elements of the base of the join operation as the elements of it and the joined parameter Source as an output, it joins one of the hierarchy Source objects to the Source for the measure, and displays the number of inputs and outputs of the resulting Source. It then joins each remaining hierarchy Source to the result of the previous join operation and displays the number of inputs and outputs of the resulting Source.

Finally the example gets the outputs of the Source produced by the last join operation, and displays the Source identifications of the outputs. The outputs of the last Source are the Source objects for the default hierarchies, which the example joined to the Source for the measure. Because the Source objects for the hierarchies are subtypes of the Source objects for the MdmPrimaryDimension objects that are the inputs of the measure, they match those inputs.

Example 5-9 Matching the Inputs of a Measure and Producing Outputs

Set inputs = units.getInputs();
Iterator inputsItr = inputs.iterator();
List outputs = units.getOutputs();
Source input = null;

int i = 1;
println("The inputs of " + units.getID() + " are:");
while(inputsItr.hasNext())
{
  input = (Source) inputsItr.next();
  println(i + ": " + input.getID());
  i++;
}

println(" ");
int setSize = inputs.size();
for(i = 0; i < (setSize + 1); i++) 
{
  println(units.getID() + " has " + inputs.size() + 
                   " inputs and " + outputs.size() + " outputs.");
  if (i < setSize) 
  {
    input = defaultHiers.get(i);
    println("Joining " + input.getID() + " to " + units.getID());
    units = units.join(input);   
    inputs = units.getInputs();
    outputs = units.getOutputs();
  }
}

println("The outputs of " + units.getID() + " are:");
Iterator outputsItr = outputs.iterator();
i = 1;
while(outputsItr.hasNext())
{
  Source output = (Source) outputsItr.next();
  println(i + ": " + output.getID());
  i++;
}

The text displayed by the example is the following:

The inputs of Hidden..GLOBAL.UNITS_CUBE_AWJ.UNITS are:
1: Hidden..GLOBAL.CHANNEL_AWJ
2: Hidden..GLOBAL.CUSTOMER_AWJ
3: Hidden..GLOBAL.PRODUCT_AWJ
4: Hidden..GLOBAL.TIME_AWJ

Hidden..GLOBAL.UNITS_CUBE_AWJ.UNITS has 4 inputs and 0 outputs.
Joining Hidden..GLOBAL.CHANNEL_AWJ.CHANNEL_PRIMARY to Hidden..GLOBAL.UNITS_CUBE_AWJ.UNITS
Join.30 has 3 inputs and 1 outputs.
Joining Hidden..GLOBAL.CUSTOMER_AWJ.SHIPMENTS to Join.30
Join.31 has 2 inputs and 2 outputs.
Joining Hidden..GLOBAL.PRODUCT_AWJ.PRODUCT_PRIMARY to Join.31
Join.32 has 1 inputs and 3 outputs.
Joining Hidden..GLOBAL.TIME_AWJ.CALENDAR_YEAR to Join.32
Join.33 has 0 inputs and 4 outputs.

The outputs of Join.33 are:
1: Hidden..GLOBAL.TIME_AWJ.CALENDAR_YEAR
2: Hidden..GLOBAL.PRODUCT_AWJ.PRODUCT_PRIMARY
3: Hidden..GLOBAL.CUSTOMER_AWJ.SHIPMENTS
4: Hidden..GLOBAL.CHANNEL_AWJ.CHANNEL_PRIMARY

Note that as each successive Source for a hierarchy is joined to the result of the previous join operation, it becomes the first output in the List of outputs of the resulting Source. Therefore, the first output of Join.33 is Hidden..GLOBAL.TIME_AWJ.CALENDAR_YEAR, and the last output is Hidden..GLOBAL.CHANNEL_AWJ.CHANNEL_PRIMARY.

Describing Parameterized Source Objects

Parameterized Source objects provide a way of specifying a query and retrieving different result sets for the query by changing the set of elements specified by the parameterized Source. You create a parameterized Source with a createSource method of the Parameter. The Parameter supplies the value that the parameterized Source specifies.

A typical use of a Parameter object is to specify the page edges of a cube. Example 6-9 demonstrates using Parameter objects to specify page edges. Another use of a Parameter is to fetch from the server only the set of elements that you currently need. Example 6-15 demonstrates using Parameter objects to fetch different sets of elements.

When you create a Parameter object, you supply an initial value for the Parameter. You then create the parameterized Source using the Parameter. You include the parameterized Source in specifying a query. You create a Cursor for the query. You can change the value of the Parameter with the setValue method, which changes the set of elements that the query specifies. Using the same Cursor, you can then display the new set of values.

Example 5-10 demonstrates the use of a Parameter and a parameterized Source to specify an element in a measure dimension. It creates a list Source that has as element values the Source objects for the Unit Cost and Unit Price measures. The example creates a StringParameter object that has as an initial value the unique identifying String for the Source for the Unit Cost measure. That StringParameter is then used to create a parameterized Source.

The example extracts the values from the measures, and then selects the data values that are specified by joining the dimension selections to the measure specified by the parameterized Source. It creates a Cursor for the resulting query and displays the results. After resetting the Cursor position and changing the value of the measParam StringParameter, the example displays the values of the Cursor again.

The dp object is the DataProvider. The getContext method gets a Context11g object that has a method that displays the values of the Cursor with only the local value of the dimension elements.

Example 5-10 Using a Parameterized Source With a Measure Dimension

Source measDim = dp.createListSource(new Source[] {unitCost, 
                                                   unitPrice});
 
// Get the unique identifiers of the Source objects for the measures.
String unitCostID = unitCost.getID();
String unitPriceID = unitPrice.getID();
 
// Create a StringParameter using one of the IDs as the initial value.
StringParameter measParam = new StringParameter(dp, unitCostID);
 
// Create a parameterized Source.
Source measParamSrc = measParam.createSource();

// Extract the values from the measure dimension elements, and join 
// them to the specified measure and the dimension selections.
Source result = measDim.extract().join(measDim, measParamSrc)
                                 .join(prodSelShortDescr)
                                 .join(timeSelShortDescr);
// Get the TransactionProvider and commit the current transaction.
// These operations are not shown.
 
// Create a Cursor.
CursorManager cursorMngr = getDataProvider().createCursorManager(result);
Cursor resultsCursor = cursorMngr.createCursor();
 
// Display the results.
getContext().displayCursor(resultsCursor, true);
 
// Reset the Cursor position to 1.
resultsCursor.setPosition(1);

// Change the value of the parameterized Source.
measParam.setValue(unitPriceID);

// Display the results again.
getContext().displayCursor(resultsCursor, true);

The following table displays the first set of values of resultsCursor, with column headings and formatting added. The left column of the table has the local value of the Time dimension hierarchy. The second column from the left has the short value description of the time value. The third column has the local value of the Product dimension hierarchy. The fourth column has the short value description of the product value. The fifth column has the Unit Cost measure value for the time and product.

Time     Description  Product     Description    Unit Cost
-------  -----------  --------  ---------------  ---------
2001.04     Apr-01    ENVY EXE  Envoy Executive    2952.85
2001.04     Apr-01    ENVY STD  Envoy Standard     2360.78
2001.05     May-01    ENVY EXE  Envoy Executive    3015.90
2001.05     May-01    ENVY STD  Envoy Standard     2376.73

The following table displays the second set of values of resultsCursor in the same format. This time the fifth column has values from the Unit Price measure.

Time     Description  Product     Description    Unit Price
-------  -----------  --------  ---------------  ----------
2001.04     Apr-01    ENVY EXE  Envoy Executive     3107.65
2001.04     Apr-01    ENVY STD  Envoy Standard      2412.42
2001.05     May-01    ENVY EXE  Envoy Executive     3147.85
2001.05     May-01    ENVY STD  Envoy Standard      2395.63

Model Objects and Source Objects

This topic describes the Model interface and the implementations of it, and the relationship of Model and Source objects. It also presents examples of creating custom Model objects and performing other tasks that involve Source and Model objects.

Describing the Model for a Source

A Model is analogous to the Oracle SQL MODEL clause. With a Model you can assign a value to the Source for a dimensioned object for one or more sets of members of the dimensions of the object. The value that the Model assigns can be anything from a simple constant to the result of a complex calculation involving several other Source objects with nested Model objects.

The value that a Model assigns for a set of dimension members is represented by an Assignment object. A Model can have one or more Assignment objects. Each dimension member in the set is represented by a Qualification object. An Assignment has one or more Qualification objects.

The value that the Assignment assigns is specified by a Source. An Assignment also has an integer that specifies a precedence that affects the order in which Oracle OLAP calculates a value and assigns it. If you create more that one Assignment for a Model without specifying a precedence, then the order in which Oracle OLAP calculates and assigns the values is not guaranteed.

A Model assigns values for existing dimension members. You can use a Model to assign a different value for a dimension member, or to assign a value for a set of members of more than one dimension, or to assign a different value for a specific measure for the set of dimension members, or to assign a value for the dimension member for an attribute.

When you create a custom dimension member, you specify an assignment value for it. Oracle OLAP automatically adds an Assignment object that specifies the value for the custom member to the appropriate Model for the dimension. Oracle OLAP assigns that value as the measure value for any measure dimensioned by the dimension.

Figure 5-1 illustrates the class hierarchy of the Model interface and the classes that implement it. The oracle.olapi.metadata.mdm.MdmModel class implements the Model interface for MdmObject objects. Another implementation of the Model interface is the CustomModel class in the oracle.olapi.data.source package.

Figure 5-1 The Model Interface and Implementations

Description of Figure 5-1 follows
Description of "Figure 5-1 The Model Interface and Implementations"

A Model has one or more inputs, which are the Source objects for which the model assigns values. The inputs are equivalent to the list of dimensions of an OLAP DML or SQL Model. For example, the MdmDimensionCalculationModel returned by the getNumberCalcModel method of an MdmStandardDimension has as an input the Source for that same MdmStandardDimension. The MdmDimensionedObjectModel returned by the getModel method of an MdmAttribute has as an input the Source for the MdmPrimaryDimension that dimensions the attribute. The MdmDimensionedObjectModel returned by getModel method of an MdmMeasure has as inputs the Source objects for the MdmPrimaryDimension objects that dimension the measure.

A Model can have one or more parents, which are other Model objects from which the Model inherits Assignment objects. An MdmMeasureModel has as parents the MdmDimensionCalculationModel objects of the dimensions associated with it. MdmAttributeModel and MdmDimensionCalculationModel objects do not have parent Model objects.

A CustomModel can have inputs and it can have parent Model objects. When you create a CustomModel object, you can specify inputs and parent Model objects for it. A CustomModel can have also have outputs, which MdmModel objects do not have.

You can create a series of CustomModel objects and have them inherit Assignment objects from each other. The following restrictions apply to the inheritance of an Assignment by one CustomModel from another:

  • The inheritance cannot be circular. For example, if customModelB inherits from customModelA, then customModelA cannot inherit from customModelB.

  • The type and the outputs of the CustomModel objects must be the same.

  • If a parent CustomModel has an input, then the child CustomModel must also specify that input. The child CustomModel can have additional inputs, but it must specify the inputs of the parent CustomModel objects.

After creating a CustomModel and adding any assignments to it, you can create a Source for it by calling the createSolvedSource method of the CustomModel. With the defaultValues parameter of the createSolvedSource method, you can specify a Source that supplies default values for the Source returned by the method. If you do not specify a Source for the default values, then the default values of the resulting Source are null.

Creating a CustomModel - Example

The Source.extract method is implemented as a CustomModel. An advantage of using your own CustomModel over the extract method is that you can assign the measure value to a String other than a Source ID. Example 5-11 demonstrates using the extract method and then using a CustomModel to achieve the same result. It also demonstrates using another CustomModel to achieve a result that assigns the measure values to a different set of String values.

In the example, unitPrice and unitCost are NumberSource objects for the Unit Price and Unit Cost measures, and dp is the DataProvider. The prodSel object is a Source that represents the selection of three members of the Product dimension.

Example 5-11 Implementing the extract Method As a CustomModel

// Create a Source that represents a calculation involving two measures.
Source calculation = unitPrice.minus(unitCost);

// Create a list Source that has Source objects as element values.
Source sourceListSrc = dp.createListSource(new Source[] 
                                           {unitPrice, unitCost, calculation});
// Use the extract method to get the values of the Source components of the
// list and join Source objects that match the inputs.
Source resultUsingExtract = 
                   sourceListSrc.extract()
                                .join(sourceListSrc)
                                .join(prodSel)
                                .join(calendar, "CALENDAR_YEAR::MONTH::2000.05");

// Produce the same result using a CustomModel directly.
CustomModel  customModel = dp.createModel(sourceListSrc);
customModel.assign(unitPrice.getID(), unitPrice);
customModel.assign(unitCost.getID(), unitCost);
customModel.assign(calculation.getID(), calculation);
Source measValForSrc = customModel.createSolvedSource();
Source resultUsingCustomModel = 
                   measValForSrc.join(sourceListSrc)
                                .join(prodSel)
                                .join(calendar, "CALENDAR_YEAR::MONTH::2000.05");

// Create a list Source that has String objects as element values.
Source stringListSrc = dp.createListSource(new String[]
                                           {"price", "cost", "markup"});
// Create a CustomModel for the list Source.
CustomModel  customModel2 = dp.createModel(stringListSrc);
customModel2.assign("price", unitPrice);
customModel2.assign("cost", unitCost);
customModel2.assign("markup", calculation);
Source measValForSrc2 = customModel2.createSolvedSource();
 
Source resultUsingCustomModel2 = 
                  measValForSrc2.join(stringListSrc)
                                .join(prodSel)
                                .join(calendar, "CALENDAR_YEAR::MONTH::2000.05");

Cursor objects for resultUsingExtract and resultUsingCustomModel have the same values, which are the following, shown with formatting added:

PRODUCT_PRIMARY::ITEM::ENVY ABM  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_PRICE
 2962.14
PRODUCT_PRIMARY::ITEM::ENVY ABM  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_COST 
 2847.47
PRODUCT_PRIMARY::ITEM::ENVY ABM  Join.2                                  
 114.67
PRODUCT_PRIMARY::ITEM::ENVY EXE  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_PRICE 
 3442.86
PRODUCT_PRIMARY::ITEM::ENVY EXE  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_COST  
 3238.36
PRODUCT_PRIMARY::ITEM::ENVY EXE  Join.2                                  
 204.50
ITEM::ENVY STD  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_PRICE
 3118.61
PRODUCT_PRIMARY::ITEM::ENVY STD  Hidden..GLOBAL.PRICE_CUBE_AWJ.UNIT_COST
 2897.40
PRODUCT_PRIMARY::ITEM::ENVY STD  Join.2
 221.21

A Cursor for resultUsingCustomModel2 has the following values, shown with formatting added:

PRODUCT_PRIMARY::ITEM::ENVY ABM  price  2962.14
PRODUCT_PRIMARY::ITEM::ENVY ABM  cost   2847.47
PRODUCT_PRIMARY::ITEM::ENVY ABM  markup  114.67
PRODUCT_PRIMARY::ITEM::ENVY EXE  price  3442.86
PRODUCT_PRIMARY::ITEM::ENVY EXE  cost   3238.36
PRODUCT_PRIMARY::ITEM::ENVY EXE  markup  204.50
PRODUCT_PRIMARY::ITEM::ENVY STD  price  3118.61
PRODUCT_PRIMARY::ITEM::ENVY STD  cost   2897.40
PRODUCT_PRIMARY::ITEM::ENVY STD  markup  221.21