PK
u.Aoa, mimetypeapplication/epub+zipPK u.A iTunesMetadata.plistL

This preface describes the features of the Oracle OLAP Java API that are new in the 11g releases of Oracle OLAP.
This topic describes the features of the Oracle OLAP Java API that Oracle has added since the initial 11g Release 1 (11.1). For a complete list of the packages, classes, fields, and methods that are new since 11.1, see the Overview of Oracle OLAP Java API Reference.
The following topics describe the new features since 11.1.
To support legacy 10g metadata objects, the Oracle OLAP Java API includes the following functionality.
Allowing 10g and 11g metadata objects in the same session. The oracle.olapi.data.source.DataProvider class has the new ALL metadata reader mode setting. For more information, see "Describing Namespaces".
Attributing namespaces. To allow a 10g metadata object to exist in the same session as 11g objects, Oracle OLAP assigns a namespace to the 10g object. The namespace identifies the metadata format and the type of object. For more information on namespaces, see "Describing Namespaces".
In 11.2, you can use the setName method to rename a persistent 11g metadata object. In previous releases, you could use the MdmObject.setName method only once to specify a name for a persistent metadata object. You could not change the name after setting it. For more information on setting names, see "Getting and Setting Names".
In a column for an attribute in an OLAP view, you can now automatically populate the rows for lower levels in a dimension hierarchy with the attribute values that are mapped at a higher level. For more information, see "Populating OLAP Views with Hierarchical Attribute Values".
The following new features affect materialized views for OLAP cubes.
Specifying attribute column names for materialized views. With the setETAttrPrefix method of the MdmDimensionality object for a dimension of an OLAP cube, you can specify the prefix that Oracle OLAP uses in naming the columns for the attributes of the dimension in the materialized view for the cube. For more information, see "Preparing Attributes for Materialized Views".
Including populated lineage attributes in a materialized view that is available to the query rewrite system. If the materialized view has a column for the same attribute at different levels of a hierarchy, you can specify the new REWRITE_WITH_ATTRIBUTES_MV_OPTION materialized view option of the AWCubeOrganization class. That option populates the column for an attribute for a level in the view with the values of the same attribute for lower levels. For more information, see "Representing Cubes".
The following topics describe new features that affect building analytic workspace metadata objects.
You can now create an oracle.olapi.syntax.LoadCommand that specifies the use of serial or parallel processing when loading data in an analytic workspace. The LoadCommand also has a PRUNE option, which specifies that the build spawns jobs only for the partitions for which measure data exists.
The LoadCommand class now has constructor methods as well as static constant fields that produce LoadCommand objects. One of the constructors takes the name of a CubeMap. With that constructor, you can specify loading data from single CubeMap rather than from all CubeMap objects.
The ClearCommand and SolveCommand classes also have serial and parallel processing options.
With an oracle.olapi.data.source.BuildResult, an application can get the identification number for a build process. The DataProvider class has executeBuild methods that take a BuildResult.
An analytic workspace automatically generates the identification number during a build. You can use the build number to track the progress of a build.
With the oracle.olapi.syntax.AggregationFunctionExpression class, in an MdmModel you can aggregate measure values over specified dimension members. You specify the dimension members with an AggregateOverMembersClause. You can use an AggregationFunctionExpression as the Expression for an MdmCustomMember or the member expression of an MdmAssignment in the MdmModel.
You can now specify a language when mapping an attribute and you can map multiple languages to the same attribute. For more information, see "Specifying a Language for an Attribute" and "Specifying Multilingual Attributes".
The following new features allow you to add identifying metadata to objects.
Classifying objects. With the addObjectClassification method of an MdmObject, you can add metadata to that object. For more information, see "Using Classifications".
Grouping attributes. With the setAttributeGroupName method of an MdmBaseAttribute, you can specify a name for an attribute group. For more information, see "Grouping Attributes".
An implementation of the oracle.olapi.metadata.XMLWriterCallback interface provides Oracle OLAP the means to call back to an application while the MdmMetadataProvider is exporting the XML definition of an object. With an XMLWriterCallback, the application can specify whether or not to exclude an attribute or an owner name from the exported XML. For more information see "Exporting and Importing Metadata as XML Templates".
Some aspects of the Oracle OLAP Java API are much the same as in previous releases, such as the ability to create queries with classes in the oracle.olapi.data.source package and to retrieve the data with classes in the oracle.olapi.data.cursor package. However, in Oracle OLAP 11g Release 1 (11.1) the metadata model of the API has changed and has many new features. The major new features are presented in the following topics.
The Oracle OLAP Java API now has the ability to create and maintain persistent metadata objects. The Oracle Database stores the metadata objects in the Oracle data dictionary.
To provide this new functionality, the Oracle OLAP Java API substantially revises the metadata model. The new model includes several new packages and has significant changes to some existing packages. For example, the oracle.olapi.metadata.mdm package has many new classes. It also has many new methods added to existing classes. For information on OLAP metadata objects, see Chapter 2, "Understanding OLAP Java API Metadata".
Some classes and methods are deprecated in the new model. For example, all of the classes in the oracle.olapi.metadata.mtm package are deprecated, and methods of other classes that use the mtm classes are also deprecated. Some mtm classes mapped transient mdm objects to relational database structures, such as columns in tables and views. Other mtm classes specified how Oracle OLAP performed operations such as aggregation or allocation of the values of custom measures. That functionality is replaced by classes in the oracle.olapi.metadata subpackages deployment, mapping, and mdm, and the oracle.olapi.syntax package. With the new classes, an application can create permanent metadata objects, map them to data sources, and specify the operations that provide values for measures.
When an application commits the Transaction in which it has created top-level objects in the OLAP metadata model, such as instances of classes like AW, MdmCube, and MdmPrimaryDimension, those objects then exist in the Oracle data dictionary. They are available for use by ordinary SQL queries as well as for use by applications that use the Oracle OLAP Java API.
Because the metadata objects exist in the Oracle data dictionary, an Oracle Database DBA can restrict access to certain types of the metadata objects. A client application can set such restrictions by using the JDBC API to send standard SQL GRANT and REVOKE commands through the JDBC connection for the user session.
An application can now define, build, and maintain analytic workspaces. This new functionality is provided by classes in the oracle.olapi.metadata subpackages deployment, mapping, and mdm, and the oracle.olapi.syntax package. In 10g releases of Oracle Database, that functionality was provided by a separate API, the Oracle OLAP Analytic Workspace Java API, which is entirely deprecated in this release. For more information see Chapter 2.
After defining a metadata object, an application can export that definition in an XML format. Analytic Workspace Manager refers to such a saved definition as a template. An application can also import the XML definition of a metadata object. The MdmMetadataProvider class has methods for exporting and importing the XML. For more information see "Exporting and Importing Metadata as XML Templates".
With the classes in the oracle.olap.syntax package, an application can create Java objects that are based on SQL-like expressions, functions, operators, and conditions. The SyntaxObject class has fromSyntax and toSyntax methods that an application can use to convert SQL expressions into Java objects or to get the SQL syntax from a Java object.
An application can create an Expression object by using the SyntaxObject.fromSyntax method or by using a constructor. For example, the following code creates a StringExpression using a fromSyntax method and another StringExpression using a constructor method. The mp object is the MdmMetadataProvider for the session.
StringExpression strExp1 = (StringExpression)
SyntaxObject.fromSyntax("'Hello world from syntax.'", mp);
StringExpression strExp2 = new StringExpression("Hello world from constructor.");
Another new feature is the ability to have multiple user sessions that share the same JDBC connection to the Oracle Database instance and that share the same cache of metadata objects. This ability is provided by the UserSession class in the oracle.olapi.session package.
To support legacy applications, the OLAP Java API provides a means of specifying a metadata reader that can recognize metadata objects that were created by a previous method. For more information, see "Supporting Legacy Metadata Objects".
Java API Developer's Guide
11g Release 2 (11.2)
E10795-06
June 2011
Oracle OLAP Java API Developer's Guide, 11g Release 2 (11.2)
E10795-06
Copyright © 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Primary Author: David McDermid
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.
If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:
U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.
This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.
Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.
This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.
This chapter describes 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. Chapter 10, "Creating Dynamic Queries", describes using Template objects to make modifiable queries.
This chapter includes the following topics:
You use Source objects to create a query that specifies the data that you want to retrieve from the database. As a query, a Source is similar to a SQL SELECT statement.
To create a query, you typically use the classes in the oracle.olapi.metadata.mdm package to get MdmSource objects that represent OLAP metadata objects. From an MdmSource object, you can get a Source object. You can also create other kinds of Source objects with methods of a DataProvider. You can then use these Source objects to create a query. To retrieve the data specified by the query, you create a Cursor for the Source.
With the methods of a Source, you can specify selections of dimension members, attribute values, or measure values. You can also 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 compariso4n, 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 relate the elements of one Source to those of another Source by joining a Source with an input to a Source that matches with that input. For example, to specify the dimension members that are required to retrieve the data of a measure that has the dimension as an input, you use a join method to relate the dimension members to the measure. The join method and the inputs of a Source are described in "Inputs and Outputs of a Source".
A Source has certain characteristics, such as a type and a data type, and it can have 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, and the join method and other Source methods and how you use those methods to specify a query.
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:
Primary Source objects, which are returned by the getSource method of an MdmSource object such as an MdmDimension or an MdmDimensionedObject. A primary Source provides access to the data that the MdmSource represents. Getting primary Source objects is usually the first step in creating a query. You then typically select elements from the primary Source objects, thereby producing derived Source objects.
Derived Source objects, which you get by calling some of the methods of a Source object. Methods such as join return a new Source that is derived from the Source on which you call the method. All queries on the data store, other than a simple list of values specified by the primary Source for an MdmDimension, are derived Source objects.
Fundamental Source objects, which are returned by the getSource method of a FundamentalMetadataObject. These Source objects represent the OLAP Java API data types.
List or range Source objects, which are returned by the createConstantSource, createListSource, or createRangeSource methods of a DataProvider. Typically, you use this kind of Source as the joined or comparison parameter to a join method.
Empty, null, or void Source objects. The empty and void Source objects are returned by the getEmptySource or getVoidSource method of a DataProvider, and the null Source object is returned by the nullSource method of a Source. The empty Source has no elements. The void Source and a null Source each has one element that has the value of null. The difference between the void Source and a null Source is that the type of the void Source is the FundamentalMetadataObject for the Value data type and the type of a null Source is the Source whose nullSource method returned it. Typically, you use these kinds of Source objects as the joined or comparison parameter to a join method.
Dynamic Source objects, which are returned by the getSource method of a DynamicDefinition. A dynamic Source is usually a derived Source. It is generated by a Template, which you use to create a dynamic query that you can revise after interacting with an end user.
Parameterized Source objects, which are returned by the createSource methods of a Parameter. Like a list or range Source, you use a parameterized Source as a parameter to the join method. Unlike a list or range Source, however, you can change the value that the Parameter represents after the join operation and thereby change the selection that the derived Source represents. You can create a Cursor for that derived Source and retrieve the results of the query. You can then change the value of the Parameter, and, without having to create a new Cursor for the derived Source, use that same Cursor to retrieve the results of the modified query.
The Source class has the following subclasses:
BooleanSource
DateSource
NumberSource
StringSource
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.
A Source has a data type, a type, and an identifier (ID), and all Source objects except the empty Source have one or more elements. 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".
All Source objects, except the empty Source, have one or more elements. An element of a Source has a value, which can be null. For example, the Source for the MdmPrimaryDimension object for the CHANNEL_AWJ dimension has four elements. The values of those elements are the unique values of the members of the dimension, which are the following.
CHANNEL_PRIMARY::CHANNEL::TOTAL CHANNEL_PRIMARY::CHANNEL::CAT CHANNEL_PRIMARY::CHANNEL::DIR CHANNEL_PRIMARY::CHANNEL::INT
The FundamentalMetadataObject class represents the data type of the values 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.
The data type for a primary Source is related to the SQL data type of the associated metadata object. For example, an MdmBaseAttribute that has a SQL data type of VARCHAR2(30) would produce a Source whose data type is the fundamental Source that represents OLAP Java API String values. The following code gets that fundamental Source.
fmp.getStringDataType().getSource(); // fmp is the FundamentalMetadataProvider.
A typical use of a Source for a data type is as the comparison Source for a join or a recursive join operation. As such it represents the set of all values of that data type. For examples of the use of the getDataType method, see Example 6-3, Example 6-5, and Example 6-11.
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 with the 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. You can find the type by calling the getType method of a Source.
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 type of the Source returned by the getSource method of a typical numeric MdmMeasure is the fundamental Source that represents the set of all OLAP Java API number values.
The Source for the object that contains the primary Source. For example, the type of the Source returned by the getSource method of an MdmLevelHierarchy is the Source for the MdmPrimaryDimension that contains the hierarchy.
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, distinct, extract, join, recursiveJoin, or value methods, or one of their shortcuts, has the base Source as the type.
A fundamental Source. The type of the Source returned by methods such as position and count is the fundamental Source for the OLAP Java API Integer data type. The type of the Source returned by methods that make comparisons, such as eq, le, and so on, is the fundamental Source for the Boolean data type. The type of the Source returned by methods that perform aggregate functions, such as the NumberSource methods total and average, is a fundamental Source that represents the function.
A derived Source that has the base Source as the type is a subtype of the Source from which it is derived. A derived Source that has a fundamental Source as the type is a subtype of the fundamental Source. You can use the isSubtypeOf method to determine if a Source is a subtype of another Source.
For example, in Example 5-1 the myList object is a list Source. The example uses myList to select values from prodHier, a Source for an MdmLevelHierarchy of the MdmPrimaryDimension for the PRODUCT_AWJ dimension. In the example, dp is the DataProvider.
Example 5-1 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 myList is the fundamental String Source. The type of prodHier is the Source for the PRODUCT_AWJ dimension. 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.
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_AWJ 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
Each Source also has a SourceDefinition object, which records information about the Source. Oracle OLAP uses this information internally. For example, the SourceDefinition of a derived Source records 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.
The DynamicDefinition class is a subclass of SourceDefinition. An OLAP Java API client application uses the DynamicDefinition of a Template to get the dynamic Source of the Template.
An input of a Source indicates that the elements of the Source have a relation to those of another Source. An output of a Source contains elements from which values of the Source with the output are derived. A Source with one or more outputs is somewhat like an array of arrays.
A Source can have inputs and it can have outputs. The inputs and the outputs of a Source are other Source objects.
The inputs and outputs of a base Source influence the elements of a Source that you derive from that base Source. To derive a Source, you use methods of the base Source. The derived Source can have outputs or inputs or both or neither, depending on the method and the parameters of the method.
Some Source methods, such as the value and position methods, return a Source that has an input. The join and recursiveJoin methods can return a Source that has an output. If the join operation involves a Source with an input and a Source that matches with that input, then the input acts as a filter in producing the elements of the derived Source.
This topic describes the join method, the concepts of outputs and inputs, and the matching of inputs. It provides examples of producing Source objects that have outputs, Source objects that have inputs, and join operations that match an input with a Source.
With the join method, you join the elements of one Source with those of another Source to produce a derived Source. The derived Source could have inputs or outputs. The elements of the derived Source, and whether it has any inputs or outputs, depend on the values of the parameters that you pass to the join method.
The full signature of the join method is the following.
Source join(Source joined,
Source comparison,
int comparisonRule,
boolean visible)
The Source on which you call the join method is the base of the join operation. The parameters of the method are the following.
The joined parameter is a Source object. The join method joins the elements of the base Source and the elements of the joined Source, with results that are determined by the values of the other join parameters. If the values of the joined Source are not related to the values of the base Source, that is, if neither the joined Source nor the base Source matches with an input of the other, then the join produces a Cartesian product of the elements of the base and the joined Source objects. The examples in the "Outputs of a Source" topic demonstrate this kind of join operation.
If the values of the joined Source are related to the values of the base Source, that is, if either the joined Source or the base Source is an input of the other, then the elements of the derived Source are the result of the matching of the input. The examples in "Matching a Source with an Input" demonstrate this kind of join operation.
The comparison parameter is another Source object. The join operation compares the values of the elements of the comparison Source to the values of the joined Source. The values that are the same in the joined and comparison objects participate in the join operation or are removed from participation, depending on the value of the comparisonRule parameter.
The value of the comparisonRule parameter specifies which values of the joined Source participate in the join operation. The comparisonRule value also determines the sort order of the participating values. The comparison rule is one of the static constant fields of the Source class. The basic comparison rules are the following.
COMPARISON_RULE_SELECT, which specifies that only the elements of the joined Source that are also in the comparison Source participate in the join operation.
COMPARISON_RULE_REMOVE, which specifies that only the elements of the joined Source that are not in the comparison Source participate in the join operation.
The other comparison rules are all select operations that sort the resulting values in various ways. Those rules are the following.
The visible parameter is a boolean value that specifies whether the joined Source appears as an output of the Source that is derived by the join operation. If the value of the visible parameter is true, then the derived Source has an output that contains the elements drawn from the joined Source. If the value is false, then the derived Source does not have an output for the joined Source.
The join method returns a derived Source that has the values of the elements of the base Source that are specified by the parameters of the method. Those values are the base values of the derived Source.
If the value of the visible parameter of the join method is true, then the joined Source becomes an output of the derived Source. The elements of the derived Source then have the values of the output and the base values, as specified by the other parameters of the join operation.
A derived Source can have from zero to many outputs. A Source that is an output can itself have outputs. You can get the outputs of a Source by calling the getOutputs method, which returns a List of Source objects.
The examples in this "Outputs of a Source" topic all have simple join operations that produce Source objects that have one or more outputs. Because none of the Source objects in the join operations have inputs, the values of the derived Source objects produced by the join operations are the Cartesian products of the base and the joined Source objects.
Very different results occur from a join operation that involves a Source that has an input and a Source that matches with that input. For examples of Source objects with inputs and the matching of inputs, see "Inputs of a Source" and "Matching a Source with an Input".
Example 5-2 uses the simplest signature of the join method to produce a Source that has one output. The example creates a list Source, letters, that has three elements, the values of which are A, B, and C. It also creates a list Source, names, that has three elements, the values of which are Stephen, Leo, and Molly.
Example 5-2 A Simple Join That Produces a Source with an Output
Source letters = dp.createListSource(new String[] {"A", "B", "C"});
Source names = dp.createListSource(new String[] {"Stephen", "Leo", "Molly"});
Source lettersWithNames = letters.join(names);
// Oracle OLAP translates this shortcut signature of the join method into the
// following full signature, where dp is the DataProvider for the session.
// Source letters.join(names,
// dp.getEmptySource(),
// Source.COMPARISON_RULE_REMOVE,
// true);
The letters.join(names) operation joins the elements of the base Source, letters, and the joined Source, names. Because the comparison Source has no elements, the join operation does not remove any of the elements that are in the joined Source in producing the derived Source. (The comparison Source is the empty Source that is returned by the dp.getEmptySource() parameter of the full join signature shown in the example.) The resulting derived Source, lettersWithNames, is the Cartesian product of the elements of the base letters and the joined names. Because both letters an d names have three elements, the number of elements in lettersWithNames is nine.
Because the visible parameter of letters.join(names) is true, the derived Source has an output. Because no elements were removed from the joined Source, the derived Source has the values of all of the elements of the joined Source.
A Cursor for a Source has the same structure as the Source. A Cursor for the lettersWithNames Source has a ValueCursor for the base values of the derived Source and a ValueCursor for the output values. The following table presents the values of the ValueCursor objects. The table includes headings that are not in the ValueCursor objects.
Output Values Base Values Stephen A Stephen B Stephen C Leo A Leo B Leo C Molly A Molly B Molly C
Example 5-3 demonstrates using a comparison Source that has values and the comparison rule COMPARISON_RULE_SELECT. The example uses the letter and names Source objects from Example 5-2 and adds the someNames Source. It uses someNames as the comparison Source. The output of the Source derived from the join operation has only the names that are in both the joined Source and the comparison Source.
Example 5-3 A Simple Join That Selects Elements of the Joined Source
Source someNames = dp.createListSource(new String[] {"Stephen", "Molly"});
Source lettersAndSelectedNames =
letters.join(names, someNames, Source.COMPARISON_RULE_SELECT, true);
A Cursor for the lettersAndSelectedNames Source has the values specified by the Source. The following table presents the Cursor values and has headings added.
Output Values Base Values Stephen A Stephen B Stephen C Molly A Molly B Molly C
Example 5-4 demonstrates using a comparison Source that has values and the comparison rule COMPARISON_RULE_REMOVE. That comparison rule removes from participation in the join operation those values that are the same in the joined and in the comparison Source objects. The output of the derived Source therefore has only the name from the joined Source that is not in the comparison Source.
The example has the same base, joined, and comparison Source objects as Example 5-3.
Example 5-4 A Simple Join That Removes Elements of the Joined Source
Source lettersAndNamesWithoutRemovedNames =
letters.join(names,
someNames,
Source.COMPARISON_RULE_REMOVE,
true);
A Cursor for the lettersAndNamesWithoutRemovedNames Source has the values specified by the Source. The following table presents the values and has headings added.
Output Values Base Values Leo A Leo B Leo C
If you join a Source to a Source that has an output, and if the visible parameter is true, then the join operation produces a Source that has the joined Source as an additional output. The additional output becomes the first output, as shown in Example 5-5.
Example 5-5 uses the Source objects from Example 5-3 and creates another list Source, colors, that contains the names of two colors. The example joins the colors Source to the lettersWithSelectedNames Source to produce the lettersWithSelectedNamesAndColors Source.
The lettersWithSelectedNames Source has names as an output. The lettersWithSelectedNamesAndColors Source has both colors and names as outputs. The first output is colors and the second output is names.
Example 5-5 A Simple Join That Produces a Source with Two Outputs
Source colors = dp.createListSource(new String[] {"Green", "Maroon"});
Source lettersWithSelectedNames =
letters.join(names,
someNames,
Source.COMPARISON_RULE_SELECT,
true);
Source lettersWithSelectedNamesAndColors =
lettersWithSelectedNames.join(colors);
A Cursor for the lettersWithSelectedNamesAndColors Source has the values shown in the following table. The table has headings added.
Output 1 Values Output 2 Values Base Values
Green Stephen A
Green Stephen B
Green Stephen C
Green Molly A
Green Molly B
Green Molly C
Maroon Stephen A
Maroon Stephen B
Maroon Stephen C
Maroon Molly A
Maroon Molly B
Maroon Molly C
If the visible parameter of a join method is false, then the joined Source participates in the join operation but does not appear as an output of the Source derived by the join. Example 5-6 uses the joinHidden shortcut method to join the lettersWithSelectedNames and the colors Source objects from Example 5-5. The example includes in a comment the full join signature for the joinHidden shortcut.
Example 5-6 A Simple Join That Hides An Output
Source lettersWithSelectedNamesAndHiddenColors = lettersWithSelectedNames.joinHidden(colors); // The full signature of the joinHidden shortcut method is // Source result = base.join(joined, // dp.getEmptySource(), // Source.COMPARISON_RULE_REMOVE, // false); // So if Source base = lettersWithSelectedNames and // Source joined = colors, then the result Source is the same as the // lettersWithSelectedNamesAndHiddenColors Source.
A Cursor for the lettersWithSelectedNamesAndHiddenColors Source has the values shown in the following table. The table has headings added.
Note that the derived lettersWithSelectedNamesAndHiddenColors Source still has twelve elements, even though the values for the colors Source do not appear as output values. The derived Source has one set of the six values of the lettersWithSelectedNames Source for each value of the hidden colors Source.
Example 5-5 displays the following output.
Output Values Base Values Stephen A Stephen B Stephen C Molly A Molly B Molly C Stephen A Stephen B Stephen C Molly A Molly B Molly C
The examples in the "Outputs of a Source" topic all produce derived Source objects that have elements that are the Cartesian product of the unrelated base and joined Source objects. While such an operation can be useful, a more powerful aspect of Source objects is the ability to relate the elements of one Source to another Source. When such a relationship exists, you can derive other Source objects that are the result of operations between the related elements. For example, you can derive a Source that contains only selected elements of another Source. This relationship between elements is represented by the input of a Source.
A Source with an input is an incomplete specification of data. The input represents the type of Source that can have the elements that a join operation requires to complete the data specification. Before you can retrieve the data with a Cursor, you must match the input with a Source that has the elements that complete the specification.
You match an input with a Source by using the join or recursiveJoin method. The match occurs between the base Source and the joined Source.
The matching of an input acts as a filter so that the Source derived by the join operation has only the elements of the base Source whose values are related to those of the elements of the joined Source. The rules related to matching a Source with an input are described in "Matching a Source with an Input". That topic has examples that produce derived Source objects that are the result of the matching of an input.
A Source can have from zero to many inputs. You can get all of the inputs of a Source by calling the getInputs method.
Some primary Source objects have inputs. You can derive a Source that has an input by using some methods of the Source class.
The primary Source objects for the MdmDimensionedObject subclasses MdmAttribute and MdmMeasure have inputs. The primary Source for an MdmAttribute has one input. The primary Source for an MdmMeasure has one or more inputs.
The inputs of an MdmAttribute or an MdmMeasure are the Source objects for the MdmPrimaryDimension objects that dimension the attribute or measure. To get the value of an attribute or a measure, you must join the attribute or measure with a Source that contains the related dimension members. The join operation matches the input of the attribute or measure with the Source that contains the dimension members. Example 5-7 matches the input of an attribute with the dimension of that attribute. Example 5-8 matches the inputs of a measure with the dimensions of that measure.
Some Source methods always return a Source that has an input. The Source returned by the extract, position, or value method has the base Source as an input. You can use these methods to produce a Source whose elements are derived, or filtered, from the elements of another Source.
The value method returns a Source that has the elements of the base Source and has the base Source as an input. You typically use the Source returned by the value method as the base or joined Source of a join method, or sometimes as the comparison Source. Several examples in this chapter and in Chapter 6 use the value method.
The position method returns a Source that has the position of each element of the base Source and that has the base Source as an input. For an example of using the position method, see Example 6-4.
You use the extract method when elements of the Source objects that you want to join have Source objects as values. For examples of using the extract method, see Example 5-12, Example 6-8, Example 6-13, and Example 6-14.
The input of a Source derived by the position or value method, and an input intrinsic to an MdmDimensionedObject, are regular inputs. A regular input relates the elements of the Source with the input to the elements of the Source that matches with the input. You can get the regular inputs by calling the getRegularInputs method.
The input of a Source returned by the extract method is an extraction input. You can get the extraction inputs by calling the getExtractionInputs method.
In a join operation, the matching of a Source with an input occurs only between the base Source and the joined Source. A Source matches with an input if one of the following conditions is true.
The Source is the same object as the input or it is a subtype of the input.
The Source has an output that is the same object as the input or the output is a subtype of the input.
The join operation looks for the conditions in the order shown in the preceding list. It searches the list of outputs of the Source recursively, including any outputs of an output, looking for a match with the input. The search ends with the first matching Source. An input can match with only one Source.
When a Source with an input is joined to a Source that matches with the input, the derived Source returned by the join method has the elements of the base that are related to the elements specified by the parameters of the method. The derived Source does not have the input.
Matching a Source with an input does not affect the outputs of the base Source or the joined Source. If a base Source has an output that matches with the input of the joined Source, then 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 the joining of the Source for an MdmBaseAttribute to the Source for an MdmPrimaryDimension. The example gets the local value attribute from the MdmPrimaryDimension for the CHANNEL_AWJ dimension. The Source for the attribute, locValAttr, has the Source for the MdmPrimaryDimension as an input.
In the example, locValAttr is the base Source of the join operation and chanDim is the joined Source. Because chanDim is an instance of the Source for the MdmPrimaryDimension for the CHANNEL_AWJ dimension, chanDim matches with the input of locValAttr. The result of the join is dimMembersWithLocalValue, which has chanDim as an output and does not have any inputs.
The locValAttr Source has four elements because each of the four members of the CHANNEL_AWJ dimension has a different local value. The Source derived by the join operation, dimMembersWithLocalValue, has four elements. The value of each element is the dimension member and the related attribute value. The dimension member is a value from the output and the attribute value is from the base.
Example 5-7 demonstrates matching the input of a base Source with the joined Source. In the example, mdmDBSchema is the MdmDatabaseSchema for the GLOBAL schema.
Example 5-7 Getting an Attribute for a Dimension Member
MdmStandardDimension mdmChanDim =
mdmDBSchema.findOrCreateStandardDimension("CHANNEL_AWJ");
Source chanDim = mdmChanDim.getSource();
Source locValAttr = mdmChanDim.getLocalValueAttribute().getSource();
Source dimMembersWithLocalValue = locValAttr.join(chanDim);
A Cursor for the dimMembersWithLocalValue Source has the values shown in the following table. The output values are the unique dimension member values derived from the joined Source, chanDim. The base values are derived from the base Source, locValAttr. The table has headings added.
Output Values Base Values
CHANNEL_PRIMARY::TOTAL_CHANNEL::TOTAL TOTAL
CHANNEL_PRIMARY::CHANNEL::CAT CAT
CHANNEL_PRIMARY::CHANNEL::DIR DIR
CHANNEL_PRIMARY::CHANNEL::INT INT
Example 5-8 demonstrates getting values from a measure. The example gets the MdmCube that contains the UNIT_PRICE measure and gets the MdmBaseMeasure for the measure from that cube. The cube, and the measures of the cube, are dimensioned by the PRODUCT_AWJ and TIME_AWJ dimensions. The example gets the MdmPrimaryDimension objects for those dimensions and gets the Source objects for those metadata objects.
The Source for the measure, unitPrice, has the Source objects for the two MdmPrimaryDimension objects as inputs. The example joins the Source for the measure with the Source objects for the dimensions. The join operations match the inputs of the measure with the Source objects for the dimensions.
The example first joins the Source for the PRODUCT_AWJ dimension to the Source for the measure. That unitPrice.join(prodDim) operation derives a Source that has base values from unitPrice and has prodDim as an output. It also has the Source for the TIME_AWJ dimension as an input. The next join operation joins the Source derived by unitPrice.join(prodDim) with timeDim, the Source for the TIME_AWJ dimension. That join operation matches the input of the Source derived by unitPrice.join(prodDim) with timeDim.
The Source derived by the second join operation is pricesByProductAndTime. That Source has no inputs and has the Source objects for the PRODUCT_AWJ and TIME_AWJ dimensions as outputs. A Cursor for pricesByProductAndTime contains the price of each product value for every time value.
The example finally calls the count method of pricesByProductAndTime. That method returns the NumberSource numPricesByProductAndTime, which contains the number of elements of the pricesByProductAndTime Source. A Cursor for the numPricesByProductAndTime Source contains the value 4998, which is the number of measure values for the product and time tuples.
Example 5-8 demonstrates matching the inputs of the base Source with the joined Source. In the example, mdmDBSchema is the MdmDatabaseSchema for the GLOBAL schema.
Example 5-8 Getting Measure Values
MdmCube mdmPriceCube =
mdmDBSchema.findOrCreateCube("PRICE_CUBE_AWJ");
MdmBaseMeasure mdmUnitPrice =
mdmPriceCube.findOrCreateBaseMeasure("UNIT_PRICE");
MdmStandardDimension mdmProdDim =
mdmDBSchema.findOrCreateStandardDimension("PRODUCT_AWJ");
MdmTimeDimension mdmTimeDim =
mdmDBSchema.findOrCreateTimeDimension("TIME_AWJ");
Source prodDim = mdmProdDim.getSource();
Source timeDim = mdmTimeDim.getSource();
Source unitPrice = mdmUnitPrice.getSource();
Source pricesByProductAndTime = unitPrice.join(prodDim).join(timeDim);
NumberSource numPricesByProductAndTime = pricesByProductAndTime.count();
To produce a Source that contains only the measure values for certain products and times, you need to join the Source for the measure with Source objects that specify the dimension values that you want. You can produce such a selection by using methods of the primary Source for the dimension. One means of producing a Source that represents a selection of values of a Source is to use the value method.
In Example 5-9, the lettersValue Source is returned by the letters.value() method. The lettersValue Source has letters as an input. The input represents a relation between the values of the Source with the input and the values of the Source that matches with the input.
In the example, the join operation has letters as the base Source and lettersValue as the joined Source. The base Source, letters, matches with the input of lettersValue, which is also letters, because they are the same. The Source produced by the join operation, lettersByLettersValue has lettersValue as an output. It does not have an input. Each element of lettersByLettersValue has a base value from letters and the related value from lettersValue.
Example 5-9 Using the value Method to Relate a Source to Itself
Source letters = dp.createListSource(new String[] {"A", "B", "C"});
Source lettersValue = letters.value();
Source lettersByLettersValue = letters.join(lettersValue);
A Cursor for the lettersByLettersValue Source has the values shown in the following table. The table has headings added.
Output Values Base Values
A A
B B
C C
Because lettersByLettersValue contains only those values of the base and joined Source objects that are related, the base values of the Cursor for lettersByLettersValue Source are the same as the output values. If the base and joined Source objects had been unrelated, as in letters.join(letters), then the Source produced by the join operation would contain the Cartesian product of the base and joined Source objects.
By using the value method, you can derive a Source that is a selection of the elements of another Source. Example 5-10 selects two elements from the Source for the PRODUCT_AWJ dimension from Example 5-7. The example demonstrates a base Source matching with the input of the joined Source.
Example 5-10 Using the value Method to Select Elements of a Source
Source productsToSelect = dp.createListSource(new String[]
{"PRODUCT_PRIMARY::ITEM::ENVY EXE",
"PRODUCT_PRIMARY::ITEM::ENVY STD"});
Source selectedProducts = prodDim.join(prodDim.value(),
productsToSelect,
Source.COMPARISON_RULE_SELECT,
false); // Hide the output.
A Cursor for the productsToSelect Source has the following values.
PRODUCT_PRIMARY::ITEM::ENVY EXE PRODUCT_PRIMARY::ITEM::ENVY STD
A Cursor for the selectedProducts Source has the following values.
PRODUCT_PRIMARY::ITEM::ENVY EXE PRODUCT_PRIMARY::ITEM::ENVY STD
The two Source objects contain the same values. However, the types of the objects are different. The type of the productsToSelect Source is the Source for the FundamentalMetadataObject for the String data type. The type of the selectedProducts Source is prodDim because selectedProducts is derived from prodDim. Therefore, selectedProducts is a subtype of prodDim and as such it can match with a Source that has the Source for the PRODUCT_AWJ dimension as an input, as shown in Example 5-11.
Example 5-11 selects elements from the Source objects for two dimensions and then gets the measure values for the selected dimension members. Example 5-11 uses the same dimensions and measure as in Example 5-8. In Example 5-11, however, the Source objects that match with the inputs of the Source for the measure are not the Source objects for the dimensions. Instead they are subtypes of the Source objects for the dimensions. The subtypes specify selected members of the dimensions. The Source that is derived by joining the measure with the dimensions, pricesForSelectedProductsAndTimes, has six elements, which specify only the measure values for the two products for the three time values, instead of the 4998 elements of the pricesByProductAndTime Source in Example 5-8. In Example 5-11, mdmDBSchema is the MdmDatabaseSchema for the GLOBAL schema.
Example 5-11 Using Derived Source Objects to Select Measure Values
// Create lists of product and time dimension members.
Source productsToSelect = dp.createListSource(new String[]
{"PRODUCT_PRIMARY::ITEM::ENVY EXE",
"PRODUCT_PRIMARY::ITEM::ENVY STD"});
Source timesToSelect = dp.createListSource(new String[]
{"CALENDAR_YEAR::MONTH::2000.01",
"CALENDAR_YEAR::MONTH::2001.01",
"CALENDAR_YEAR::MONTH::2002.01"});
// Get the PRICE_CUBE_AWJ cube.
MdmCube mdmPriceCube = mdmDBSchema.findOrCreateCube("PRICE_CUBE_AWJ");
// Get the UNIT_PRICE measure from the cube.
MdmBaseMeasure mdmUnitPrice =
mdmPriceCube.findOrC*reateBaseMeasure("UNIT_PRICE");
// Get the PRODUCT_AWJ and TIME_AWJ dimensions.
MdmStandardDimension mdmProdDim =
mdmDBSchema.findOrCreateStandardDimension("PRODUCT_AWJ");
MdmTimeDimension mdmTimeDim =
mdmDBSchema.findOrCreateTimeDimension("TIME_AWJ");
// Get the Source objects for the dimensions and the measure.
Source prodDim = mdmProdDim.getSource();
Source timeDim = mdmTimeDim.getSource();
Source unitPrice = mdmUnitPrice.getSource();
// Using the value method, derive Source objects that specify the selected
// dimension members.
Source selectedProducts = prodDim.join(prodDim.value(),
productsToSelect,
Source.COMPARISON_RULE_SELECT,
false);
Source selectedTimes = timeDim.join(timeDim.value(),
timesToSelect,
Source.COMPARISON_RULE_SELECT,
false);
// Derive a Source that specifies the unitPrice values for the selected products
// and times.
Source pricesForSelectedProductsAndTimes = unitPrice.join(selectedProducts)
.join(selectedTimes);
A Cursor for the pricesForSelectedProductsAndTimes Source has the values shown in the following table. The table has headings added.
Month Product Price
----------------------------- ------------------------------- -------
CALENDAR_YEAR::MONTH::2000.01 PRODUCT_PRIMARY::ITEM::ENVY EXE 3358.02
CALENDAR_YEAR::MONTH::2000.01 PRODUCT_PRIMARY::ITEM::ENVY STD 3000.11
CALENDAR_YEAR::MONTH::2001.01 PRODUCT_PRIMARY::ITEM::ENVY EXE 3223.28
CALENDAR_YEAR::MONTH::2001.01 PRODUCT_PRIMARY::ITEM::ENVY STD 2426.07
CALENDAR_YEAR::MONTH::2002.01 PRODUCT_PRIMARY::ITEM::ENVY EXE 3008.95
CALENDAR_YEAR::MONTH::2002.01 PRODUCT_PRIMARY::ITEM::ENVY STD 2140.71
The extract method derives a Source that has the base Source as an input. You use the extract method when the values of the elements of a Source are Source objects themselves.
Example 5-12 uses the selectValues method to derive two selections of elements from a StringSource for the PRODUCT_AWJ dimension. The selectValues method is a shortcut for the full join signature of the methods in Example 5-10 and Example 5-11 that produce the selectedProducts and selectedTimes Source objects.
Example 5-12 creates a list Source, sourcesToCombine, that has the two derived Source objects as element values. The sourcesToCombine.extract() method produces sourcesToCombineWithAnInput, which is a Source that has sourcesToCombine as an input. The join operation sourcesToCombineWithAnInput.joinHidden(sourcesToCombine) matches the input of sourcesToCombineWithAnInput with the joined sourcesToCombine and produces combinedSources, which has no inputs or outputs. A shortcut for this combining of Source elements is the appendValues method.
Example 5-12 Extracting Elements of a Source
MdmStandardDimension mdmProdDim =
mdmDBSchema.findOrCreateStandardDimension("PRODUCT_AWJ");
StringSource prodDim = (StringSource) mdmProdDim.getSource();
Source productsToSelect = prodDim.selectValues(new String[]
{"PRODUCT_PRIMARY::ITEM::ENVY ABM",
"PRODUCT_PRIMARY::ITEM::ENVY EXE",
"PRODUCT_PRIMARY::ITEM::ENVY STD"});
Source moreProductsToSelect = prodDim.selectValues(new String[]
{"PRODUCT_PRIMARY::ITEM::SENT FIN",
"PRODUCT_PRIMARY::ITEM::SENT MM",
"PRODUCT_PRIMARY::ITEM::SENT STD"});
Source sourcesToCombine =
dp.createListSource(new Source[] {productsToSelect, moreProductsToSelect});
Source sourcesToCombineWithAnInput = sourcesToCombine.extract();
Source combinedProducts =
sourcesToCombineWithAnInput.joinHidden(sourcesToCombine);
A Cursor for the combinedProducts Source has the following values.
PRODUCT_PRIMARY::ITEM::ENVY ABM PRODUCT_PRIMARY::ITEM::ENVY EXE PRODUCT_PRIMARY::ITEM::ENVY STD PRODUCT_PRIMARY::ITEM::SENT FIN PRODUCT_PRIMARY::ITEM::SENT MM PRODUCT_PRIMARY::ITEM::SENT STD
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.
Example 5-13 in this topic is a very simple demonstration of using a Parameter object. A typical use of a Parameter is to specify the page edges of a cube, as shown in Example 6-9. 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 retrieve the new set of values.
Example 5-13 demonstrates the use of a Parameter and a parameterized Source to specify a member in a dimension. The example gets the MdmStandardDimension for the PRODUCT_AWJ dimension and gets the Source for the MdmStandardDimension cast as a StringSource.
The example creates a StringParameter object that has a dimension member as the initial value. It then creates a parameterized Source, paramProdSel, by using the createSource method of the StringParameter. Next it uses paramProdSel as the comparison Source in a join operation that selects the dimension member.
The example gets the Source for the local value attribute of the dimension. It joins that Source, locValAttr, with paramProdSel. That join operation produces the dimMemberWithLocalValue Source.
The example creates a Cursor for dimMemberWithLocalValue and displays the value of the Cursor. After resetting the Cursor position and changing the value of the prodParam StringParameter, the example displays the value of the Cursor again.
The dp object is the DataProvider. The getContext method gets a Context11g object that has a method that commits the current Transaction and a method that displays the values of a Cursor.
Example 5-13 Using a Parameterized Source to Change a Dimension Selection
MdmStandardDimension mdmProdDim =
mdmDBSchema.findOrCreateStandardDimension("PRODUCT_AWJ");
StringSource prodDim = (StringSource) mdmProdDim.getSource();
StringParameter prodParam =
new StringParameter(dp, "PRODUCT_PRIMARY::FAMILY::LTPC");
Source prodParamSrc = prodParam.createSource();
Source paramProdSel = prodDim.join(prodDim.value(), prodParamSrc);
Source locValAttr = mdmProdDim.getLocalValueAttribute().getSource();
Source dimMemberWithLocalValue = locValAttr.join(paramProdSel);
// Commit the Transaction.
getContext().commit();
// Create a Cursor for the Source.
CursorManager cursorMngr = dp.createCursorManager(dimMemberWithLocalValue);
Cursor cursor = cursorMngr.createCursor();
// Display the value of the Cursor.
getContext().displayCursor(cursor);
// Change the product parameter value.
prodParam.setValue("PRODUCT_PRIMARY::FAMILY::DTPC");
// Reset the Cursor position to 1
cursor.setPosition(1);
// Display the value of the Cursor again.
getContext().displayCursor(cursor);
The Cursor for dimMemberWithLocalValue displays the following.
PRODUCT_PRIMARY::FAMILY::LTPC,LTPC
After changing the value of the StringParameter and resetting the position of the Cursor, the Cursor for dimMemberWithLocalValue displays the following.
PRODUCT_PRIMARY::FAMILY::DTPC,DTPC
This appendix contains the code for the SingleSelectionTemplate class. This class is used by the examples in Chapter 7, "Using a TransactionProvider", and Chapter 10, "Creating Dynamic Queries".
The following is the SingleSelectionTemplate.java class.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import oracle.olapi.data.cursor.CursorManager;
import oracle.olapi.data.cursor.ValueCursor;
import oracle.olapi.data.source.DataProvider;
import oracle.olapi.data.source.DynamicDefinition;
import oracle.olapi.data.source.Source;
import oracle.olapi.data.source.StringSource;
import oracle.olapi.data.source.SourceGenerator;
import oracle.olapi.data.source.Template;
import oracle.olapi.metadata.mdm.MdmAttribute;
import oracle.olapi.metadata.mdm.MdmDimensionMemberInfo;
import oracle.olapi.metadata.mdm.MdmHierarchy;
import oracle.olapi.metadata.mdm.MdmPrimaryDimension;
import oracle.olapi.transaction.TransactionProvider;
import oracle.olapi.transaction.NotCommittableException;
import oracle.olapi.transaction.metadataStateManager.MetadataState;
/**
* A Template that joins Source objects for selected members of
* dimension hierarchies to a Source for a measure.
*/
public class SingleSelectionTemplate extends Template
{
// Variable to store the DynamicDefinition.
private DynamicDefinition dynamicDef;
/**
* Creates a SingleSelectionTemplate.
*/
public SingleSelectionTemplate(Source measure, DataProvider dataProvider)
{
super(new SingleSelectionTemplateState(measure), dataProvider);
dynamicDef = createDynamicDefinition(
new SingleSelectionTemplateGenerator(dataProvider));
}
/**
* Gets the Source produced by the SingleSelectionTemplateGenerator
* from the DynamicDefinition.
*/
public final Source getSource()
{
return dynamicDef.getSource();
}
/**
* Gets the Source for the measure stored by the SingleSelectionTemplateState.
*/
public Source getMeasure()
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
return state.measure;
}
/**
* Specifies the Source for the measure stored by the
* SingleSelectionTemplateState.
*/
public void setMeasure(Source measure)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
state.measure = measure;
setCurrentState(state);
}
/**
* Gets the List of MdmDimensionMemberInfo objects for the selected members
* of the dimensions.
*/
public List getDimMemberInfos()
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
return Collections.unmodifiableList(state.dimMemberInfos);
}
/**
* Adds an MdmDimensionMemberInfo to the List of
* MdmDimensionMemberInfo objects.
*/
public void addDimMemberInfo(MdmDimensionMemberInfo mdmDimMemberInfo)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
state.dimMemberInfos.add(mdmDimMemberInfo);
setCurrentState(state);
}
/**
* Changes the member specified for a dimension.
*/
public void changeSelection(MdmDimensionMemberInfo mdmDimMemberInfo)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
int i = 0;
Iterator dimMemberInfosItr = state.dimMemberInfos.iterator();
while (dimMemberInfosItr.hasNext())
{
MdmDimensionMemberInfo mdmDimMemberInfoInList =
(MdmDimensionMemberInfo)dimMemberInfosItr.next();
MdmPrimaryDimension mdmPrimDim1 = mdmDimMemberInfo.getPrimaryDimension();
MdmPrimaryDimension mdmPrimDim2 =
mdmDimMemberInfoInList.getPrimaryDimension();
//String value = (String)valuesItr.next();
if (mdmPrimDim1.getName().equals(mdmPrimDim2.getName()))
{
state.dimMemberInfos.remove(i);
state.dimMemberInfos.add(i, mdmDimMemberInfo);
break;
}
i++;
}
setCurrentState(state);
}
/**
* Gets the short value description of the each of the dimension members
* specified by the list of MdmDimensionMemberInfo objects and returns
* the descriptions in a StringBuffer.
*/
public StringBuffer getMemberShortDescrs(DataProvider dp)
{
boolean firsttime = true;
List mdmDimMemInfoList = getDimMemberInfos();
StringBuffer shortDescrForMemberVals = new StringBuffer(" ");
Iterator mdmDimMemInfoListItr = mdmDimMemInfoList.iterator();
while(mdmDimMemInfoListItr.hasNext())
{
MdmDimensionMemberInfo mdmDimMemInfo =
(MdmDimensionMemberInfo)mdmDimMemInfoListItr.next();
MdmPrimaryDimension mdmPrimDim = mdmDimMemInfo.getPrimaryDimension();
MdmAttribute mdmShortDescrAttr =
mdmPrimDim.getShortValueDescriptionAttribute();
Source shortDescrAttr = mdmShortDescrAttr.getSource();
MdmHierarchy mdmHier = mdmDimMemInfo.getHierarchy();
StringSource hierSrc = (StringSource) mdmHier.getSource();
Source memberSel = hierSrc.selectValue(mdmDimMemInfo.getUniqueValue());
Source shortDescrForMember = shortDescrAttr.joinHidden(memberSel);
// Commit the current transaction.
try
{
(dp.getTransactionProvider()).commitCurrentTransaction();
}
catch (Exception ex)
{
println("Could not commit the Transaction. " + ex);
}
}
CursorManager cmngr = dp.createCursorManager(shortDescrForMember);
ValueCursor valCursor = (ValueCursor)cmngr.createCursor();
String shortDescrForMemberVal = valCursor.getCurrentString();
if(firsttime)
{
shortDescrForMemberVals.append(shortDescrForMemberVal);
firsttime = false;
}
else
{
shortDescrForMemberVals.append(", " + shortDescrForMemberVal);
}
}
return shortDescrForMemberVals;
}
/**
* Inner class that implements the MetadataState object for this Template.
* Stores data that can be changed by its SingleSelectionTemplate.
* The data is used by a SingleSelectionTemplateGenerator in producing
* a Source for the SingleSelectionTemplate.
*/
private static class SingleSelectionTemplateState
implements MetadataState
{
public Source measure;
public ArrayList dimMemberInfos;
/**
* Creates a SingleSelectionTemplateState.
*/
public SingleSelectionTemplateState(Source measure)
{
this(measure, new ArrayList());
}
private SingleSelectionTemplateState(Source measure,
ArrayList dimMemberInfos)
{
this.measure = measure;
this.dimMemberInfos = dimMemberInfos;
}
public Object clone()
{
return new SingleSelectionTemplateState(measure,
(ArrayList)
dimMemberInfos.clone());
}
}
/**
* Inner class that implements the SourceGenerator object for this Template.
* Produces a Source based on the data values of a SingleSelectionTemplate.
*/
private static final class SingleSelectionTemplateGenerator
implements SourceGenerator
{
DataProvider dp = null;
/**
* Creates a SingleSelectionTemplateGenerator.
*/
public SingleSelectionTemplateGenerator(DataProvider dataProvider)
{
dp = dataProvider;
}
/**
* Generates a Source for the SingleSelectionTemplate.
*/
public Source generateSource(MetadataState state)
{
SingleSelectionTemplateState castState =
(SingleSelectionTemplateState)state;
Source result = castState.measure;
Iterator dimMemberInfosItr = castState.dimMemberInfos.iterator();
while (dimMemberInfosItr.hasNext())
{
MdmDimensionMemberInfo mdmDimMemInfo =
(MdmDimensionMemberInfo)dimMemberInfosItr.next();
MdmHierarchy mdmHier = mdmDimMemInfo.getHierarchy();
StringSource hierSrc = (StringSource) mdmHier.getSource();
Source memberSel = hierSrc.selectValue(mdmDimMemInfo.getUniqueValue());
// Join the Source objects for the selected dimension members
// to the measure.
result = result.joinHidden(memberSel);
}
return result;
}
}
}
This chapter introduces the Oracle OLAP Java application programming interface (API). The chapter includes the following topics:
The Oracle OLAP Java API is an application programming interface that provides access to the online analytic processing (OLAP) technology in Oracle Database with the OLAP option. This topic lists operations that an OLAP Java API client application can perform, describes the classes in the OLAP Java API, describes the objects in a dimensional data model, and discusses organizing data for online analytical processing.
For a description of the advantages of OLAP technology, see Oracle OLAP User's Guide. That document describes the capabilities that Oracle OLAP provides for the analysis of multidimensional data by business intelligence and advanced analytical applications. It describes in depth the dimensional data model, and it discusses the database administration and management tasks related to Oracle OLAP.
Using the OLAP Java API, your can develop client applications that do the following operations.
Establish one or more user sessions in a JDBC connection to an Oracle Database instance. Multiple user sessions can share the same connection and the same cache of metadata objects.
Manage OLAP transactions with the database.
Implement a dimensional data model using OLAP metadata objects.
Create and maintain analytic workspaces.
Create logical metadata objects and map them to relational sources.
Deploy the metadata objects as an analytic workspace or as relational tables and views and commit the objects to the database.
Explore the metadata to discover the data that is available for viewing or for analysis.
Construct analytical queries of the multidimensional data. Enable end users to create queries that specify and manipulate the data according to the needs of the user (for example, selecting, aggregating, and calculating data).
Modify queries, rather than totally redefine them, as application users refine their analyses.
Retrieve query results that are structured for display in a multidimensional format.
For more information on some of these operations, see "Tasks That an OLAP Java API Application Performs".
The OLAP Java API has classes that represent the following types of objects.
User sessions
Transactions
Metadata objects
Build items, processes, specifications, and commands
Queries
Cursors that retrieve the data of a query
Expressions that specify data objects, such as a column in a relational table or view, or that specify a function or command that operates on data
Table 1-1 lists packages that contain the majority of the OLAP Java API classes. These packages are under the oracle.olapi package. The table contains brief descriptions of the package contents.
Table 1-1 Packages of the OLAP Java API under oracle.olapi
| Package | Description |
|---|---|
|
|
Contains classes that represent cursor managers and cursors that retrieve the data specified by a |
|
|
Contains classes that represent data sources and cursor specifications. You use |
|
|
Contains classes that represent metadata objects, classes that map the metadata objects to relational data sources, and classes that deploy the metadata objects in an analytic workspace or in relational database structures. For a description of these packages, see Chapter 2, "Understanding OLAP Java API Metadata". For information on using the classes in these packages, see Chapter 3, "Discovering Metadata" and Chapter 4, "Creating Metadata and Analytic Workspaces". |
|
|
Contains classes that support the internationalization of messages for |
|
|
Contains a class that represents a session in a connection to an Oracle database. |
|
Contains classes that represent the items and commands that specify how Oracle OLAP builds analytic workspace objects and classes that implement a syntax for creating SQL-like expressions. You use | |
|
|
Contains classes that represent transactions with Oracle OLAP in an Oracle Database instance. You use |
The OLAP Java API also has packages organized under the oracle.express package. These packages date from the earliest versions of the API. The classes that remain in these packages are mostly Exception classes for exceptions that occur during interactions between Oracle OLAP and a client application.
For information on obtaining the OLAP Java API software and on the requirements for using it to develop applications, see Appendix A, "Setting Up the Development Environment."
Data warehousing and OLAP applications are based on a multidimensional view of data. This view is implemented in a dimensional data model that includes the following dimensional objects. For more detailed information about all of these concepts, see Oracle OLAP User's Guide and Oracle Warehouse Builder Concepts.
Cubes are containers for measures that have the same set of dimensions. A cube usually corresponds to a single relational fact table or view. The measures of a cube contain facts and the dimensions give shape to the fact data. Typically, the dimensions form the edges of the cube and the measure data is the body of the cube. For example, you could organize data on product units sold into a cube whose edges contain values for members from time, product, customer, and channel dimensions and whose body contains values from a measure of the quantity of units sold and a measure of sales amounts.
The OLAP concept of a cube edge is not represented by a metadata object in the OLAP Java API, but edges are often incorporated into the design of applications that use the OLAP Java API. Each edge contains values of members from one or more dimensions. Although there is no limit to the number of edges on a cube, data is often organized for display purposes along three edges, which are referred to as the row edge, column edge, and page edge.
Measures contain fact data in a cube. The measure values are organized and identified by dimensions. Measures are usually multidimensional. Each measure value is identified by a unique set of dimension members. This set of dimension members is called a tuple.
Dimensions contain lists of unique values that identify and categorize data in a measure. Commonly-used dimensions are customers, products, and times. Typically, a dimension has one or more hierarchies that organize the dimension members into parent-child relationships.
By specifying dimension members, measures, and calculations to perform on the data, end users formulate business questions and get answers to their queries. For example, using a time dimension that categorizes data by month, a product dimension that categorizes data by unit item, and a measure that contains data for the quantities of product units sold by month, you can formulate a query that asks if sales of a product unit were higher in January or in June.
Hierarchies are components of a dimension that organize dimension members into parent-child relationships. Typically, in the user interface of a client application, an end user can expand or collapse a hierarchy by drilling down or up among the parents and children. The measure values for the parent dimension members are aggregations of the values of the children.
A dimension can have more than one hierarchy. For example, a time dimension could have a calendar year hierarchy and a fiscal year hierarchy. A hierarchy can be level-based or value-based.
In a level-based hierarchy, a parent must be in a higher level than the children of that parent. In a cube, the measure values for the parents are typically aggregated from the values of the children. For example, a time dimension might have levels for year, quarter, and month. The month level contains the base data, which is the most detailed data. The measure value for a quarter is an aggregation of the values of the months that are the children of the quarter and the measure value for a year is the aggregation of the quarters that are children of the year. Typically each level is mapped to a different column in the relational dimension table.
In a value-based hierarchy, the parent and the child dimension members typically come from the same column in the relational table. Another column identifies the parent of a member. For example, a value hierarchy could contain all employees of a company and identify the manager for each employee that has one. All employees, including managers, would come from the same column. Another column would contain the managers of the employees.
Levels are components of a level-based hierarchy. A level can be associated with more than one hierarchy. A dimension member can belong to only one level.
A level typically corresponds to a column in a dimension table or view. The base level is the primary key.
Attributes contain information related to the members of a dimension. An end user can use an attribute to select data. For example, an end user might select a set of products by using an attribute that has a descriptive name of each product. An attribute is contained by a dimension.
A query is a specification for a particular set of data. The term query in the OLAP Java API refers to a Source object that specifies a set of data and can include aggregations, calculations, or other operations to perform using the data. The data and the operations on it define the result set of the query. In this documentation, the general term query refers to a Source object.
The API has a Query class in the oracle.olapi.syntax package. A Query represents a multirow, multicolumn result set that is similar to a relational table, a SQL SELECT statement, or an OLAP function. You use a Query object in mapping a dimension or measure to a relational table or view.
In the OLAP Java API, the dimensional data objects are represented by Multidimensional Model (MDM) classes. These classes are in the oracle.olapi.metadata.mdm package. Related classes are in the oracle.olapi.metadata package and the other packages under it. For detailed information about those classes, see Chapter 2, "Understanding OLAP Java API Metadata".
The OLAP Java API makes it possible for Java applications (including applets) to access data that resides in an Oracle data warehouse. A data warehouse is a relational database that is designed for query and analysis, rather than for transaction processing. Warehouse data often conforms to a star schema, which is a dimensional data model for a relational database. A star schema consists of one or more fact tables and one or more dimension tables. The fact tables have columns that contain foreign keys to the dimension tables. Typically, a data warehouse is created from a transaction processing database by an extraction transformation transport (ETT) tool, such as Oracle Warehouse Builder.
For the data in a data warehouse to be accessible to an OLAP Java API application, a database administrator must ensure that the data warehouse is configured according to an organization that is supported by Oracle OLAP. The star schema is one such organization, but not the only one. See Oracle OLAP User's Guide for information about supported data warehouse configurations.
Once the data is organized in the warehouse, you can use an OLAP Java API application to design an OLAP dimensional data model of cubes, measures, dimensions, and so on, and to create the logical OLAP metadata objects that implement the model. You map the metadata objects to data in the warehouse and build an analytic workspace. Building the analytic workspace populates the OLAP views and other storage structures with the data that the OLAP metadata objects represent.
You can also use Analytic Workspace Manager to do the same tasks. See Oracle OLAP User's Guide for information about creating an analytic workspace with Analytic Workspace Manager.
An OLAP Java API application can get the OLAP metadata objects created either by Analytic Workspace Manager or through the OLAP Java API. It can use the metadata objects to create queries that operate on the data in the warehouse.
The collection of warehouse data in an analytic workspace is the data store to which the OLAP Java API gives access. Of course, the scope of the data that a user has access to is limited by the privileges granted to the user by the database administrator.
In addition to ensuring that data and metadata have been prepared appropriately, you must ensure that application users can make a JDBC connection to the data store and that users have database privileges that give them access to the data. For information about specifying privileges, see Oracle OLAP User's Guide. For information about establishing a connection, see Chapter 3, "Discovering Metadata".
Oracle OLAP metadata objects organize and describe the data that is available to a client application. The metadata objects contain other information, as well, such as the data type of the data. However, you cannot retrieve data directly from a metadata object. To specify the data that you want, you must create a query. In specifying the data, you usually must specify one or more dimension member values. To retrieve the specified data, you create a Cursor. This topic briefly describes those actions.
Another way that you can query the data contained in OLAP metadata objects is through SQL queries of the views that Oracle OLAP creates for the metadata objects. For information about querying these views, see "Using OLAP Views" in Chapter 2, "Understanding OLAP Java API Metadata".
Queries are represented by oracle.olapi.data.source.Source objects. You get a Source from a metadata object and use that Source object in specifying the data that you want to get. Source classes have methods for selecting and performing operations on the data. You can use the methods to manipulate data in any way that the user requires. For information about Source objects, see Chapter 5, "Understanding Source Objects" and Chapter 6, "Making Queries Using Source Methods".
The members of an Oracle OLAP dimension are usually organized into one or more hierarchies. Some hierarchies have parent-child relationships based on levels and some have those relationships based on values. The value of each dimension member must be unique.
The OLAP Java API uses a three-part format to uniquely identify a dimension member. The format contains the hierarchy, the level, and the value of the dimension member, and thereby identifies a unique value in the dimension. The first part of a unique value is the name of the hierarchy object, the second part is the name of the level object, and the third part is the value of the member in the level. The parts of the unique value are separated by a value separation string, which by default is double colons (::). The following is an example of a unique member value of a level named YEAR in a hierarchy named CALENDAR_YEAR in a dimension named TIME_AWJ.
CALENDAR_YEAR::YEAR::CY2001
The third part of a unique value is the local value. The local value in the preceding example identifies the calendar year 2001.
To retrieve the data specified by a Source, you create an oracle.olapi.data.cursor.Cursor for that Source. You then use this Cursor to request and retrieve the data from the data store. You can specify the amount of data that the Cursor retrieves in each fetch operation (for example, enough to fill a 40-cell table in the user interface). Oracle OLAP then efficiently manages the timing, sizing, and caching of the data blocks that it retrieves for your application, so that you do not need to do so. For information about Cursor objects, see Chapter 8, "Understanding Cursor Classes and Concepts" and Chapter 9, "Retrieving Query Results".
The examples of OLAP Java API code in this documentation are excerpts from a set of example programs that are available on the Oracle Technology Network (OTN) Web site. One example, CreateAndBuildAW.java, has methods that create and build an analytic workspace. Another example, SpecifyAWValues, calls the methods of CreateAndBuildAW.java and specifies values, such as names for the metadata objects and names of columns of relational tables for mapping the metadata objects to data sources. The analytic workspace produced by these examples is named GLOBAL_AWJ. Other examples query that analytic workspace. The metadata objects in the analytic workspace are mapped to columns in relational tables that are in the Global schema.
From the OTN Web site, you can download a file that contains SQL scripts that create the Global schema and a file that contains the example programs. The OTN Web site is at http://www.oracle.com/technetwork/database/options/olap/index.html.
To get either file, select Sample Code and Schemas in the Download section of the Web page. To get the sample schema, select Global Schema 11g. To get the example programs, select Example Programs for Documentation and then select Download the Example Programs for 11g Release 2 (11.2) to download the compressed file that contains the examples.
The example programs are in a package structure that you can easily add to your development environment. The classes include a base class that the example program classes extend, and utility classes that they use. The base class is BaseExample11g.java. The utility classes include Context11g.java and CursorPrintWriter.java. The Context11g.java class has methods that create a connection to an Oracle Database instance, that store metadata objects, that return the stored metadata objects, and that create Cursor objects. The CursorPrintWriter.java class is a PrintWriter that has methods that display the contents of Cursor objects.
The OLAP metadata objects are created and built by the CreateAndBuildAW.java and the SpecifyAWValues programs. Those metadata objects include the following:
GLOBAL_AWJ, which is the analytic workspace that contains the other objects.
PRODUCT_AWJ, which is a dimension for products. It has one hierarchy named PRODUCT_PRIMARY. The lowest level of the hierarchy has product item identifiers and the higher levels have product family, class, and total products identifiers.
CUSTOMER_AWJ, which is a dimension for customers. It has two hierarchies named SHIPMENTS and MARKETS. The lowest level of each hierarchy has customer identifiers and higher levels have warehouse, region, and total customers, and account, market segment, and total market identifiers, respectively.
TIME_AWJ, which is a dimension for time values. It has a hierarchy named CALENDAR_YEAR. The lowest level has month identifiers, and the other levels have quarter and year identifiers.
CHANNEL_AWJ, which is a dimension for sales channels. It has one hierarchy named CHANNEL_PRIMARY. The lowest level has sales channel identifiers and the higher level has the total channel identifier.
UNITS_CUBE_AWJ, which is a cube that contains the measures COST, SALES, and UNITS. COST has values for the costs of product units. SALES has the dollar amounts for the sales of product units. UNITS has values for the quantities of product units sold. The cube is dimensioned by all four dimensions. The aggregation method for the cube is SUM, in which each the value for each parent is the sum of the values of the children of the parent.
PRICE_CUBE_AWJ, which is a cube that contains the measures UNIT_COST and UNIT_PRICE. UNIT_COST has the costs of the units. UNIT_PRICE has the prices of the units. The cube is dimensioned by the PRODUCT_AWJ and TIME_AWJ dimensions. The aggregation method for the cube is AVG, in which the value for each parent is the average of the values of the children of the parent.
For an example of a program that discovers the OLAP metadata for the analytic workspace, see Chapter 3, "Discovering Metadata".
A client application that uses the OLAP Java API typically performs the following tasks:
Connects to the data store and creates a DataProvider and a UserSession.
Creates or discovers metadata objects.
Deploys, maps, and builds metadata objects, as needed.
Specifies queries that select and manipulate data.
Retrieves query results.
The rest of this topic briefly describes these tasks, and the rest of this guide provides detailed information about how to accomplish them.
You connect to the data store by identifying some information about the target Oracle Database instance and specifying this information in a JDBC connection method. Having established a connection, you create a DataProvider and use it and the connection to create a UserSession. For more information about connecting and creating a DataProvider and UserSession, see "Connecting to Oracle OLAP" in Chapter 3.
You use the DataProvider to get an MdmMetadataProvider. The MdmMetadataProvider gives access to all of the metadata objects in the data store. You next obtain the MdmRootLSchema object by calling the getRootSchema method of the MdmMetdataProvider. The MdmRootSchema object contains all of the OLAP metadata objects in the database. From the MdmRootSchema, you get the MdmDatabaseSchema objects for the schemas that the current user has permission to access. An MdmDatabaseSchema represents a named Oracle Database user as returned by the SQL statement SELECT username FROM all_users.
From an MdmDatabaseSchema, you can discover the existing metadata objects that are owned by the schema or you can create new ones. Methods such as getMeasures and getDimensions get all of the measures or dimensions owned by the MdmDatabaseSchema. Methods such as findOrCreateAW and findOrCreateCube get an analytic workspace or cube, if it exists, or create one if it does not already exist.
From a top-level metadata object contained by the MdmDatabaseSchema, such as an analytic workspace, cube, or dimension, you can get the objects that it contains. For example, from an MdmPrimaryDimension, you can get the hierarchies, levels, and attributes that are associated with it. Having determined the metadata objects that are available to the user, you can present relevant lists of objects to the user for data selection and manipulation.
For a description of the metadata objects, see Chapter 2, "Understanding OLAP Java API Metadata". For information about how you can discover the available metadata, see Chapter 3, "Discovering Metadata".
If you create a new MdmCube or MdmPrimaryDimension, you must deploy it as an analytic workspace object or as a relational OLAP (Rolap) object. To deploy a cube, you call an MdmCube method such as findOrCreateAWCubeOrganization. To deploy a dimension, you call an MdmPrimaryDimension method such as findOrCreateAWPrimaryDimensionOrganization.
If you create a new metadata object that represents data, you must specify an Expression that maps the metadata object to a relational source table or view, or that Oracle OLAP uses to generate the data. For objects that are contained by an analytic workspace, you can build the metadata objects after mapping them. For information on creating metadata, deploying, mapping, and building metadata objects, see Chapter 4, "Creating Metadata and Analytic Workspaces".
An OLAP Java API application can construct queries against the data store. A typical application user interface provides ways for the user to select data and to specify the operations to perform using the data. Then, the data manipulation code translates these instructions into queries against the data store. The queries can be as simple as a selection of dimension members, or they can be complex, including several aggregations and calculations involving the measure values that are specified by selections of dimension members.
The OLAP Java API object that represents a query is a Source. Metadata objects that represent data are extensions of the MdmSource class. From an MdmSource, such as an MdmMeasure or an MdmPrimaryDimension, you can get a Source object. With the methods of a Source object, you can produce other Source objects that specify a selection of the elements of the Source, or that specify calculations or other operations to perform on the values of a Source.
If you are implementing a simple user interface, then you might use only the methods of a Source object to select and manipulate the data that users specify in the interface. However, if you want to offer your users multistep selection procedures and the ability to modify queries or undo individual steps in their selections, then you should design and implement Template classes. Within the code for each Template, you use the methods of the Source classes, but the Template classes themselves allow you to dynamically modify and refine even the most complex query. In addition, you can write general-purpose Template classes and reuse them in various parts of your application.
For information about working with Source objects, see Chapter 5, "Understanding Source Objects". For information about working with Template objects, see Chapter 10, "Creating Dynamic Queries".
When users of an OLAP Java API application are selecting, calculating, combining, and generally manipulating data, they also want to see the results of their work. This means that the application must retrieve the result sets of queries from the data store and display the data in multidimensional form. To retrieve a result set for a query through the OLAP Java API, you create a Cursor for the Source that specifies the query.
You can also get the SQL that Oracle OLAP generates for a query. To do so, you create a SQLCursorManager for the Source instead of creating a Cursor. The generateSQL method of the SQLCursorManager returns the SQL specified by the Source. You can then retrieve the data by means outside of the OLAP Java API.
Because the OLAP Java API was designed to deal with a multidimensional view of data, a Source can have a multidimensional result set. For example, a Source can represent an MdmMeasure that is dimensioned by four MdmPrimaryDimension objects. Each MdmPrimaryDimension has an associated Source. You can create a query by joining the Source objects for the dimensions to the Source for the measure. The resulting query has the Source for the measure as the base and it has the Source objects for the dimensions as outputs.
A Cursor for a query Source has the same structure as the Source. For example, the Cursor for the Source just mentioned has base values that are the measure data. The Cursor also has four outputs. The values of the outputs are those of the Source objects for the dimensions.
To retrieve all of the items of data through a Cursor, you can loop through the multidimensional Cursor structure. This design is well adapted to the requirements of standard user interface objects for painting the computer screen. It is especially well adapted to the display of data in multidimensional format.
For more information about using Source objects to specify a query, see Chapter 5, "Understanding Source Objects". For more information about using Cursor objects to retrieve data, see Chapter 8, "Understanding Cursor Classes and Concepts". For more information about the SQLCursorManager class, see Oracle OLAP Java API Reference.
This chapter describes how to create new metadata objects and map them to relational structures or expressions. It describes how to export and import the definitions of the metadata objects to XML templates. It also describes how to associate the objects with an analytic workspace, and how to build the analytic workspace.
This chapter includes the following topics:
The OLAP Java API provides the ability to create persistent metadata objects. The top-level metadata objects exist in the data dictionary of the Oracle Database instance. The API also provides the ability to create transient metadata objects that exist only for the duration of the session. An application can use both types of metadata objects to create queries that retrieve or otherwise use the data in the data store.
Before an OLAP Java API application can create metadata objects, a database administrator must have prepared the Oracle Database instance. The DBA must have set up permanent and temporary tablespaces in the database to support the creation of Oracle OLAP metadata objects and must have granted the privileges that allow the user of the session to create and manage objects. For information on preparing an Oracle Database instance, see Oracle OLAP User's Guide.
A dimensional metadata model typically includes the objects described in Chapter 2, "Understanding OLAP Java API Metadata". For detailed information on designing a dimensional metadata model, see Oracle OLAP User's Guide.
You implement the dimensional model by creating OLAP Java API metadata objects. You use classes in the oracle.olapi.metadata.mapping package to map the metadata objects to relational source objects and to build analytic workspaces. You use classes in the oracle.olapi.syntax package to specify Expression objects that you use in mapping the metadata. You use classes in the oracle.olapi.metadata.deployment package to deploy the metadata objects in an analytic workspace or in a relational database (ROLAP) organization.
The basic steps for implementing the dimensional model as OLAP Java API objects in an analytic workspace are the following:
Create an AW object and MdmPrimaryDimension and MdmCube objects.
Deploy the MdmPrimaryDimension and MdmCube objects to the AW.
Create MdmDimensionLevel, MdmHierarchy, and MdmAttribute objects for each MdmPrimaryDimension, create MdmHierarchyLevel objects to associate MdmDimensionLevel objects with an MdmHierarchy, and create the MdmMeasure and related objects for the MdmCube objects.
Map the metadata objects to the relational sources of the base data.
Commit the Transaction, which creates persistent objects in the database.
Load data into the objects from the relational sources by building the analytic workspace.
The following topics describe these steps. The examples in this chapter are from the CreateMetadataAndAW.java example program. That program creates some of the same metadata objects as the CreateAndBuildAW.java and SpecifyAWValues.java example programs. The CreateMetadataAndAW program also exports the analytic workspace to an XML template.
An analytic workspace is a container for dimensional objects. It is represented by the AW class in the oracle.olapi.metadata.deployment package. An analytic workspace is owned by an MdmDatabaseSchema.
Example 4-1 demonstrates getting the MdmDatabaseSchema for the GLOBAL user and creating an AW. For an example that gets the MdmRootSchema, see Chapter 3.
A dimension is a list of unique values that identify and categorize data. Dimensions form the edges of a cube and identify the values in the measures of the cube. A dimension can have one or more levels that categorize the dimension members. It can have one or more hierarchies that further categorize the members. A dimension can also have no levels or hierarchies. However, a dimension must have one or more levels before Oracle OLAP can create a materialized view for it.
A dimension also has attributes that contain information about dimension members. For descriptions of creating attributes, see "Creating Attributes".
This topic describes how to create objects that represent a dimension and the levels and hierarchies of a dimension.
An OLAP dimension is represented by the MdmPrimaryDimension class. A dimension is owned by an MdmDatabaseSchema. You create a dimension with the findOrCreateTimeDimension or the findOrCreateStandardDimension method of the MdmDatabaseSchema. You can map a dimension that has no levels to a relational data source by creating a MemberListMap for the dimension.
Example 4-2 creates a standard dimension that has the name CHANNEL_AWJ. The example creates an AWPrimaryDimensionOrganization object to deploy the dimension in an analytic workspace. The mdmDBSchema and aw objects are created by Example 4-1. The last three lines call the methods of Example 4-3, Example 4-4, and Example 4-9, respectively.
Example 4-2 Creating and Deploying an MdmStandardDimension
MdmStandardDimension mdmChanDim =
mdmDBSchema.findOrCreateStandardDimension("CHANNEL_AWJ");
AWPrimaryDimensionOrganization awChanDimOrg =
mdmChanDim.findOrCreateAWPrimaryDimensionOrganization(aw);
createAndMapDimensionLevels(mdmChanDim);
createAndMapHierarchies();
commit(mdmChanDim);
An MdmDimensionLevel represents the members of a dimension that are at the same level. Typically, the members of a level are in a column in a dimension table in the relational source. A MemberListMap associates the MdmDimensionLevel with the relational source.
Example 4-3 creates two MdmDimensionLevel objects for the CHANNEL_AWJ dimension and maps the dimension levels to the key columns of the GLOBAL.CHANNEL_DIM table. The example also maps the long description attributes for the dimension levels to columns of that table. The long description attribute, chanLongDescAttr, is created by Example 4-6.
Example 4-3 Creating and Mapping an MdmDimensionLevel
private ArrayList<MdmDimensionLevel> dimLevelList = new ArrayList();
private ArrayList<String> dimLevelNames = new ArrayList();
private ArrayList<String> keyColumns = new ArrayList();
private ArrayList<String> lDescColNames = new ArrayList();
private void createAndMapDimensionLevels(MdmPrimaryDimension mdmChanDim)
{
dimLevelNames.add("TOTAL_CHANNEL");
dimLevelNames.add("CHANNEL");
keyColumns.add("GLOBAL.CHANNEL_DIM.TOTAL_ID");
keyColumns.add("GLOBAL.CHANNEL_DIM.CHANNEL_ID");
lDescColNames.add("GLOBAL.CHANNEL_DIM.TOTAL_DSC");
lDescColNames.add("GLOBAL.CHANNEL_DIM.CHANNEL_DSC");
// Create the MdmDimensionLevel and MemberListMap objects.
int i = 0;
for(String dimLevelName : dimLevelNames)
{
MdmDimensionLevel mdmDimLevel =
mdmChanDim.findOrCreateDimensionLevel(dimLevelNames.get(i));
dimLevelList.add(mdmDimLevel);
// Create a MemberListMap for the dimension level.
MemberListMap mdmDimLevelMemListMap =
mdmDimLevel.findOrCreateMemberListMap();
ColumnExpression keyColExp =
(ColumnExpression)SyntaxObject.fromSyntax(keyColumns.get(i),
metadataProvider);
mdmDimLevelMemListMap.setKeyExpression(keyColExp);
mdmDimLevelMemListMap.setQuery(keyColExp.getQuery());
// Create an attribute map for the Long Description attribute.
AttributeMap attrMapLong =
mdmDimLevelMemListMap.findOrCreateAttributeMap(chanLongDescAttr);
// Create an expression for the attribute map.
Expression lDescColExp =
(Expression)SyntaxObject.fromSyntax(lDescColNames.get(i),
metadataProvider);
attrMapLong.setExpression(lDescColExp);
i++;
}
}
An MdmHierarchy represents a hierarchy in the dimensional object model. An MdmHierarchy can be an instance of the MdmLevelHierarchy or the MdmValueHierarchy class. An MdmLevelHierarchy has an ordered list of MdmHierarchyLevel objects that relate MdmDimensionLevel objects to the hierarchy.
Example 4-4 creates a hierarchy for the CHANNEL_AWJ dimension. It creates hierarchy levels for the hierarchy and associates attributes with the hierarchy levels. It also maps the hierarchy levels and the attributes to relational sources. The example uses the ArrayList objects from Example 4-3. It maps the MdmHierarchyLevel objects to the same relational source objects as the MdmDimensionLevel objects are mapped.
Example 4-4 Creating and Mapping MdmLevelHierarchy and MdmHierarchyLevel Objects
private void createAndMapHierarchies()
{
MdmLevelHierarchy mdmLevelHier =
mdmChanDim.findOrCreateLevelHierarchy("CHANNEL_PRIMARY");
// Create the MdmHierarchyLevel and HierarchyLevelMap objects.
int i = 0;
for(String dimLevelName : dimLevelNames)
{
MdmDimensionLevel mdmDimLevel =
mdmChanDim.findOrCreateDimensionLevel(dimLevelName);
MdmHierarchyLevel mdmHierLevel =
mdmLevelHier.findOrCreateHierarchyLevel(mdmDimLevel);
HierarchyLevelMap hierLevelMap =
mdmHierLevel.findOrCreateHierarchyLevelMap();
ColumnExpression keyColExp =
(ColumnExpression)SyntaxObject.fromSyntax(keyColumns.get(i),
metadataProvider);
hierLevelMap.setKeyExpression(keyColExp);
hierLevelMap.setQuery(keyColExp.getQuery());
i++;
}
}
The GLOBAL_AWJ analytic workspace that is used by the examples in this documentation does not have an MdmPrimaryDimension for which an MdmValueHierarchy would be sensible. The sample schema for the user SCOTT has a table that can serve as an example.
The SCOTT sample schema has a table named EMP. That table has columns for employees and for managers. You could create a dimension for employees. You could then create an MdmValueHierarchy in which you map the employee column as the base values for the hierarchy and you map the manager column as the parent relation, as shown in Example 4-5. To be able to create OLAP dimensions, the SCOTT user must be granted the OLAP_USER role and the CREATE SESSION privilege.
In the example, mdmDBSchema is the MdmDatabaseSchema for the SCOTT user, dp is the DataProvider, and mp is the MdmMetadataProvider. The example does not show the code for connecting to the database or getting the DataProvider and creating a UserSession, or getting the MdmMetadataProvider, the MdmRootSchema, or the MdmDatabaseSchema. The code is an excerpt from a class that extends the BaseExample11g example class. That class uses other example classes that have methods for committing the current Transaction and for displaying output. For the complete code, see the CreateValueHierarchy.java example program.
Example 4-5 Creating an MdmValueHierarchy
// Create an analytic workspace object.
AW aw = mdmDBSchema.findOrCreateAW(awName);
// Create a dimension and deploy it to the analytic workspace.
MdmPrimaryDimension mdmEmpDim =
mdmDBSchema.findOrCreateStandardDimension("EMP_DIM");
AWPrimaryDimensionOrganization awEmpDimOrg =
mdmEmpDim.findOrCreateAWPrimaryDimensionOrganization(aw);
// Get the EMP table and the Query for the table.
MdmTable empTable = (MdmTable)mdmDBSchema.getTopLevelObject("EMP");
Query empQuery = empTable.getQuery();
// Create a value hierarchy.
MdmValueHierarchy mdmValHier =
mdmEmpDim.findOrCreateValueHierarchy("EMPVALHIER");
// Create a map for the hierarchy.
SolvedValueHierarchyMap solvedValHierMap =
mdmValHier.findOrCreateSolvedValueHierarchyMap();
// Specify the Query, the key expression and the parent key expression for
// the hierarchy.
solvedValHierMap.setQuery(empQuery);
Expression keyExp =
(Expression)SyntaxObject.fromSyntax("SCOTT.EMP.EMPNO", mp);
solvedValHierMap.setKeyExpression(keyExp);
Expression parentExp =
(Expression)SyntaxObject.fromSyntax("SCOTT.EMP.MGR", mp);
solvedValHierMap.setParentKeyExpression(parentExp);
// Create an attribute that relates a name to each dimension member.
MdmBaseAttribute mdmNameAttr =
mdmEmpDim.findOrCreateBaseAttribute("EMP_NAME");
SQLDataType sdtVC2 = new SQLDataType("VARCHAR2");
mdmNameAttr.setSQLDataType(sdtVC2)
// Create an attribute map for the attribute.
AttributeMap attrMap =
solvedValHierMap.findOrCreateAttributeMap(mdmNameAttr);
// Create and set an expression for the attribute map.
Expression exp = (Expression)
SyntaxObject.fromSyntax("SCOTT.EMP.ENAME", mp);
attrMap.setExpression(exp);
mdmValHier.addAttribute(mdmNameAttr);
// Commit the Transaction before building the analytic workspace.
// The getContext method of BaseExample11g returns a Context11g object,
// which has a method that commits the Transaction.
getContext().commit();
BuildItem bldEmpDim = new BuildItem(mdmEmpDim);
ArrayList<BuildItem> items = new ArrayList();
items.add(bldEmpDim);
BuildProcess bldProc = new BuildProcess(items);
// Execute the build.
try
{
dp.executeBuild(bldProc, 0);
}
catch (Exception ex)
{
println("Could not execute the BuildProcess.");
println("Caught: " + ex);
}
//Get the Source objects for the dimension, the hierarchy, and the attribute.
Source empDim = mdmEmpDim.getSource();
Source valHier = mdmValHier.getSource();
Source empNameAttr = mdmNameAttr.getSource();
// Get the parent attribute and get the Source for it.
MdmAttribute mdmParentAttr = mdmEmpDim.getParentAttribute();
Source parentAttr = mdmParentAttr.getSource();
Source parentByEmpByName = parentAttr.join(valHier.join(empNameAttr));
// Sort the values in ascending order by employee number of the managers.
Source sortedParentByEmpByName = parentByEmpByName.sortAscending();
// Commit the Transaction before creating a Cursor.
getContext().commit();
// The displayResult method of the Context11g object creates a Cursor and
// displays the results.
println("The managers of the employees are:");
getContext().displayResult(sortedParentByEmpByName);
The output of Example 4-5 is the following. It shows the employee name, the employee ID and then the employee ID of the manager. The results are sorted by manager. The employee King does not have a parent and is the highest member of the hierarchy so the manager value for King is null, which appears as NA in the output.
The managers of the employees are: 1: ((SCOTT,EMPVALHIER::7788),EMPVALHIER::7566) 2: ((FORD,EMPVALHIER::7902),EMPVALHIER::7566) 3: ((ALLEN,EMPVALHIER::7499),EMPVALHIER::7698) 4: ((WARD,EMPVALHIER::7521),EMPVALHIER::7698) 5: ((MARTIN,EMPVALHIER::7654),EMPVALHIER::7698) 6: ((TURNER,EMPVALHIER::7844),EMPVALHIER::7698) 7: ((JAMES,EMPVALHIER::7900),EMPVALHIER::7698) 8: ((MILLER,EMPVALHIER::7934),EMPVALHIER::7782) 9: ((ADAMS,EMPVALHIER::7876),EMPVALHIER::7788) 10: ((JONES,EMPVALHIER::7566),EMPVALHIER::7839) 11: ((BLAKE,EMPVALHIER::7698),EMPVALHIER::7839) 12: ((CLARK,EMPVALHIER::7782),EMPVALHIER::7839) 13: ((SMITH,EMPVALHIER::7369),EMPVALHIER::7902) 14: ((KING,EMPVALHIER::7839),NA)
Attributes contain information about dimension members. An MdmBaseAttribute represents values that are based on relational source tables. An MdmDerivedAttribute represents values that Oracle OLAP derives from characteristics or relationships of the dimension members. For example, the getParentAttribute method of an MdmPrimaryDimension returns an MdmDerivedAttribute that records the parent of each dimension member.
You create a base attribute for a dimension with the findOrCreateBaseAttribute method. You can specify the data type of the attribute, although for many attributes Oracle OLAP can determine the data type from the attribute mapping. With the setAllowAutoDataTypeChange method, you can specify that Oracle OLAP determine the data type. Some attributes are used by the dimension in certain ways, such as to provide descriptions of dimension members or to provide date information that can be used in calculations. For example, you can specify an attribute for descriptions with the setValueDescriptionAttribute method of the dimension and you can specify an attribute that contains end date time period values with the setEndDateAttribute method of an MdmTimeDimension.
Example 4-6 creates a long description attribute for the CHANNEL_AWJ dimension and specifies it as the attribute that contains descriptions of the members of the dimension. The example specifies that Oracle OLAP automatically determines a SQL data type for the attribute.
Example 4-6 Creating an MdmBaseAttribute
private MdmBaseAttribute chanLongDescAttr = null;
private void createLongDesciptionAttribute(MdmPrimaryDimension mdmChanDim)
{
// Create the long description attribute and allow the automatic changing of
// the SQL data type.
chanLongDescAttr = mdmChanDim.findOrCreateBaseAttribute("LONG_DESCRIPTION");
chanLongDescAttr.setAllowAutoDataTypeChange(true));
// Specifies that the attribute contains descriptions of the dimension members.
mdmChanDim.setValueDescriptionAttribute(chanLongDescAttr);
}
An attribute can have different values for the members of different levels of the dimension. In that case the attribute has an attribute mapping for each level. Example 4-3 creates an AttributeMap for the long description attribute for each dimension level by calling the findOrCreateAttributeMap method of the MemberListMap for each dimension level. It specifies a different column for each attribute map.
A cube in a dimensional object model is represented by the MdmCube class. An MdmCube owns one or more MdmMeasure objects. It has a list of the MdmPrimaryDimension objects that dimension the measures.
An MdmCube has the following objects associated with it.
MdmPrimaryDimension objects that specify the dimensionality of the cube.
MdmMeasure objects that contain data that is identified by the dimensions.
A CubeOrganization that specifies how the cube stores and manages the measure data.
CubeMap objects that associate the cube with relational sources.
A ConsistentSolveSpecification that specifies how to calculate, or solve, the aggregate level data.
This topic has an example that creates a cube and some of the objects associated with it. Example 4-7 creates an MdmCube that has the name PRICE_CUBE_AWJ. The example creates an AWCubeOrganization object to deploy the cube in an analytic workspace. The mdmDBSchema and aw objects are created by Example 4-1 and the leafLevel ArrayList is created in Example 4-4. The mdmTimeDim and mdmProdDim objects are dimensions of time periods and product categories. The CreateAndBuildAW program creates those dimensions. The last lines of the example call the methods in Example 4-8 and Example 4-9, respectively.
Example 4-7 Creating and Mapping an MdmCube
private MdmCube createAndMapCube(MdmPrimaryDimension mdmTimeDim,
MdmPrimaryDimension mdmProdDim)
{
MdmCube mdmPriceCube = mdmDBSchema.findOrCreateCube("PRICE_CUBE_AWJ");
// Add dimensions to the cube.
mdmPriceCube.addDimension(mdmTimeDim);
mdmPriceCube.addDimension(mdmProdDim);
AWCubeOrganization awCubeOrg =
mdmPriceCube.findOrCreateAWCubeOrganization(aw);
awCubeOrg.setMVOption(AWCubeOrganization.NONE_MV_OPTION);
awCubeOrg.setMeasureStorage(AWCubeOrganization.SHARED_MEASURE_STORAGE);
awCubeOrg.setCubeStorageType("NUMBER");
AggregationCommand aggCommand = new AggregationCommand("AVG");
ArrayList<ConsistentSolveCommand> solveCommands = new ArrayList();
solveCommands.add(aggCommand);
ConsistentSolveSpecification conSolveSpec =
new ConsistentSolveSpecification(solveCommands);
mdmPriceCube.setConsistentSolveSpecification(conSolveSpec);
// Create and map the measures of the cube.
createAndMapMeasures(mdmPriceCube);
// Commit the Transaction.
commit(mdmPriceCube);
}
This topic has an example that creates measures for a cube and maps the measures to fact tables in the relational database. The example uses the cube created by Example 4-7.
Example 4-8 Creating and Mapping Measures
private void createAndMapMeasures(MdmCube mdmPriceCube)
{
ArrayList<MdmBaseMeasure> measures = new ArrayList();
MdmBaseMeasure mdmCostMeasure =
mdmPriceCube.findOrCreateBaseMeasure("UNIT_COST");
MdmBaseMeasure mdmPriceMeasure =
mdmPriceCube.findOrCreateBaseMeasure("UNIT_PRICE");
mdmCostMeasure.setAllowAutoDataTypeChange(true);
mdmPriceMeasure.setAllowAutoDataTypeChange(true);
measures.add(mdmCostMeasure);
measures.add(mdmPriceMeasure);
MdmTable priceCostTable =
(MdmTable)mdmDBSchema.getTopLevelObject("PRICE_FACT");
Query cubeQuery = priceCostTable.getQuery();
ArrayList<String> measureColumns = new ArrayList();
measureColumns.add("GLOBAL.PRICE_FACT.UNIT_COST");
measureColumns.add("GLOBAL.PRICE_FACT.UNIT_PRICE");
CubeMap cubeMap = mdmPriceCube.findOrCreateCubeMap();
cubeMap.setQuery(cubeQuery);
// Create MeasureMap objects for the measures of the cube and
// set the expressions for the measures. The expressions specify the
// columns of the fact table for the measures.
int i = 0;
for(MdmBaseMeasure mdmBaseMeasure : measures)
{
MeasureMap measureMap = cubeMap.findOrCreateMeasureMap(mdmBaseMeasure);
Expression expr =
(Expression)SyntaxObject.fromSyntax(measureColumns.get(i),
metadataProvider);
measureMap.setExpression(expr);
i++;
}
// Create CubeDimensionalityMap objects for the dimensions of the cube and
// set the expressions for the dimensions. The expressions specify the
// columns of the fact table for the dimensions.
ArrayList<String> factColNames = new ArrayList();
factColNames.add("GLOBAL.PRICE_FACT.MONTH_ID");
factColNames.add("GLOBAL.PRICE_FACT.ITEM_ID");
List<MdmDimensionality> mdmDimltys = mdmPriceCube.getDimensionality();
for (MdmDimensionality mdmDimlty: mdmDimltys)
{
CubeDimensionalityMap cubeDimMap =
cubeMap.findOrCreateCubeDimensionalityMap(mdmDimlty);
MdmPrimaryDimension mdmPrimDim =
(MdmPrimaryDimension)mdmDimlty.getDimension();
String columnMap = null;
if (mdmPrimDim.getName().startsWith("TIME"))
{
columnMap = factColNames.get(0);
i = 0;
}
else// (mdmPrimDim.getName().startsWith("PRODUCT"))
{
columnMap = factColNames.get(1);
i = 1;
}
Expression expr =
(Expression)SyntaxObject.fromSyntax(columnMap,metadataProvider);
cubeDimMap.setExpression(expr);
// Associate the leaf level of the hierarchy with the cube.
MdmHierarchy mdmDefHier = mdmPrimDim.getDefaultHierarchy();
MdmLevelHierarchy mdmLevHier = (MdmLevelHierarchy)mdmDefHier;
List<MdmHierarchyLevel> levHierList = mdmLevHier.getHierarchyLevels();
// The last element in the list must be the leaf level of the hierarchy.
MdmHierarchyLevel leafLevel = levHierList.get(levHierList.size() - 1);
cubeDimMap.setMappedDimension(leafLevel);
}
}
To save a metadata object as a persistent entity in the database, you must commit the Transaction in which you created the object. You can commit a Transaction at any time. Committing the Transaction after creating a top-level object and the objects that it owns is a good practice.
Example 4-9 gets the TransactionProvider from the DataProvider for the session and commits the current Transaction.
Example 4-9 Committing Transactions
private void commit(MdmSource mdmSource)
{
try
{
System.out.println("Committing the transaction for " +
mdmSource.getName() + ".");
(dp.getTransactionProvider()).commitCurrentTransaction();
}
catch (Exception ex)
{
System.out.println("Could not commit the Transaction. " + ex);
}
}
You can save the definition of a metadata object by exporting the object to an XML template. Exporting an object saves the definition of the object and the definitions of any objects that it owns. For example, if you export an AW object to XML, then the XML includes the definitions of any MdmPrimaryDimension and MdmCube objects that the AW owns, and the MdmAttribute, MdmMeasure and other objects owned by the dimensions and cubes.
Example 4-10 exports metadata objects to an XML template and saves it in a file. The code excerpt at the beginning of the example creates a List of the objects to export. It adds to the List the aw object, which is the analytic workspace created by Example 4-1. It then calls the exportToXML method.
Example 4-10 Exporting to an XML Template
... // In some method.
List objectsToExport = new ArrayList();
objectsToExport.add(aw);
exportToXML(objectsToExport, "globalawj.xml");
...
public void exportToXML(List objectsToExport, String fileName)
{
try
{
PrintWriter writer = new PrintWriter(new FileWriter(filename));
mp.exportFullXML(writer, // mp is the MdmMetadataProvider
objectsToExport,
null, // No Map for renaming objects
false); // Do not include the owner name
writer.close();
}
catch (IOException ie)
{
ie.printStackTrace();
}
}
You can import a metadata object definition as an XML template. After importing, you must build the object.
After creating and mapping metadata objects, or importing the XML definition of an object, you must perform the calculations that the objects specify and load the resulting data into physical storage structures.
Example 4-11 creates BuildItem objects for the dimensions and cubes of the analytic workspace. It creates a BuildProcess that specifies the BuildItem objects and passes the BuildProcess to the executeBuild method of the DataProvider for the session.
Example 4-11 Building an Analytic Workspace
BuildItem bldChanDim = new BuildItem(mdmChanDim);
BuildItem bldProdDim = new BuildItem(mdmProdDim);
BuildItem bldCustDim = new BuildItem(mdmCustDim);
BuildItem bldTimeDim = new BuildItem(mdmTimeDim);
BuildItem bldUnitsCube = new BuildItem(mdmUnitsCube);
BuildItem bldPriceCube = new BuildItem(mdmPriceCube);
ArrayList<BuildItem> items = new ArrayList();
items.add(bldChanDim);
items.add(bldProdDim);
items.add(bldCustDim);
items.add(bldTimeDim);
items.add(bldUnitsCube);
items.add(bldPriceCube);
BuildProcess bldProc = new BuildProcess(items);
try
{
dp.executeBuild(bldProc, 0);
}
catch (Exception ex)
{
System.out.println("Could not execute the BuildProcess." + ex);
}
Oracle OLAP Java API Developer's Guide introduces Java programmers to the Oracle OLAP Java API, which is the Java application programming interface for Oracle OLAP. Through Oracle OLAP, the OLAP Java API provides access to data stored in an Oracle database, particularly data in an analytic workspace. The OLAP Java API capabilities for creating and maintaining analytic workspaces, and for querying, manipulating, and presenting data are particularly suited to applications that perform online analytical processing (OLAP) operations.
The preface contains these topics:
Oracle OLAP Java API Developer's Guide is intended for Java programmers who are responsible for creating applications that do one or more of the following:
Implement an Oracle OLAP metadata model.
Define, build, and maintain analytic workspaces.
Perform analysis using Oracle OLAP.
To use this manual, you should be familiar with Java, relational database management systems, data warehousing, OLAP concepts, and Oracle OLAP.
For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.
Access to Oracle Support
Oracle customers have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.
Accessibility of Code Examples in Documentation
Screen readers may not always correctly read the code examples in this document. The conventions for writing code require that closing braces should appear on an otherwise empty line; however, some screen readers may not always read a line of text that consists solely of a bracket or brace.
For more information, see these Oracle resources:
The following text conventions are used in this document:
| Convention | Meaning |
|---|---|
| boldface | Boldface type indicates graphical user interface elements associated with an action, or terms defined in text or the glossary. |
| italic | Italic type indicates book titles, emphasis, or placeholder variables for which you supply particular values. |
monospace | Monospace type indicates commands within a paragraph, URLs, code in examples, text that appears on the screen, or text that you enter. |