Oracle OLAP Java API Guide 26ai
Oracle OLAP Java API Guide 26ai
26ai
G44123-01
October 2025
Oracle OLAP Java API Developer's Guide, 26ai
G44123-01
Contributors: David McDermid, David Greenfield, Jim Hartsing, Scott Feinstein, Anne Murphy, Richard Samuels, Steve
Mesropian, Chuck Venezia, Afsaneh Koochek
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, software documentation, data (as defined in the Federal Acquisition Regulation), or related
documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, then
the following notice is applicable:
U.S. GOVERNMENT END USERS: Oracle programs (including any operating system, integrated software, any
programs embedded, installed, or activated on delivered hardware, and modifications of such programs) and Oracle
computer documentation or other Oracle data delivered to or accessed by U.S. Government end users are "commercial
computer software," "commercial computer software documentation," or "limited rights data" pursuant to the applicable
Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, reproduction,
duplication, release, display, disclosure, modification, preparation of derivative works, and/or adaptation of i) Oracle
programs (including any operating system, integrated software, any programs embedded, installed, or activated on
delivered hardware, and modifications of such programs), ii) Oracle computer documentation and/or iii) other Oracle
data, is subject to the rights and limitations specified in the license contained in the applicable contract. The terms
governing the U.S. Government's use of Oracle cloud services are defined by the applicable contract for such services.
No other rights are granted to the U.S. Government.
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®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates. Other names may be
trademarks of their respective owners.
Intel and Intel Inside 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, Epyc, and the AMD 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 about 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 unless otherwise set forth in an
applicable agreement between you and Oracle. 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, except as set forth
in an applicable agreement between you and Oracle.
Contents
Preface
Audience i
Documentation Accessibility i
Related Documents ii
Conventions ii
Changes in This Release for Oracle OLAP Java API Developer's Guide
Changes in Oracle AI Database 26ai i
3 Discovering Metadata
3.1 Connecting to Oracle OLAP 1
3.1.1 Prerequisites for Connecting 1
3.1.2 Establishing a Connection 2
[Link] Creating a JDBC Connection 2
[Link] Creating a DataProvider and a UserSession 3
3.1.3 Closing the Connection and the DataProvider 3
3.2 Overview of the Procedure for Discovering Metadata 3
3.2.1 Purpose of Discovering the Metadata 4
3.2.2 Steps in Discovering the Metadata 4
3.3 Creating an MdmMetadataProvider 4
3.4 Getting the MdmSchema Objects 5
3.5 Getting the Contents of an MdmSchema 6
7 Using a TransactionProvider
7.1 About Creating a Metadata Object or a Query in a Transaction 1
7.1.1 Types of Transaction Objects 2
7.1.2 Committing a Transaction 3
7.1.3 About Transaction and Template Objects 3
7.1.4 Beginning a Child Transaction 3
B SingleSelectionTemplate Class
B.1 Code for the SingleSelectionTemplate Class B-1
Index
Audience
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.
Documentation Accessibility
For information about Oracle's commitment to accessibility, visit the Oracle Accessibility
Program website at [Link]
Related Documents
For more information, see these Oracle resources:
• Oracle OLAP Java API Reference
• Oracle OLAP User's Guide
• Oracle OLAP DML Reference
Conventions
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.
• Deprecated Features
Deprecated Features
Oracle recommends that you do not use deprecated features or values in new applications.
Support for deprecated features is for backward compatibility only. For more information about
deprecated features, see Oracle Database Upgrade Guide.
Package Description
[Link] Contains classes that represent cursor managers and cursors that
retrieve the data specified by a Source object. For information on
Cursor objects, see Understanding Cursor Classes and Concepts and
Retrieving Query Results.
[Link] Contains classes that represent data sources and cursor specifications.
You use Source objects to create queries of the data store. With the
Template class you can incrementally build a Source object that
represents a query that you can dynamically modify. For information on
Source objects, see Understanding Source Objects and Making
Queries Using Source Methods. For information on Template objects,
see Creating Dynamic Queries.
Table 1-1 (Cont.) Packages of the OLAP Java API under [Link]
Package Description
metadata Contains classes that represent metadata objects, classes that map
[Link] the metadata objects to relational data sources, and classes that
deploy the metadata objects in an analytic workspace or in relational
[Link] database structures. For a description of these packages, see
[Link] Understanding OLAP Java API Metadata. For information on using the
classes in these packages, see Discovering Metadata and Creating
Metadata and Analytic Workspaces.
resource Contains classes that support the internationalization of messages for
Exception classes.
session Contains a class that represents a session in a connection to an Oracle
database.
syntax 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
Expression objects in mapping metadata objects to relational data
sources such as columns in a table or a view. You also use
Expression objects to specify calculations and analytical operations
for some metadata objects.
transaction Contains classes that represent transactions with Oracle OLAP in an
Oracle Database instance. You use Transaction objects to commit
changes to the database. For information on Transaction objects,
see Using a TransactionProvider.
The OLAP Java API also has packages organized under the [Link] 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 Setting Up the Development Environment.
Cubes
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
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
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
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
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
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.
Queries
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 [Link] 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.
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 Understanding OLAP Java API Metadata.
• Creating Queries
• Specifying Dimension Members
• Creating Cursors
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.
example, [Link], has methods that create and build an analytic workspace.
Another example, SpecifyAWValues, calls the methods of [Link] 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 website, you can download a file that contains SQL scripts that create the
Global schema and a file that contains the example programs. The OTN website is at http://
[Link]/technetwork/database/options/olap/[Link].
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 [Link]. The utility classes
include [Link] and [Link]. The [Link] 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
[Link] class is a PrintWriter that has methods that display the contents of
Cursor objects.
The OLAP metadata objects are created and built by the [Link] 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 Discovering Metadata.
Task 1: Connect to the Data Store and Create a DataProvider and UserSession
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 Discovering Metadata.
the metadata objects after mapping them. For information on creating metadata, deploying,
mapping, and building metadata objects, see Creating Metadata and Analytic Workspaces.
[Link]
Other classes in the package correspond to relational objects. Table 2-2 shows those
correspondences.
The ID of a metadata object is persistent. However, if the name or the owner of a metadata
object changes, then the ID changes as well. For more information on getting objects by ID,
see "Getting Metadata Objects by ID".
For a legacy 10g metadata object, the first part of the identifier is a namespace. The
namespace is followed by the namespace delimiter, which is two periods. An example of the
identifier of a 10g dimension is AWXML_DIMENSION..GLOBAL.PRODUCT_AW.
In Oracle Database, Release 10g, an Oracle OLAP cube, dimension, or measure folder could
have the same name as a relational table or view. In Release 11g, top-level OLAP metadata
objects are stored in the Oracle Database data dictionary, so they cannot have the same name
as another relational object. A namespace designation allows a legacy OLAP Java API 10g
metadata object to exist in the same session as 11g metadata objects. Such legacy metadata
objects were created by using classes in the [Link] package of the Oracle
OLAP Analytic Workspace Java API or by using CWM PL/SQL packages. For 10g and 11g
objects to exist in the same session, the metadata reader mode of the DataProvider must be
set to ALL. The ALL mode is the default metadata reader mode. For more information on
metadata reader mode settings, see the DataProvider class documentation in Oracle OLAP
Java API Reference.
The metadata objects for a 10g cube, dimension, and measure folder are represented in 11g
by the MdmCube, MdmPrimaryDimension, and MdmSchema classes. An instance of one of those
classes can have a namespace associated with it, which is returned by the getNamespace
method. For an 11g object, the namespace is null.
The 11g XML definition of a 10g object has a Namespace attribute. For information on exporting
and importing XML definitions of metadata objects, see "Exporting and Importing Metadata as
XML Templates".
The namespace of a legacy metadata object identifies the metadata format and the type of
object. It begins with either AWXML_ or CWM_ and then has the type of object, such as CUBE or
DIMENSION. For example, a dimension created by using the Oracle OLAP Analytic Workspace
Java API in Oracle Database 10g, Release 2 (10.2), would have the namespace
AWXML_DIMENSION in 11g.
The valid namespaces are represented by static constant fields of the MdmMetadataProvider
class. The getValidNamespaces method of that class returns a list of the valid namespaces,
including the default namespace. You cannot create a new namespace.
You can use the constant fields to get a legacy metadata object from an MdmDatabaseSchema.
For example, the following code gets the PRODUCT_AW dimension. In the code, mdmDBSchema
is the MdmDatabaseSchema for the GLOBAL user.
MdmStandardDimension mdmProdAWDim =
[Link]("PRODUCT_AW",
MdmMetadataProvider.AWXML_DIMENSION_NAMESPACE);
In the ALL metadata reader mode, you get an existing 10g metadata object but you cannot
create a new one. If the legacy metadata object does not exist, the method returns an 11g
object that has the specified name.
Note
A descriptive name that you associate with an MdmObject through an MdmDescription
is not the object name that is returned by the [Link] method. The object
name is used by Oracle OLAP to identify the object internally. A descriptive name is
used only by an application.
The OLAP Java API defines some types of descriptions. The MdmDescriptionType class has
static methods that provide the following description types:
• Name
• Short name
• Long name
• Plural name
• Short plural name
• Long plural name
• Description
• Short description
• Long description
You get one of these defined description types by calling a method of MdmDescriptionType.
For example, the following code gets the description type object for a long name and a long
description.
MdmDescriptionType mdmLongNameDescrType =
[Link]();
MdmDescriptionType mdmLongDescrDescrType =
[Link]();
Some of the defined description types have an associated default description type. You change
a default description type or assign a default description type for a new or existing
MdmDescriptionType by using the MdmDescriptionType([Link] type,
MdmDescriptionType defaultType) constructor method. You can get the default type of an
MdmDescriptionType object with the getDescriptiveTypeDefault method.
This example shows both ways of associating an MdmDescription with an MdmObject. In the
example, mdmProdDim is an MdmStandardDimension object.
MdmDescription mdmShortNameDescr =
[Link](
[Link](), "AMERICAN");
[Link]("Product");
[Link](
[Link](), "Product Dimension");
This figure shows the methods of MdmObject that use MdmDescription and
MdmDescriptionType objects. It also shows the MdmDescription and MdmDescriptionType
classes and their methods, and the associations between the classes. An MdmObject can have
from zero to many MdmDescription objects. An MdmDescription is associated with one
MdmObject and one MdmDescriptionType. An MdmDescriptionType can be associated with one
or more MdmDescription objects.
MdmObject
0..*
MdmDescription MdmDescriptionType
Versions of the OLAP Java API before 11g did not have the MdmDescription and
MdmDescriptionType classes. In those versions, the MdmObject class had only the following
methods for getting and setting descriptions.
Figure 2-3 Methods for Getting and Setting Descriptions Before 11g
MdmObject
getDescription() : String
getShortDescription() : String
setShortDescription(String description) : void
setDescription(String description) : void
For backward compatibility, the OLAP Java API still supports these methods, but implements
them internally using MdmDescription and MdmDescriptionType objects.
MdmDatabaseSchema objects are owners of top-level metadata objects such as AW, MdmCube, and
MdmPrimaryDimension objects. The top-level objects are first-class data objects and are
represented in the Oracle Database data dictionary. Because they are in the data dictionary,
these OLAP data objects are available to SQL queries. You create top-level metadata objects
by using findOrCreate methods of an MdmDatabaseSchema.
The top-level objects are the containers of objects such as MdmMeasure, MdmHierarchy, and
MdmAttribute objects. You create the contained objects by using methods of the top-level
objects.
For more information on MdmSchema objects, see "Representing Schemas". For information on
top-level metadata objects, see "Providing Access to Data Sources".
You can also get an existing metadata object by calling the getMetadataObject or
getMetadataObjects method of the MdmMetadataProvider and providing the ID of the
metadata object.
The following topics describe getting metadata objects:
• Getting Metadata Objects by ID
• Exporting and Importing Metadata as XML Templates
• Getting Metadata Objects by ID
• Exporting and Importing Metadata as XML Templates
You can store the ID of a metadata object from one session and then get the object by that ID
in another session. Of course, getting an object by a stored ID assumes that the object still
exists and that the ID of the object has not changed. For some metadata objects, you can
change the name or the owner. If the name or owner of the object changes, then the ID of the
object changes.
When exporting XML, you can rename objects or specify bind variables for the values of XML
attributes. You can also supply an implementation of the XMLWriterCallback interface to
manage some aspects of the export process. When importing XML, you can specify an
MdmDatabaseSchema to own the imported objects, bind values to replace the bind variables in
the exported XML, and an implementation of the XMLParserCallback interface to manage
some aspects of the import process.
The following topics describe exporting and importing metadata objects through XML
templates.
• Exporting XML Templates
• Importing XML Templates
• Describing Bind Variables in XML Templates
• Exporting XML Templates
• Importing XML Templates
• Describing Bind Variables in XML Templates
You can use an XML template produced by these methods to import metadata objects through
the importXML methods of MdmMetadataProvider. You can also use the XML template to import
metadata objects in Analytic Workspace Manager.
An exportFullXML method exports the complete XML definitions for the specified objects or for
the objects that you have created or modified since a specified
[Link]. For an example of using the exportFullXML
method, see Example 4-10.
An exportIncrementalXML method exports only the XML attributes that have changed for a
metadata object since a specified Transaction. If you specify a List of objects, then the
exported templates contain the XML attributes that have changed for the objects that are in the
list. The exported incremental XML includes the type and name of the objects in the ownership
and containment hierarchy of the changed object.
The exportFullXML and exportIncrementalXML methods take various combinations of the
following parameters.
• A List of the objects to export or a Transaction.
• A Writer to which Oracle OLAP exports the XML. If you do not specify a Writer, then the
method returns a [Link] that contains the XML.
• A [Link] that has metadata object references as keys and that has, as the objects
for the keys, String values that contain new names for the referenced objects. With this
Map, you can rename an object that you export. You can specify null for the parameter if
you do not want to rename any objects.
If you specify a Map for this renameMap parameter, then the Oracle OLAP XML generator
renames a referenced object during the export. You can copy the definition of an existing
object this way, by renaming an object during the export of an XML template and then
importing the template.
• A boolean that specifies whether or not to include the name of the owning object in the
exported XML.
• An optional Map that has metadata object references as keys and that has, as the objects
for the keys, String values that function like SQL bind variables. For more information on
the bind variables in this parameter, see "Describing Bind Variables in XML Templates".
An importXML method imports XML definitions of objects and either creates new objects or
modifies existing objects. The importXML method take various combinations of the following
parameters.
• A [Link] for input of the XML or a String that contains the XML to import.
• An MdmDatabaseSchema to contain the new or modified metadata objects.
• A boolean, modifyIfExists, that indicates whether or not you want differences in the
imported XML definition to modify an existing object of the same name.
• An optional Map, bindValues, that contains bind variables as keys and, as the objects for
the keys, String values to replace the bind variables. For more information on the bind
values in this parameter, see "Describing Bind Variables in XML Templates".
• An optional implementation of the [Link] interface.
If the value of the modifyIfExists parameter is true and if the imported XML contains a full
definition for an object that already exists and the object definition is different from the XML,
then the method merges the new or changed elements of the object definition with the existing
definition of the object. If the value of modifyIfExists is false and if the XML contains a full
definition for an object that already exists, then the importXML method throws an exception.
With the bindValues parameter, you can specify a Map that has key/object pairs that Oracle
OLAP uses to replace bind variables when importing an XML template. A key in the Map is a
bind variable to replace and the object paired to the key is the value with which to replace the
bind variable. When you import a template, if you specify a Map that contains bind variables as
keys, then Oracle OLAP replaces a bind variable in the imported XML with the value specified
for the bind variable in the bindValues Map.
A value specified in the bindVariables map appears in the exported XML in the format
"&BV;", where BV is the bind variable.
The bindValues parameter of an importXML method specifies values that Oracle OLAP uses to
replace the bind variables when importing an XML template. When you import a template, if
you specify a Map that contains bind variables as keys, then Oracle OLAP replaces a bind
variable in the imported XML with the String specified as the object for the bind variable key in
the Map.
If you provide a Map for the bindValues parameter, then the inXML string that you provide to the
method must include the !DOCTYPE Metadata declaration and the bind variables in the XML to
import must be in the "&BV;" format.
The 11g OLAP Java API introduced subclasses of MdmSchema to separate and define the
different roles. In 11g, MdmSchema remains a concrete class for compatibility with the earlier
versions and for use in 10g metadata reader modes.
In 11g, an MdmSchema is an instance of one of the following subclasses of MdmSchema:
The MdmRootSchema class also contains all of the MdmCube, MdmMeasure, and
MdmPrimaryDimension objects that are provided by the MdmMetadataProvider, and has
methods for getting those objects. However, the List of objects returned by those methods
contains only the cubes, measures, or dimensions that the user has permission to see.
Figure 2-4 shows the associations between an MdmMetadataProvider and the subclasses of
MdmSchema.
1 1
MdmMetadataProvider MdmRootSchema
getRootSchema
1
getDatabaseSchema
0...* 1...* getDatabaseSchemas
addOrganizationalSchema
1
0...*
MdmOrganizationalSchema MdmDatabaseSchema
findOrCreateOrganizationalSchema
You can get one or all of the MdmDatabaseSchema objects with methods of the MdmRootSchema.
However, access to the objects that are owned by an MdmDatabaseSchema is determined by the
security privileges granted to the user of the session.
An MdmDatabaseSchema is the owner of top-level OLAP metadata objects and the objects
created by them. You use an MdmDatabaseSchema to get existing metadata objects or to create
new ones. The top-level objects are the following:
• AW
• MdmCube
• MdmNamedBuildProcess
• MdmOrganizationalSchema
• MdmPrimaryDimension
• MdmTable
Except for an MdmTable, you can create new top-level objects, or get existing ones, with the
findOrCreate methods such as findOrCreateAW and findOrCreateStandardDimension.
Creating objects is described in Discovering Metadata.
When you commit the Transaction in which you have created top-level OLAP metadata
objects, 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. In a client application, you 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.
You can get an MdmTable, or other top-level object, with the getTopLevelObject method. You
can get all of the instances of a particular type of top-level object with methods such as getAWs,
getDimensions, or getOrganizationalSchemas, or you can use the getSchemaObjects to get
all of the objects owned by the MdmDatabaseSchema. You can add or remove top-level objects
with methods like addAW and removeSchemaObject.
Figure 2-5 shows the associations between the classes that implement dimensional data
model objects. An MdmCube can contain from zero to many MdmMeasure objects. An MdmMeasure
is contained by one MdmCube object. An MdmCube can have from zero to many
MdmPrimaryDimension objects, which are associated with it through MdmDimensionality
objects. An MdmPrimaryDimension can contain from zero to many MdmDimensionLevel objects,
MdmHierarchy objects, and MdmAttribute objects.
0...*
MdmCube MdmPrimaryDimension
1 1 1 1
The classes that represent these dimensional or relational data objects are subclasses of the
MdmSource class. Subclasses of MdmSource have a getSource method, which returns a Source
object. You use Source objects to define a query of the data. You then use Cursor objects to
retrieve the data. For more information about working with Source and Cursor objects, see
Understanding Source Objects and Understanding Cursor Classes and Concepts.
You can also use SQL to query the views that Oracle OLAP automatically generates for the
cubes, dimensions, and hierarchies. For information on querying these views, see "Getting
Dimension and Hierarchy View and View Column Names".
The following topics describe the classes that provide access to data sources.
• Representing Cubes and Measures
• Representing Dimensions, Levels, and Hierarchies
• Representing Dimension Attributes
• Using OLAP Views
• Representing Cubes and Measures
• Representing Dimensions, Levels, and Hierarchies
• Representing Dimension Attributes
• Using OLAP Views
An MdmCube usually corresponds to a single fact table or view. To associate the table or view
with the cube, you use Query and CubeMap objects. You get the Query for the table or view and
then associate the Query with the CubeMap by using the setQuery method of the CubeMap.
The CubeMap contains MeasureMap and CubeDimensionalityMap objects that map the
measures and dimensions of the cube to data sources. With the MeasureMap, you specify an
MdmBaseMeasure and an Expression that identifies the column in the fact table or view that
contains the base data for the measure.
To map the dimensions of the cube you get the MdmDimensionality objects of the cube. You
create a CubeDimensionalityMap for each MdmDimensionality. You then specify an
Expression for the CubeDimensionalityMap that identifies the foreign key column for the
dimension in the fact table or view. If you want to specify a dimension column other than the
column for the leaf-level dimension members, then you must specify a join Condition with the
setJoinCondition method of the CubeDimensionalityMap.
For examples of creating MdmCube and MdmMeasure objects and mapping them, and of the other
operations described in this topic, see Example 4-7 and Example 4-8.
Figure 2-6 shows the associations between an MdmCube and the some of the classes
mentioned in this topic. The figure shows an MdmCube as deployed in an analytic workspace.
ConsistentSolveCommand
1...*
setConsistentSolveSpecification
findOrCreateAWCubeOrganization
ConsistentSolveSpecification AWCubeOrganization
1 1
findOrCreateCubeMap
addDimension
MdmDimensionality MdmCube CubeMap
0...* 1 0...*
1
MdmDimension 1 1
findOrCreateBaseMeasure findOrCreateDerivedMeasure
0...* 0...*
MdmBaseMeasure MdmDerivedMeasure
For example, suppose you have an MdmMeasure that has data that records the number of
product units sold to a customer during a time period and through a sales channel. The data of
the measure is organized by dimensions for products, times, customers, and channels (with a
channel representing the sales avenue, such as catalog or internet.). You can think of the data
as occupying a four-dimensional array with the product, time, customer, and channel
dimensions providing the organizational structure. The values of these four dimensions are
indexes for identifying each particular cell in the array. Each cell contains a single data value
for the number of units sold. You must specify a value for each dimension in order to identify a
value in the array.
The values of an MdmMeasure are usually numeric, but a measure can have values of other
data types. The concrete subclasses of MdmMeasure are MdmBaseMeasure and
MdmDerivedMeasure.
Some mdmUnitCost values are identified by a combination of leaf members (for example, a
particular product item and a particular month). Other mdmUnitCost values are identified by a
combination of aggregate members (for example, a particular product family and a particular
quarter). Still other mdmUnitCost values are identified by a mixture of leaf and aggregate
members.
The values of mdmUnitCost that are identified only by leaf members come directly from the
column in the database fact table (or fact table calculation). They represent the lowest level of
data. However, the values that are identified by at least one aggregate member are calculated
by Oracle OLAP. These higher-level values represent aggregated, or rolled-up, data. Thus, the
data represented by an MdmBaseMeasure is a mixture of fact table data from the data store and
aggregated data that Oracle OLAP makes available for analytical manipulation.
are in higher levels. Hierarchies define the relationships between the levels. Dimensions
usually have associated attributes.
The base class for dimension, level, and hierarchy objects is the abstract class MdmDimension,
which extends MdmSource. An MdmDimension has methods for getting and for removing the
attributes associated with the object. It also has methods for getting and setting the cardinality
and the custom order of the members of the object. The direct subclasses of MdmDimension are
the abstract MdmPrimaryDimension and MdmSubDimension classes.
• Buildable, which is a marker interface for objects that you can specify in constructing a
BuildItem.
• MdmMemberListMapOwner, which defines methods for finding or creating, or getting, a
MemberListMap object.
• MdmViewColumnOwner, which is marker interface for objects that can have an associated
MdmViewColumn.
• MetadataObject, which defines a method for getting a unique identifier.
• MdmQuery, which defines methods for getting the Query object associated with the
implementing class and for getting information about the Query.
An MdmPrimaryDimension can have component MdmDimensionLevel objects that organize the
dimension members into levels. It also can have MdmHierarchy objects, which organize the
levels into the hierarchies. An MdmPrimaryDimension has all of the members of the component
MdmHierarchy objects, while each of the MdmHierarchy objects has only the members in that
hierarchy.
You can get all of the MdmPrimaryDimension objects that are contained by an
MdmDatabaseSchema or an MdmOrganizationalSchema by calling the getDimensions method of
the object. An MdmDatabaseSchema has methods for finding an MdmTimeDimension or an
MdmStandardDimension by name or creating the object if it does not already exist.
An MdmPrimaryDimension has a method for getting a list of all of the MdmHierarchy objects that
it contains. It also has methods for finding an MdmLevelHierarchy or MdmValueHierarchy by
name or creating the object if it does not already exist.
The following topics describe the objects that represent level-based and value-based
hierarchies.
• Representing a Level-based Hierarchy
• Representing a Value-based Hierarchy
• Representing a Level-based Hierarchy
• Representing a Value-based Hierarchy
Oracle OLAP also expects that if a member is in a level below the top level, then that member
has a parent, and that the parent is in the level just above the level of the member. If a member
is not at the top level and that member either does not have a parent or the parent is not in the
next higher level, then the hierarchy is a skip-level hierarchy. You can specify allowing a
skip-level hierarchy by calling the setIsSkipLevel(true) method of the MdmLevelHierarchy.
Figure 2-7 illustrates the relationships of members in a regular hierarchy, a ragged hierarchy,
and two types of skip-level hierarchies.
Regular
Level Hierarchy Ragged Hierarchy Skip-level Hierarchies
Top level
Leaf level
An MdmLevelHierarchy has a method for getting a list of all of the MdmHierarchyLevel objects
that it contains. It also has a method for finding an MdmHierarchyLevel by name or creating the
object if it does not already exist.
An MdmPrimaryDimension can contain more than one MdmLevelHierarchy. For example, an
MdmTimeDimension dimension might have two MdmLevelHierarchy objects, one organized by
calendar year time periods and the other organized by fiscal year time periods. The
MdmHierarchyLevel objects of one hierarchy associate MdmDimensionLevel objects of calendar
year time periods with the hierarchy. The MdmHierarchyLevel objects of the other hierarchy
associate MdmDimensionLevel objects of fiscal year time periods with that hierarchy. Generally,
level-based hierarchies share the lowest level, so the MdmHierarchyLevel for the lowest level
of each of the hierarchies associates the same MdmDimensionLevel with each hierarchy. For
example, the calendar year hierarchy and the fiscal year hierarchy share the same
MdmHierarchyLevel of month time periods.
The order of the levels in the hierarchy is specified by the order in which you create the
MdmHierarchyLevel objects for the MdmLevelHierarchy. The first MdmHierarchyLevel that you
create is the highest level and the last one that you create is the lowest level. For an example
of creating a hierarchy, see "Creating and Mapping an MdmLevelHierarchy".
Table 2-3 shows the first few members of the PRODUCT_AWJ dimension and their related
short description and package attribute values. Only some of the members of the ITEM level of
the dimension have a package attribute. For other items, and for higher levels, the package
attribute value is null, which appears as NA in the table.
To get values from an MdmAttribute, you must join the Source for the MdmAttribute and a
Source that specifies one or more members of the MdmDimension. For an explanation of joining
Source objects, see Understanding Source Objects. For examples of joining the Source objects
for an MdmAttribute and an MdmDimension, see Example 4-5 and examples from
Understanding Source Objects and Making Queries Using Source Methods, such as
Example 5-7 and Example 6-10.
The following topics describe the classes that represent dimension attributes.
• Describing the MdmAttribute Class
• Describing the MdmBaseAttribute Class
• Describing the MdmDerivedAttribute Class
• Describing the MdmAttribute Class
• Describing the MdmBaseAttribute Class
• Describing the MdmDerivedAttribute Class
the values of the MdmBaseAttribute in an OLAP view. You can get the column for the
MdmBaseAttribute in the OLAP view by using the getETAttributeColumn method. That
method returns an MdmViewColumn object.
Examples of MdmBaseAttribute objects are the name attribute created and mapped in
Example 4-5 and the long description attribute created in Example 4-6. The mapping for that
long description attribute is in Example 4-3.
For regular OLAP queries, using Source objects, you only need to map an MdmBaseAttribute
to MdmDimensionLevel objects by using MemberListMap objects. For SQL queries against
OLAP views, you should map the attributes to MdmHierarchyLevel objects by using
HierarchyLevelMap objects.
By specifying true with the setAllowAutoDataTypeChange method, you can allow Oracle OLAP
to automatically set the SQL data type. If you allow the automatic changing of the SQL data
type, then Oracle OLAP ignores the SQL data type specified by the setSQLDataType method.
This can be useful if you map the same attribute to levels that have different data types, or if
the data type of a level changes.
for the MdmDimensionLevel named CHANNEL, you would create an AttributeMap by calling the
[Link] method and passing in the long description
MdmBaseAttribute and FRENCH as the String that specifies the language. You would then
specify GLOBAL.CHANNEL_DIM.CHANNEL_DSC_FRENCH as the Expression for the AttributeMap.
By using the setLanguage method of an AttributeMap, you can specify a language for an
AttributeMap after you have created it.
The language in use for the database determines which language appears in the OLAP view
for the dimension. Only one language is in use at a time in a session, but if the language in use
changes, then the language in the attribute column in the OLAP view also changes. For more
information on specifying languages for database sessions, see Setting Up a Globalization
Support Environment in Oracle AI Database Globalization Support Guide.
For materialized views, you should create a separate attribute for each language, so that there
is a long description attribute for English, one for French, and so on. That behavior is more
typical in SQL, which does not expect multivalued columns.
The OLAP view for a hierarchy of the dimension would then have a column for each of the long
description attributes. Those columns would contain the long description attribute values for
the members of the mapped hierarchy level and for the hierarchy members of all levels that are
descendants of the mapped level.
For example, the CreateAndBuildAW example class has a line of code that specifies populating
the lineage for the MdmBaseAttribute objects that it adds to each individual
MdmHierarchyLevel. The following line appears in the createLineageAttributes method of
the class.
[Link](true);
Example 2-2 shows the results of the following SQL query when that line of code is
commented out. Example 2-3 shows the results of the SQL query when the line is included in
the class. Both examples show the values that are in the selected columns of the OLAP view
for the PRODUCT_PRIMARY hierarchy. The view name is
PRODUCT_AWJ_PRODUCT_PRIMA_VIEW. The examples show only a few of the lines
returned by the SQL query.
SELECT TOTAL_PRODUCT_SHORT_DESC || '*' || CLASS_SHORT_DESC || '*' ||
FAMILY_SHORT_DESC || '*' || ITEM_SHORT_DESC
FROM PRODUCT_AWJ_PRODUCT_PRIMA_VIEW
ORDER BY TOTAL_PRODUCT nulls first, CLASS nulls first,
FAMILY nulls first, ITEM nulls first;
When Oracle OLAP creates a materialized view for a cube, it creates columns for the attributes
of the dimensions of the cube. For the name of a column, it uses the name of the attribute
column from the OLAP view of the dimension. To ensure that the column name is unique,
Oracle OLAP adds a default prefix to the name. You can specify the prefix by using the
setETAttrPrefix method of the MdmDimensionality object for a dimension of the cube.
You can change the name of the OLAP view by using the [Link] method. To
make the name change permanent, you must commit the Transaction.
The OLAP view for an MdmCube has a column for each measure of the cube, including each
derived measure. In Oracle OLAP User's Guide, a derived measure is known as a calculated
measure. A cube view also has a column for each dimension of the cube. For example, for the
MdmCube named UNITS_CUBE_AWJ, the view is named UNITS_CUBE_AWJ_VIEW. The
following code gets the names of the view columns.
MdmCube mdmUnitsCube = [Link]("UNITS_CUBE_AWJ");
List<MdmQueryColumn> mdmQCols = [Link]();
for (MdmQueryColumn mdmQCol : mdmQCols )
{
MdmViewColumn mdmViewCol = (MdmViewColumn) mdmQCol;
println([Link]());
}
The UNITS, SALES, and COST columns are for the measures of the cube, and the other four
columns are for the dimensions of the cube.
[Link] Getting Dimension and Hierarchy View and View Column Names
To get the name of the OLAP view for a dimension or a hierarchy, call the getETViewName()
method of the MdmPrimaryDimension or MdmHierarchy. You can get the name of a column in
the view by calling the appropriate method of the metadata object. For example, the following
code gets the name of the key column for the CHANNEL_AWJ dimension and the parent
column for the CHANNEL_PRIMARY hierarchy.
println([Link]().getViewColumnName());
MdmViewColumn mdmParentCol =(MdmViewColumn) [Link]();
println([Link]());
DIM_KEY
PARENT
You can change the name of the OLAP view by using the setETViewName method of the
MdmPrimaryDimension or MdmHierarchy.
The OLAP view for an MdmPrimaryDimension has a column for the dimension keys, a column
for each dimension level, and a column for each attribute associated with the dimension. For
example, for the MdmStandardDimension named CHANNEL_AWJ, the view is named
CHANNEL_AWJ_VIEW. The SQL command DESCRIBE CHANNEL_AWJ_VIEW displays the names
of the following columns.
DIM_KEY
LEVEL_NAME
MEMBER_TYPE
DIM_ORDER
LONG_DESCRIPTION
SHORT_DESCRIPTION
TOTAL_CHANNEL_LONG_DESC
TOTAL_CHANNEL_SHORT_DESC
CHANNEL_LONG_DESC
CHANNEL_SHORT_DESC
The OLAP view for an MdmHierarchy has a column for the dimension keys and a column for
the parent of a hierarchy member. If it is an MdmLevelHierarchy, then it also has a column for
each hierarchy level and a column for the depth of a level. If the hierarchy has one or more
added attributes, then the view has a column for each attribute. For example, for the
MdmLevelHierarchy named CHANNEL_PRIMARY, the view is named
CHANNEL_AWJ_CHANNEL_PRIMA_VIEW. The SQL command DESCRIBE
CHANNEL_AWJ_CHANNEL_PRIMA_VIEW displays the names of the following columns.
DIM_KEY
LEVEL_NAME
MEMBER_TYPE
DIM_ORDER
HIER_ORDER
LONG_DESCRIPTION
SHORT_DESCRIPTION
TOTAL_CHANNEL_LONG_DESC
TOTAL_CHANNEL_SHORT_DESC
CHANNEL_LONG_DESC
CHANNEL_SHORT_DESC
PARENT
DEPTH
TOTAL_CHANNEL
CHANNEL
from UNITS_CUBE_AWJ_VIEW, and joins the keys from the cube view to the hierarchy views
to select the data.
In the example, mdmDBSchema is the MdmDatabaseSchema for the GLOBAL user. The example is
an excerpt from the [Link] example program.
// Display the name of the OLAP view name for the hierarchy and
// display the names of the hierarchy levels.
displayViewAndLevelNames(mdmCalHier);
MdmPrimaryDimension mdmProdDim =
(MdmPrimaryDimension)[Link]("PRODUCT_AWJ");
MdmLevelHierarchy mdmProdHier =
[Link]("PRODUCT_PRIMARY");
displayViewAndLevelNames(mdmProdHier);
MdmPrimaryDimension mdmCustDim =
(MdmPrimaryDimension)[Link]("CUSTOMER_AWJ");
MdmLevelHierarchy mdmShipHier =
[Link]("SHIPMENTS");
displayViewAndLevelNames(mdmShipHier);
MdmPrimaryDimension mdmChanDim =
(MdmPrimaryDimension)[Link]("CHANNEL_AWJ");
MdmLevelHierarchy mdmChanHier =
[Link]("CHANNEL_PRIMARY");
displayViewAndLevelNames(mdmChanHier);
// Create a SQL SELECT statement using the names of the views and the
// levels.
// UNITS_CUBE_AWJ_VIEW has a column named SALES for the sales measure.
// TIME_AWJ_CALENDAR_YEAR_VIEW has a column named LONG_DESCRIPTION
// for the long description attribute.
// The hierarchy views have columns that have the same names as the levels.
String sql = "SELECT t.long_description time,\n" +
" ROUND([Link]) sales\n" +
" FROM TIME_AWJ_CALENDAR_YEAR_VIEW t,\n" +
" PRODUCT_AWJ_PRODUCT_PRIMA_VIEW p,\n" +
" CUSTOMER_AWJ_SHIPMENTS_VIEW cu,\n" +
" CHANNEL_AWJ_CHANNEL_PRIMA_VIEW ch,\n" +
" UNITS_CUBE_AWJ_VIEW f\n" +
" WHERE t.level_name = 'YEAR'\n" +
" AND p.level_name = 'TOTAL_PRODUCT'\n" +
" AND cu.level_name = 'TOTAL_CUSTOMER'\n" +
TIME SALES
---------- ----------------------
1998 100870877
1999 134109248
2000 124173522
2001 116931722
2002 92515295
2003 130276514
2004 144290686
2005 136986572
2006 140138317
2007 <null>
// Select single values for the hierarchies except for the time hierarchy.
Source prodSel = [Link]("PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL");
Source custSel = [Link]("SHIPMENTS::TOTAL_CUSTOMER::TOTAL");
Source chanSel = [Link]("CHANNEL_PRIMARY::TOTAL_CHANNEL::TOTAL");
getContext().commit();
getContext().displayResult(result);
The values of the Cursor for the result Source are the following. The code for formatting the
values is not shown. For the complete code for Example 2-4 and Example 2-5, see the
[Link] example program.
Year Sales
---- ------------
1998 100870876.58
1999 134109248.15
2000 124173521.55
2001 116931722.03
2002 92515295.02
2003 130276513.86
2004 144290685.55
2005 136986571.96
2006 140138317.39
2007 NA
• The Oracle Database instance is running and was installed with the OLAP option.
• The Oracle Database user ID that you are using for the connection has access to the
relational schemas that contain the data.
• The Oracle JDBC and OLAP Java API jar files are in your application development
environment. For information about setting up the required jar files, see Setting Up the
Development Environment.
The values of the properties for the OracleDataSource are from a [Link]
object. The url property has the form jdbc:oracle:thin:@serverName:portNumber:sid,
where serverName is the hostname of the server on which the Oracle Database instance is
running, portNumber is the number of the TCP/IP listener port for the database, and sid is the
system identifier (SID) of the database instance.
Example 3-1 Getting a JDBC OracleConnection
[Link] conn = null;
try
{
OracleDataSource ods = new OracleDataSource();
[Link]([Link]("url"));
[Link]([Link]("user"));
[Link]([Link]("password"));
conn = ([Link]) [Link]();
}
catch(SQLException e)
{
[Link]("Connection attempt failed. " + e);
}
In the example, the connection uses the Oracle JDBC thin driver. There are many ways to
specify your connection characteristics using the getConnection method. There are also other
ways to connect to an Oracle Database instance. For more information about Oracle JDBC
connections, see Oracle AI Database JDBC Developer’s Guide.
After you have the OracleConnection object, you can create OLAP Java API DataProvider
and UserSession objects.
Using the DataProvider, you can get the MdmMetadataProvider, which is described in
"Creating an MdmMetadataProvider". You use the DataProvider to get the
TransactionProvider and to create Source and CursorManager objects as described in
Understanding Source Objects and Making Queries Using Source Methods.
When you have completed your work with the database, use the [Link]
method.
Example 3-3 Closing the Connection
try
{
[Link](); // conn is the OracleConnection
}
catch(SQLException e)
{
[Link]("Cannot close the connection. " + e);
}
{
mp = (MdmMetadataProvider) [Link]();
}
catch (Exception e)
{
println("Cannot get the MDM metadata provider. " + e);
}
if ([Link]() > 0)
{
println("The MdmOrganizationalSchema subschemas of "
+ [Link]() + " are:");
Iterator orgSchemaListItr = [Link]();
while ([Link]())
{
MdmOrganizationalSchema mdmOrgSchema = (MdmOrganizationalSchema)
[Link]();
println([Link]());
getOrgSchemas(mdmOrgSchema);
}
}
else
{
println([Link]() + " does not have any" +
" MdmOrganizationalSchema subschemas.");
}
}
If you want to display all of the dimensions and methods that are owned by a particular user,
then you could get the lists of dimensions and measures from the MdmDatabaseSchema for that
user.
Example 3-7 Getting the Dimensions and Measures of an MdmDatabaseSchema
This example gets the dimensions and measures from the MdmDatabaseSchema from
Example 3-6. It displays the name of each dimension and measure.
private void getObjects(MdmDatabaseSchema mdmGlobalSchema)
{
List dimList = [Link]();
String objName = [Link]() + " schema";
getNames(dimList, "dimensions", objName);
UNIT_COST
UNIT_PRICE
SALES
UNITS
COST
To get the primary Source for a metadata object, an application calls the getSource method of
that metadata object. For example, if an application needs to display the quantity of product
units sold during the year 1999, then it must use the getSource method of the MdmMeasure for
that data, which is mdmUnits in the following example.
For more information about getting and working with primary Source objects, see
Understanding Source Objects.
manage objects. A dimensional metadata model typically includes the objects described in
Understanding OLAP Java API Metadata.
You implement the dimensional model by creating OLAP Java API metadata objects. You use
classes in the [Link] package to map the metadata objects to
relational source objects and to build analytic workspaces. You use classes in the
[Link] package to specify Expression objects that you use in mapping the
metadata. You use classes in the [Link] 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:
1. Create an AW object and MdmPrimaryDimension and MdmCube objects.
2. Deploy the MdmPrimaryDimension and MdmCube objects to the AW.
3. 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.
4. Map the metadata objects to the relational sources of the base data.
5. Commit the Transaction, which creates persistent objects in the database.
6. Load data into the objects from the relational sources by building the analytic workspace.
For a list of the topics that describe these steps, see Creating Metadata and Analytic
Workspaces.
Example 4-1 demonstrates getting the MdmDatabaseSchema for the GLOBAL user and creating
an AW. For an example that gets the MdmRootSchema, see Discovering Metadata.
The following topics describe how to create objects that represent a dimension and the levels
and hierarchies of a dimension.
• Creating and Mapping Dimensions
• Creating and Mapping Dimension Levels
• Creating and Mapping Hierarchies
• Creating and Mapping Dimensions
• Creating and Mapping Dimension Levels
• Creating and Mapping Hierarchies
createAndMapDimensionLevels(mdmChanDim);
createAndMapHierarchies();
commit(mdmChanDim);
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.
[Link]("GLOBAL.CHANNEL_DIM.TOTAL_ID");
[Link]("GLOBAL.CHANNEL_DIM.CHANNEL_ID");
[Link]("GLOBAL.CHANNEL_DIM.TOTAL_DSC");
[Link]("GLOBAL.CHANNEL_DIM.CHANNEL_DSC");
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 [Link] example program.
// Get the EMP table and the Query for the table.
MdmTable empTable = (MdmTable)[Link]("EMP");
//Get the Source objects for the dimension, the hierarchy, and the attribute.
Source empDim = [Link]();
Source valHier = [Link]();
Source empNameAttr = [Link]();
// Get the parent attribute and get the Source for it.
MdmAttribute mdmParentAttr = [Link]();
Source parentAttr = [Link]();
The output of the example 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)
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 = [Link]("LONG_DESCRIPTION");
[Link](true));
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.
AWCubeOrganization awCubeOrg =
[Link](aw);
[Link](AWCubeOrganization.NONE_MV_OPTION);
[Link](AWCubeOrganization.SHARED_MEASURE_STORAGE);
[Link]("NUMBER");
// set the expressions for the dimensions. The expressions specify the
// columns of the fact table for the dimensions.
}
}
You can import a metadata object definition as an XML template. After importing, you must
build the object.
Example 4-10 Exporting to an XML Template
This example 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.
... // In some method.
List objectsToExport = new ArrayList();
[Link](aw);
exportToXML(objectsToExport, "[Link]");
...
public void exportToXML(List objectsToExport, String fileName)
{
try
{
PrintWriter writer = new PrintWriter(new FileWriter(filename));
[Link](writer, // mp is the MdmMetadataProvider
objectsToExport,
null, // No Map for renaming objects
false); // Do not include the owner name
[Link]();
}
catch (IOException ie)
{
[Link]();
}
}
To create a query, you typically use the classes in the [Link] 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.
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.
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.
[Link]().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.
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 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.
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.
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.
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.
The following topics describe the join method, the concepts of outputs and inputs, and the
matching of inputs. They provide examples of producing Source objects that have outputs,
Source objects that have inputs, and join operations that match an input with a Source.
The Source on which you call the join method is the base of the join operation. The
parameters of the method are the following.
• Describing the joined Parameter
• Describing the comparison Parameter
• Describing the comparisonRule Parameter
• Describing the visible Parameter
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.
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 the following topics 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.
// Oracle OLAP translates this shortcut signature of the join method into the
The [Link](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
[Link]() 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 and names have three elements,
the number of elements in lettersWithNames is nine.
Because the visible parameter of [Link](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
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
The example has the same base, joined, and comparison Source objects as Example 5-3.
Source lettersAndNamesWithoutRemovedNames =
[Link](names,
someNames,
Source.COMPARISON_RULE_REMOVE,
true);
Source lettersWithSelectedNames =
[Link](names,
someNames,
Source.COMPARISON_RULE_SELECT,
true);
Source lettersWithSelectedNamesAndColors =
[Link](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
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 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.
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 Making Queries Using Source Methods 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 returned by the extract method is an extraction input. You can get the
extraction inputs by calling the getExtractionInputs method.
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.
The examples in the following topics demonstrate matching a Source with 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.
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
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 [Link](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
[Link](prodDim) with timeDim, the Source for the TIME_AWJ dimension. That join
operation matches the input of the Source derived by [Link](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.
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.
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.
Source letters = [Link](new String[] {"A", "B", "C"});
Source lettersValue = [Link]();
Source lettersByLettersValue = [Link](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
[Link](letters), then the Source produced by the join operation would contain the
Cartesian product of the base and joined Source objects.
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 the next example.
A Cursor for the pricesForSelectedProductsAndTimes Source has the values shown in the
following table. The table has headings added.
This example creates a list Source, sourcesToCombine, that has the two derived Source objects
as element values. The [Link]() method produces
sourcesToCombineWithAnInput, which is a Source that has sourcesToCombine as an input.
The join operation [Link](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.
MdmStandardDimension mdmProdDim =
[Link]("PRODUCT_AWJ");
StringSource prodDim = (StringSource) [Link]();
Source productsToSelect = [Link](new String[]
{"PRODUCT_PRIMARY::ITEM::ENVY ABM",
"PRODUCT_PRIMARY::ITEM::ENVY EXE",
"PRODUCT_PRIMARY::ITEM::ENVY STD"});
Source moreProductsToSelect = [Link](new String[]
{"PRODUCT_PRIMARY::ITEM::SENT FIN",
"PRODUCT_PRIMARY::ITEM::SENT MM",
"PRODUCT_PRIMARY::ITEM::SENT STD"});
Source sourcesToCombine =
[Link](new Source[] {productsToSelect, moreProductsToSelect});
Source sourcesToCombineWithAnInput = [Link]();
Source combinedProducts =
[Link](sourcesToCombine);
Source. You create a parameterized Source with a createSource method of the Parameter.
The Parameter supplies the value that the parameterized Source specifies.
The example 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.
This example 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.
StringParameter prodParam =
new StringParameter(dp, "PRODUCT_PRIMARY::FAMILY::LTPC");
Source prodParamSrc = [Link]();
Source paramProdSel = [Link]([Link](), prodParamSrc);
[Link]("PRODUCT_PRIMARY::FAMILY::DTPC");
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 chapter briefly describes the various kinds of Source methods, and discusses some of
them in greater detail. It also discusses how to make some typical OLAP queries using these
methods and provides examples of some of them.
This chapter includes the following topics:
• Describing the Basic Source Methods
• Using the Basic Methods
• Using Other Source Methods
• Describing the Basic Source Methods
• Using the Basic Methods
• Using Other Source Methods
Method Description
alias Returns a Source that has the same elements as the base Source, but
has the base Source as the type.
Method Description
distinct Returns a Source that has the same elements as the base Source,
except that any elements that are duplicated in the base appear only
once in the derived Source.
join Returns a Source that has the elements of the base Source that are
specified by the joined, comparison, and comparisonRule
parameters of the method call. If the visible parameter is true, then
the joined Source is an output of the resulting Source.
position Returns a Source that has the positions of the elements of the base
Source, and that has the base Source as an input.
recursiveJoin Similar to the join method, except that this method, in the Source that
it returns, orders the elements of the Source hierarchically by parent-
child relationships.
value Returns a Source that has the same elements as the base Source, but
that has the base Source as an input.
The following topics describe the basic Source methods and provide some examples of their
use.
• Using the Basic Methods
• Using Other Source Methods
then you need to match the inputs of the measure twice in the same join operation. To do so,
you can derive two Source objects that are aliases for the same dimension, make them inputs
of two Source objects that are derived from the measure, join each derived measure Source to
the associated aliased dimension Source objects, and then compare the results.
Example 6-1 performs such an operation. It produces a Source that specifies whether the
number of units sold for each value of the CHANNEL_AWJ dimension is greater than the
number of units sold for the other values of the CHANNEL_AWJ dimension.
The example joins units, which is the Source for a measure, to Source objects that are
selections of single values of three of the dimensions of the measure to produce unitsSel. The
unitsSel Source specifies the units elements for the dimension values that are specified by
the timeSel, custSel, and prodSel objects, which are outputs of unitsSel. The unitsSel
Source has the Source for CHANNEL_AWJ dimension as an input.
The timeSel, custSel, and prodSel Source objects specify single values from hierarchies of
the TIME_AWJ, CUSTOMER_AWJ, and PRODUCT_AWJ dimensions, respectively. The
timeSel value is CALENDAR_YEAR::MONTH::2001.01, which identifies the month January, 2001,
the custSel value is SHIPMENTS::SHIP_TO::BUSN WRLD SJ, which identifies the Business World
San Jose customer, and the prodSel value is PRODUCT_PRIMARY::ITEM::ENVY ABM, which
identifies the Envoy Ambassador portable PC.
The example next creates two aliases, chanAlias1 and chanAlias2, for chanHier, which is the
Source for the CHANNEL_PRIMARY hierarchy of the CHANNEL_AWJ dimension. It then
produces unitsSel1 by joining unitsSel with the Source returned by [Link]().
The unitsSel1 Source has the elements and outputs of unitsSel and it has chanAlias1 as an
input. Similarly, the example produces unitsSel2, which has chanAlias2 as an input.
The example uses the gt method of unitsSel1, which determines whether the values of
unitsSel1 are greater than the values of unitsSel2. The final join operations match
chanAlias1 with the input of unitsSel1 and match chanAlias2 with the input of unitsSel2.
The result Source specifies the query, "Are the units sold values of unitsSel1 for the channel
values of chanAlias1 greater than the units sold values of unitsSel2 for the channel values of
chanAlias2?" Because result is produced by the joining of chanAlias2 to the Source returned
by [Link](unitsSel2).join(chanAlias1), chanAlias2 is the first output of result, and
chanAlias1 is the second output of result.
A Cursor for the result Source has as values the boolean values that answer the query. The
values of the first output of the Cursor are the channel values specified by chanAlias2 and the
values of the second output are the channel values specified by chanAlias1.
The following is a display of the values of the Cursor formatted as a crosstab with headings
added. The column edge values are the values from chanAlias1, and the row edge values are
the values from chanAlias2. The values of the crosstab cells are the boolean values that
indicate whether the units sold value for the column channel value is greater than the units sold
value for the row channel value. For example, the crosstab values in the first column indicate
that the units sold value for the column channel value Total Channel is not greater than the
units sold value for the row Total Channel value but it is greater than the units sold value for
the Direct Sales, Catalog, and Internet row values.
----------------- chanAlias1 ----------------
chanAlias2 TotalChannel Catalog Direct Sales Internet
------------ ------------ ------- ------------ --------
TotalChannel false false false false
Catalog true false false false
Direct Sales true true false false
Internet true true true false
The example gets the MdmStandardDimension object for the CUSTOMER_AWJ dimension and
gets the MdmLevelHierarchy object for the MARKETS hierarchy of that dimension. It gets the
StringSource object, mktHier, for the MdmLevelHierarchy. It then uses the selectValues
method of mktHier to produce two selections of members of the hierarchy, customersToSelect
and moreCustomersToSelect. Two of the members of customersToSelect are also present in
moreCustomersToSelect.
The example uses the appendValues method to combine the elements of customersToSelect
and moreCustomersToSelect in the combinedCustomers Source. Finally, the example uses the
distinct method of combinedCustomers, which returns a Source,
distinctCombinedCustomers, that has only the distinct members of the hierarchy.
Source customersToSelect =
[Link](new String[] {"MARKETS::SHIP_TO::KOSH ENT BOS",
"MARKETS::SHIP_TO::KOSH ENT TOK",
"MARKETS::SHIP_TO::KOSH ENT WAN"});
Source moreCustomersToSelect =
[Link](new String[] {"MARKETS::SHIP_TO::KOSH ENT BOS",
"MARKETS::SHIP_TO::KOSH ENT TOK",
"MARKETS::SHIP_TO::BUSN WRLD NY",
"MARKETS::SHIP_TO::BUSN WRLD SJ"});
Source combinedCustomers =
[Link](moreCustomersToSelect);
Most of the examples in this chapter use one or more signatures of the join method, as do
many of the examples in Understanding Source Objects. Example 6-3 uses the full join
signature and the simplest join signature. In the example, the full join signature
demonstrates the use of COMPARISON_RULE_DESCENDING as the comparisonRule parameter.
Source.COMPARISON_RULE_DESCENDING,
true)
.join(timeSelWithShortDescr)
.join(custSelWithShortDescr)
.join(chanSelWithShortDescr);
A Cursor for the result Source has the following values, displayed as a table. The table
includes only the short value descriptions of the hierarchy members and the sales amount
values, and has headings and formatting added.
Total Channel
Total Customer
MAY-01
Next, the example creates an array of Source objects and gets a List of the
MdmHierarchyLevel components of the hierarchy. It gets the Source object for each level and
adds it to the array, and then creates a list Source that has the Source objects for the levels as
element values.
The example then produces levelMembers, which is a Source that specifies the members of
the levels of the hierarchy. Because the comparison parameter of the join operation is the
Source produced by [Link](), levelMembers has levelList as an input. Therefore,
levelMembers is a Source that returns the members of each level, by level, when the input is
matched in a join operation.
The range Source specifies a range of elements from the second element to the next to last
element of a Source.
The next join operation produces the firstAndLast Source. The base of the operation is
levelMembers. The joined parameter is the Source that results from the
[Link]() method. The comparison parameter is the range Source and the
comparison rule is COMPARISON_RULE_REMOVE. The value of the visible parameter is true. The
firstAndLast Source therefore specifies only the first and last members of the levels because
it removes all of the other members of the levels from the selection. The firstAndLast Source
still has levelList as an input.
The final join operation matches the input of firstAndLast with levelList.
A Cursor for the result Source has the following values, displayed as a table with column
headings and formatting added. The left column names the level, the middle column is the
position of the member in the level, and the right column is the local value of the member. The
TOTAL_TIME level has only one member.
Level Member Position in Level Member Value
---------- ------------------------ ------------
TOTAL_TIME 1 TOTAL
YEAR 1 CY1998
YEAR 10 CY2007
QUARTER 1 CY1998.Q1
QUARTER 40 CY2007.Q4
MONTH 1 1998.01
MONTH 120 2007.12
The full recursiveJoin method has other parameters that specify the parent attribute of the
hierarchy, whether the result should have the parents before or after their children, and how to
order the elements of the result if the result includes children but not the parent. The
recursiveJoin method has several signatures that are shortcuts for the full signature.
Example 6-5 uses a recursiveJoin method that lists the parents first, restricts the parents to
the base, and does not add the joined Source as an output. The example first sorts the
members of the PRODUCT_PRIMARY hierarchy of the PRODUCT_AWJ dimension by
hierarchical levels and then by the value of the package attribute of each member.
In the first recursiveJoin method, the COMPARISON_RULE_ASCENDING parameter specifies that
the members of the prodHier hierarchy be in ascending alphabetical order within each level.
The prodParentAttr object is the Source for the parent attribute of the hierarchy.
The prodPkgAttr object in the second recursiveJoin method is the Source for the package
attribute of the dimension. Only the members of the ITEM level have a related package
attribute value. Because the members in the aggregate levels TOTAL_PRODUCT, CLASS, and
FAMILY, do not have a related package, the package attribute value for members in those
levels is null, which appears as NA in the results. Some of the ITEM level members do not
have a related package value, so their values are NA, also.
The second recursiveJoin method joins the package attribute values to their related hierarchy
members and sorts the members hierarchically by level, and then sorts them in ascending
alphabetical order in the level by the package attribute value. The
COMPARISON_RULE_ASCENDING_NULLS_FIRST parameter specifies that members that have a null
value appear before the other members in the same level. The example then joins the result of
the method, sortedHierAscending, to the package attribute to produce a Source that has the
package attribute values as element values and sortedHierAscending as an output.
The third recursiveJoin method is the same as the second, except that the
COMPARISON_RULE_DESCENDING_NULLS_FIRST parameter sorts the hierarchy members in
descending alphabetical order in the level by package attribute value.
Example 6-5 Sorting Products Hierarchically by Attribute
Source result1 = [Link]([Link](),
[Link](),
prodParentAttr,
Source.COMPARISON_RULE_ASCENDING);
Source sortedHierAscending =
[Link](prodPkgAttr,
[Link](),
prodParentAttr,
Source.COMPARISON_RULE_ASCENDING_NULLS_FIRST);
Source result2 = [Link](sortedHierAscending);
Source sortedHierDescending =
[Link](prodPkgAttr,
[Link](),
prodParentAttr,
Source.COMPARISON_RULE_DESCENDING_NULLS_FIRST);
Source result3 = [Link](sortedHierDescending);
A Cursor for the result1 Source has the following values, displayed with a heading added.
The list contains only the first seventeen values of the Cursor.
Product Primary Hierarchy Value
-------------------------------------
PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL
PRODUCT_PRIMARY::CLASS::HRD
PRODUCT_PRIMARY::FAMILY::DISK
PRODUCT_PRIMARY::ITEM::EXT CD ROM
PRODUCT_PRIMARY::ITEM::EXT DVD
PRODUCT_PRIMARY::ITEM::INT 8X DVD
PRODUCT_PRIMARY::ITEM::INT CD ROM
PRODUCT_PRIMARY::ITEM::INT CD USB
PRODUCT_PRIMARY::ITEM::INT RW DVD
PRODUCT_PRIMARY::FAMILY::DTPC
PRODUCT_PRIMARY::ITEM::SENT FIN
PRODUCT_PRIMARY::ITEM::SENT MM
PRODUCT_PRIMARY::ITEM::SENT STD
PRODUCT_PRIMARY::FAMILY::LTPC
PRODUCT_PRIMARY::ITEM::ENVY ABM
PRODUCT_PRIMARY::ITEM::ENVY EXE
PRODUCT_PRIMARY::ITEM::ENVY STD
...
A Cursor for the result2 Source has the following values, displayed as a table with headings
added. The table contains only the first seventeen values of the Cursor. The left column has
the member values of the hierarchy and the right column has the package attribute value for
the member.
The ITEM level members that have a null value appear first, and then the other level
members appear in ascending order of package value. Since the data type of the package
attribute is String, the package values are in ascending alphabetical order.
Product Primary Hierarchy Value Package Attribute Value
------------------------------------- -----------------------
PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL NA
PRODUCT_PRIMARY::CLASS::HRD NA
PRODUCT_PRIMARY::FAMILY::DISK NA
PRODUCT_PRIMARY::ITEM::EXT CD ROM NA
PRODUCT_PRIMARY::ITEM::INT 8X DVD NA
PRODUCT_PRIMARY::ITEM::INT CD USB NA
PRODUCT_PRIMARY::ITEM::EXT DVD Executive
PRODUCT_PRIMARY::ITEM::INT CD ROM Laptop Value Pack
PRODUCT_PRIMARY::ITEM::INT RW DVD Multimedia
PRODUCT_PRIMARY::FAMILY::DTPC NA
PRODUCT_PRIMARY::ITEM::SENT FIN NA
PRODUCT_PRIMARY::ITEM::SENT STD NA
PRODUCT_PRIMARY::ITEM::SENT MM Multimedia
PRODUCT_PRIMARY::FAMILY::LTPC NA
RODUCT_PRIMARY::ITEM::ENVY ABM NA
PRODUCT_PRIMARY::ITEM::ENVY EXE Executive
PRODUCT_PRIMARY::ITEM::ENVY STD Laptop Value Pack
...
A Cursor for the result3 Source has the following values, displayed as a table with headings
added. This time the members are in descending order, alphabetically by package attribute
value.
Product Primary Hierarchy Value Package Attribute Value
------------------------------------- -----------------------
PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL NA
PRODUCT_PRIMARY::CLASS::HRD NA
PRODUCT_PRIMARY::FAMILY::DISK NA
PRODUCT_PRIMARY::ITEM::EXT CD ROM NA
PRODUCT_PRIMARY::ITEM::INT 8X DVD NA
PRODUCT_PRIMARY::ITEM::INT CD USB NA
PRODUCT_PRIMARY::ITEM::INT RW DVD Multimedia
PRODUCT_PRIMARY::ITEM::INT CD ROM Laptop Value Pack
PRODUCT_PRIMARY::ITEM::EXT DVD Executive
PRODUCT_PRIMARY::FAMILY::DTPC NA
PRODUCT_PRIMARY::ITEM::SENT FIN NA
PRODUCT_PRIMARY::ITEM::SENT STD NA
PRODUCT_PRIMARY::ITEM::SENT MM Multimedia
PRODUCT_PRIMARY::FAMILY::LTPC NA
PRODUCT_PRIMARY::ITEM::ENVY ABM NA
PRODUCT_PRIMARY::ITEM::ENVY STD Laptop Value Pack
PRODUCT_PRIMARY::ITEM::ENVY EXE Executive
...
The first join method has custSel as the base and as the joined Source. It has custSel2 as
the comparison Source. The elements of the resulting Source, result1, are the Cartesian
product of the base and joined Source objects that are specified by the comparison Source.
The result1 Source has one set of the elements of custSel for each element of custSel that
is in the comparison Source. The true value of the visible parameter causes the joined
Source to be an output of result1.
The second join method also has custSel as the base and custSel2 as the comparison
Source, but it has the Source returned by the [Link]() method as the joined Source.
Because custSel is an input of the joined Source, the base Source matches with that input.
That input relationship causes the resulting Source, result2, to have only those elements of
custSel that are also in the comparison Source.
A Cursor for result1 has the values shown in the following table. The table has formatting and
headings that are not in the Cursor. The left column has the values of the elements of the
output of the Cursor. The right column has the base values of the Cursor.
Output Value result1 Value
--------------------------------- ---------------------------------
SHIPMENTS::SHIP_TO::COMP WHSE SJ SHIPMENTS::SHIP_TO::COMP WHSE ATL
SHIPMENTS::SHIP_TO::COMP WHSE SJ SHIPMENTS::SHIP_TO::COMP WHSE SJ
SHIPMENTS::SHIP_TO::COMP WHSE SJ SHIPMENTS::SHIP_TO::COMP WHSE SIN
SHIPMENTS::SHIP_TO::COMP WHSE SJ SHIPMENTS::SHIP_TO::COMP WHSE LON
SHIPMENTS::SHIP_TO::COMP WHSE SIN SHIPMENTS::SHIP_TO::COMP WHSE ATL
SHIPMENTS::SHIP_TO::COMP WHSE SIN SHIPMENTS::SHIP_TO::COMP WHSE SJ
SHIPMENTS::SHIP_TO::COMP WHSE SIN SHIPMENTS::SHIP_TO::COMP WHSE SIN
SHIPMENTS::SHIP_TO::COMP WHSE SIN SHIPMENTS::SHIP_TO::COMP WHSE LON
A Cursor for result2 has the following values, displayed as a table with headings added. The
left column has the values of the elements of the output of the Cursor. The right column has
the base values of the Cursor.
Output Value result2 Value
--------------------------------- ---------------------------------
SHIPMENTS::SHIP_TO::COMP WHSE SJ SHIPMENTS::SHIP_TO::COMP WHSE SJ
SHIPMENTS::SHIP_TO::COMP WHSE SIN SHIPMENTS::SHIP_TO::COMP WHSE SIN
Another example of reversing a relation is Example 6-10. It uses the value method in reversing
the parent attribute to get the children of a parent.
Example 6-7 first gets the MdmStandardDimension object for the CUSTOMER_AWJ dimension
and the MdmLevelHierarchy object for the MARKETS hierarchy of that dimension. It gets the
Source for the hierarchy.
The example next gets the ancestors attribute of the dimension and the Source for it. The
ancestors attribute relates each dimension member to the ancestors of that member.
To produce a Source that represents the descendants of each member of the dimension, the
example reverses the ancestor relation by joining the Source for the hierarchy, mktHier, with
the ancestors attribute, ancestorsAttr. The join operation uses [Link]() as the
comparison Source, so that the Source returned by the join operation, marketsDescendants,
has mktHier as an input. The marketsDescendants Source specifies, for each element of
ancestorsAttr, the elements of mktHier that have the ancestorsAttr element as their
ancestor. Because it has mktHier as an input, the marketsDescendants Source functions in the
same way as an attribute that represents the descendants relationship for the hierarchy.
The example demonstrates this when it joins mktHier to marketsDescendants in the following
line.
Source selValDescendants = [Link](mktHier, selVal);
In the join operation, the joined Source, mktHier, matches with the input of
marketsDescendants. The comparison Source is selVal, which specifies a single member of
the hierarchy. The join operation returns selValDescendants, which specifies the elements of
marketsDescendants that are the descendants of the selVal member. The result also includes
the ancestor member itself. The mktHier Source is not an output of selValDescendants
because the signature of the join method used derives a Source that does not have the joined
Source as an output.
The example next uses the full signature of the join method to produce
selValDescendantsOnly, which contains only the descendants and not the ancestor value. To
remove the ancestor value, the example again uses the value method, this time to return a
Source that is the joined parameter of the join operation that returns selValDescendantsOnly.
The comparison Source is selVal, and the comparison rule is COMPARISON_RULE_REMOVE.
The subclasses of Source each have other specialized methods, also. For example, the
NumberSource class has many methods that perform mathematical functions such as abs, div,
and cos, and methods that perform aggregations, such as average and total.
The following topics have examples that demonstrate the use of some of the Source methods.
Some of the examples are tasks that an OLAP application typically performs.
• Using the extract Method
• Creating a Cube and Pivoting Edges
• Drilling Up and Down in a Hierarchy
• Sorting Hierarchically by Measure Values
• Using NumberSource Methods To Compute the Share of Units Sold
• Selecting Based on Time Series Operations
• Selecting a Set of Elements Using Parameterized Source Objects
• Using the extract Method
• Creating a Cube and Pivoting Edges
• Drilling Up and Down in a Hierarchy
• Sorting Hierarchically by Measure Values
• Using NumberSource Methods To Compute the Share of Units Sold
• Selecting Based on Time Series Operations
• Selecting a Set of Elements Using Parameterized Source Objects
Example 6-8 uses the extract method to get the values of the NumberSource objects that are
themselves the values of the elements of the list Source measDim. Each of the NumberSource
objects represents a measure.
The example selects elements from StringSource objects for the hierarchies of the
dimensions of the UNITS_CUBE_AWJ cube. The cost, units, and sales objects are
NumberSource objects for the COST, UNITS, and SALES measures of the cube.
Next, the example creates measDim, which is a list Source that has the three NumberSource
objects as element values. It then uses the extract method to get the values of the
NumberSource objects. The resulting unnamed Source has measDim as an extraction input. The
first join operation has [Link]() as the base Source. The input of the base Source
matches with measDim, which is the joined parameter. The example then matches the other
inputs of the measures by joining the dimension selections to produce the result Source.
The following crosstab displays the values of a Cursor for the result Source, with headings
and formatting added.
SHIPMENTS::TOTAL_CUSTOMER::TOTAL
CHANNEL_PRIMARY::CHANNEL::DIR
CALENDAR_YEAR::MONTH::2001.05
joins the Source objects derived from the hierarchies to the Source for the measure to produce
the cube query. It commits the current Transaction, and then creates a Cursor for the query
and displays the values.
After displaying the values of the Cursor, the example changes the value of the Parameter for
the parameterized Source for the customer selection, thereby retrieving a different result set
using the same Cursor in the same Transaction. The example resets the position of the
Cursor, and displays the values of the Cursor again.
The example then pivots the column and row edges so that the column values are time
members and the row values are channel members. It commits the Transaction, creates
another Cursor for the query, and displays the values. It then changes the value of each
Parameter object and displays the values of the Cursor again.
The dp object is the DataProvider. The getContext method gets a Context11g object that has
a method that displays the values of the Cursor in a crosstab format.
The following crosstab has the values of cubeCursor displayed by the first
displayCursorAsCrosstab method.
Portable PCs
Europe
The following crosstab has the values of cubeCursor after the example changed the value of
the custParam Parameter object.
Portable PCs
North America
The next crosstab has the values of cubeCursor after pivoting the column and row edges.
Portable PCs
North America
The last crosstab has the values of cubeCursor after changing the value of the prodParam
Parameter object.
Desktop PCs
North America
// Get the short value descriptions for the members of the level.
Source levelSrcWithShortDescr = [Link](levelSrc);
[Link](levelElementChildren);
The following list has the values of the Cursor objects created by the displayResults
methods.
Level Source element values:
PRODUCT_PRIMARY::FAMILY::ACC,Accessories
PRODUCT_PRIMARY::FAMILY::DISK,CD/DVD
PRODUCT_PRIMARY::FAMILY::DOC,Documentation
PRODUCT_PRIMARY::FAMILY::DTPC,Portable PCs
PRODUCT_PRIMARY::FAMILY::LTPC,Desktop PCs
PRODUCT_PRIMARY::FAMILY::MEM,Memory
PRODUCT_PRIMARY::FAMILY::MOD,Modems/Fax
PRODUCT_PRIMARY::FAMILY::MON,Monitors
PRODUCT_PRIMARY::FAMILY::OS,Operating Systems
value description attribute of the dimension, and then joins the result of that operation,
sortedProductsShortDescr, to units.
The successive joinHidden methods join the selections of the other dimensions of units to
produce the result Source, which has the measure data as element values and
sortedProductsShortDescr as an output. The example uses the joinHidden methods so that
the other dimension selections are not outputs of the result.
The example uses the following objects.
• prodHier, which is the Source for the PRODUCT_PRIMARY hierarchy.
• units, which is the Source for the UNITS measure of product units sold.
• prodParentAttr, which is the Source for the parent attribute of the PRODUCT_PRIMARY
hierarchy.
• prodShortDescr, which is the Source for the short value description attribute of the
PRODUCT_AWJ dimension.
• custSel, which is a Source that specifies a single member of the SHIPMENTS hierarchy of
the CUSTOMER_AWJ dimension. The member is SHIPMENTS::TOTAL_CUSTOMER::TOTAL,
which is the total for all customers.
• chanSel, which is a Source that specifies a single member of the CHANNEL_PRIMARY
hierarchy of the CHANNEL_AWJ dimension. The member value is
CHANNEL_PRIMARY::CHANNEL::DIR, which is the direct sales channel.
• timeSel, which is a Source that specifies a single member of the CALENDAR_YEAR
hierarchy of the TIME_AWJ dimension. The member is CALENDAR_YEAR::YEAR::CY2001,
which is the year 2001.
Example 6-11 Hierarchical Sorting by Measure Value
Source sortedProduct =
[Link](units,
[Link](),
prodParentAttr,
Source.COMPARISON_RULE_ASCENDING,
true, // Parents first
true); // Restrict parents to base
A Cursor for the result Source has the following values, displayed in a table with column
headings and formatting added. The left column has the name of the level in the
PRODUCT_PRIMARY hierarchy. The next column to the right has the product identification value,
and the next column has the short value description of the product. The rightmost column has
the number of units of the product sold to all customers in the year 2001 through the direct
sales channel.
The table contains only the first nine and the last eleven values of the Cursor, plus the
Software/Other class value. The product values are listed hierarchically and in ascending order
by units sold. The Hardware class appears before the Software/Other class because the
Software/Other class has a greater number of units sold. In the Hardware class, the Portable
PCs family sold the fewest units, so it appears first. In the Software/Other class, the
Accessories family has the greatest number of units sold, so it appears last.
The prodFamilies object is the Source for the FAMILY level of the PRODUCT_PRIMARY
hierarchy. The join method of productShare, with prodFamilies as the joined Source,
produces a Source that specifies the share that each product family has of the total quantity of
products sold.
The custSel, chanSel, and timeSel Source objects are selections of single members of
hierarchies of the CUSTOMER_AWJ, CHANNEL_AWJ, and TIME_AWJ dimensions. The
remaining join methods match those Source objects to the other inputs of productShare, to
produce result. The join(Source joined, String comparison) signature of the join
method produces a Source that does not have the joined Source as an output.
The result Source specifies the share for each product family of the total quantity of products
sold to all customers through the direct sales channel in the year 2001.
A Cursor for the sortedResult Source has the following values, displayed in a table with
column headings and formatting added. The left column has the product family value and the
right column has the share of the total number of units sold for the product family to all
customers through the direct sales channel in the year 2001.
Product Family Member Share of Total Units Sold
----------------------------- -------------------------
PRODUCT_PRIMARY::FAMILY::LTPC 2.72%
PRODUCT_PRIMARY::FAMILY::MON 2.73%
PRODUCT_PRIMARY::FAMILY::MEM 3.57%
PRODUCT_PRIMARY::FAMILY::DTPC 5.13%
PRODUCT_PRIMARY::FAMILY::DOC 6.4%
PRODUCT_PRIMARY::FAMILY::DISK 11.71%
PRODUCT_PRIMARY::FAMILY::MOD 11.92%
PRODUCT_PRIMARY::FAMILY::OS 12.54%
PRODUCT_PRIMARY::FAMILY::ACC 43.28%
The unitPrice and unitPriceLag4 measures both have the Source objects for the
PRODUCT_AWJ and TIME_AWJ dimensions as inputs. The second join method matches
quarterLevel, which is a Source for the QUARTER level of the CALENDAR_YEAR hierarchy
of the TIME_AWJ dimension, with the TIME_AWJ dimension input of the measure, and makes
it an output of the resulting Source.
The joinHidden method matches prodSel with the PRODUCT_AWJ dimension input of the
measure, and does not make prodSel an output of the resulting Source. The prodSel Source
specifies the single hierarchy member PRODUCT_PRIMARY::FAMILY::DTPC, which is Desktop
PCs.
The lagResult Source specifies the aggregate unit prices for the Desktop PC product family
for each quarter and the quarter that is four quarters earlier.
A Cursor for the lagResult Source has the following values, displayed in a table with column
headings and formatting added. The left column has the quarter, the middle column has the
total of the unit prices for the members of the Desktop PC family for that quarter, and the right
column has the total of the unit prices for the quarter that is four quarters earlier. The first four
values in the right column are NA because quarter 5, Q1-98, is the first quarter in the
CALENDAR_YEAR hierarchy. The table includes only the first eight quarters.
Unit Price
Quarter Unit Price Four Quarters Before
--------------------------------- ---------- --------------------
CALENDAR_YEAR::QUARTER::CY1998.Q1 2687.54 NA
CALENDAR_YEAR::QUARTER::CY1998.Q2 2704.48 NA
CALENDAR_YEAR::QUARTER::CY1998.Q3 2673.27 NA
CALENDAR_YEAR::QUARTER::CY1998.Q4 2587.76 NA
CALENDAR_YEAR::QUARTER::CY1999.Q1 2394.79 2687.54
CALENDAR_YEAR::QUARTER::CY1999.Q2 2337.18 2704.48
CALENDAR_YEAR::QUARTER::CY1999.Q3 2348.39 2673.27
CALENDAR_YEAR::QUARTER::CY1999.Q4 2177.89 2587.76
...
The movingTotalResult Source specifies, for each quarter, the aggregate of the unit prices for
the members of the Desktop PC family for that quarter and the total of that unit price plus the
unit prices for the next three quarters.
NumberSource unitPriceMovingTotal =
[Link](mdmCalHier, 0, 3);
Source measuresDim =
[Link](new Source[]{unitPrice, unitPriceMovingTotal});
A Cursor for the movingTotalResult Source has the following values, displayed in a table with
column headings and formatting added. The left column has the quarter, the middle column
has the total of the unit prices for the members of the Desktop PC family for that quarter, and
the left column has the total of the unit prices for that quarter and the next three quarters. The
table includes only the first eight quarters.
The elements of the product Source specify the elements of the units measure that appear in
the result Source. By changing the values of the Parameter objects, you can select a different
set of units sold values using the same Cursor and without having to produce new Source and
Cursor objects.
Source paramProdSelInterval =
[Link](startParamSrc, endParamSrc);
Source paramProdSelIntervalShortDescr =
[Link](paramProdSelInterval);
NumberSource result =
(NumberSource)[Link](chanHier, "CHANNEL_PRIMARY::CHANNEL::INT")
.join(calHier, "CALENDAR_YEAR::YEAR::CY2001")
.join(shipHier, "SHIPMENTS::TOTAL_CUSTOMER::TOTAL")
.join(paramProdSelIntervalShortDescr);
getContext().displayCursor(resultCursor);
The following table displays the values of resultCursor, with column headings and formatting
added. The left column has the product hierarchy members, the middle column has the short
value description, and the right column has the quantity of units sold.
Product Description Units Sold
------------------------------------- ---------------------- ----------
PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL Total Product 55,872
PRODUCT_PRIMARY::CLASS::HRD Hardware 21,301
PRODUCT_PRIMARY::FAMILY::DISK Memory 6,634
PRODUCT_PRIMARY::ITEM::EXT CD ROM External 48X CD-ROM 136
PRODUCT_PRIMARY::ITEM::EXT DVD External - DVD-RW - 8X 1,526
PRODUCT_PRIMARY::ITEM::INT 8X DVD Internal - DVD-RW - 8X 1,543
A single-user application does not need to explicitly create a root Transaction. The ability to
create multiple root Transaction objects is provided for use by multithreaded, middle-tier
applications. If your application uses multiple root Transaction objects, the changes that the
application makes in one root Transaction can be overwritten by changes the application
makes in another root Transaction. The changes that occur in the last root Transaction that
the application commits are the changes that persist.
When you or Oracle OLAP creates the initial root Transaction, it is the current Transaction. If
you create another root Transaction, it becomes the current Transaction.
Oracle OLAP creates other Transaction objects as you create Source objects or child
Transaction objects under a root Transaction. You must commit the root Transaction for the
Oracle Database to add to persistent storage any metadata objects that you have created in
any Transaction in the session.
When you create a derived Source by calling a method of another Source, the derived Source
is created in the context of the current Transaction. The Source is active in the Transaction in
which you create it or in a child Transaction of that Transaction.
You get or set the current Transaction, or begin a child Transaction, by calling methods of a
TransactionProvider. In a child Transaction you can alter a query, for example by changing
the selection of dimension elements or by performing a different mathematical or analytical
operation on the data, which changes the state of a Template that you created in the parent
Transaction. By displaying the data specified by the Source produced by the Template in the
parent Transaction and also displaying the data specified by the Source produced by the
Template in the child Transaction, you can provide the end user of your application with the
means of easily altering a query and viewing the results of different operations on the same set
of data, or the same operations on different sets of data.
• Types of Transaction Objects
• Committing a Transaction
• About Transaction and Template Objects
• Beginning a Child Transaction
• About Rolling Back a Transaction
• Getting and Setting the Current Transaction
If you then create another derived Source or change the Template state again, then that
operation occurs in the same write Transaction. You can create any number of derived Source
objects, or make any number of Template state changes, in that same write Transaction. You
can use those Source objects, or the Source produced by the Template, to define a complex
query.
Before you can create a Cursor to fetch the result set specified by a derived Source, you must
move the Source from the child write Transaction into the parent read Transaction. To do so,
you commit the Transaction.
To get the data specified by the Source produced by the Template, you commit the write
Transaction into the parent read Transaction. You can then create a Cursor to fetch the data.
The changed state of the Template is not visible in the original parent. The changed state does
not become visible in the parent until you commit the child read Transaction into the parent
read Transaction.
After beginning a child read Transaction, you can begin a child read Transaction of that child,
or a grandchild of the initial parent Transaction. For an example of creating child and
grandchild Transaction objects, see Example 7-3.
Before rolling back a Transaction, you must close any CursorManager objects you created in
that Transaction. After rolling back a Transaction, any Source objects that you created or
Template state changes that you made in the Transaction are no longer valid. Any Cursor
objects you created for those Source objects are also invalid.
Once you roll back a Transaction, you cannot commit that Transaction. Likewise, once you
commit a Transaction, you cannot roll it back.
// Undo t3, which discards the state of topNBottom that was set in t4.
[Link](); // t3 disappears
1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL
2. PRODUCT_PRIMARY::CLASS::SFT
3. PRODUCT_PRIMARY::FAMILY::ACC
4. PRODUCT_PRIMARY::CLASS::HRD
5. PRODUCT_PRIMARY::FAMILY::MOD
6. PRODUCT_PRIMARY::FAMILY::OS
7. PRODUCT_PRIMARY::FAMILY::DISK
8. PRODUCT_PRIMARY::ITEM::MOUSE PAD
9. PRODUCT_PRIMARY::ITEM::OS 1 USER
10. PRODUCT_PRIMARY::ITEM::DLX MOUSE
1. PRODUCT_PRIMARY::ITEM::EXT CD ROM
2. PRODUCT_PRIMARY::ITEM::OS DOC ITA
3. PRODUCT_PRIMARY::ITEM::OS DOC SPA
4. PRODUCT_PRIMARY::ITEM::INT CD USB
5. PRODUCT_PRIMARY::ITEM::ENVY EXT KBD
6. PRODUCT_PRIMARY::ITEM::19 SVGA
7. PRODUCT_PRIMARY::ITEM::OS DOC FRE
8. PRODUCT_PRIMARY::ITEM::OS DOC GER
9. PRODUCT_PRIMARY::ITEM::ENVY ABM
10. PRODUCT_PRIMARY::ITEM::INT CD ROM
11. PRODUCT_PRIMARY::ITEM::ENVY EXE
12. PRODUCT_PRIMARY::ITEM::OS DOC KAN
13. PRODUCT_PRIMARY::ITEM::ENVY STD
14. PRODUCT_PRIMARY::ITEM::1GB USB DRV
15. PRODUCT_PRIMARY::ITEM::SENT MM
1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL
2. PRODUCT_PRIMARY::CLASS::SFT
3. PRODUCT_PRIMARY::FAMILY::ACC
4. PRODUCT_PRIMARY::CLASS::HRD
5. PRODUCT_PRIMARY::FAMILY::MOD
6. PRODUCT_PRIMARY::FAMILY::OS
7. PRODUCT_PRIMARY::FAMILY::DISK
8. PRODUCT_PRIMARY::ITEM::MOUSE PAD
9. PRODUCT_PRIMARY::ITEM::OS 1 USER
10. PRODUCT_PRIMARY::ITEM::DLX MOUSE
To make a previously saved Transaction the current Transaction, you call the
setCurrentTransaction method of the TransactionProvider, as in the following example.
[Link](t1);
If you are using Template objects in your application, then you might also use the other
methods of TransactionProvider to do the following:
// The commit moves the changes made in writeT3 into its parent,
// the read Transaction childT2. The writeT3 Transaction
// disappears. The current Transaction is now childT2
// again but the state of the TopBottomTemplate has changed.
getContext().displayTopBottomResult(result);
}
catch(Exception e)
{
println("Cannot display the results of the query. " + e);
}
// Commit writeT5.
commit();
// you can roll back the childT2 Transaction instead of committing it.
// If you do so, then the changes that you made in childT2 are discarded.
// The current Transaction is be parentT1, which has the original state
// of the TopBottomTemplate, without any of the changes made in the
// grandchild or the child transactions.
1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL
2. PRODUCT_PRIMARY::CLASS::SFT
3. PRODUCT_PRIMARY::FAMILY::ACC
4. PRODUCT_PRIMARY::CLASS::HRD
5. PRODUCT_PRIMARY::FAMILY::MOD
6. PRODUCT_PRIMARY::FAMILY::OS
7. PRODUCT_PRIMARY::FAMILY::DISK
8. PRODUCT_PRIMARY::ITEM::MOUSE PAD
9. PRODUCT_PRIMARY::ITEM::OS 1 USER
10. PRODUCT_PRIMARY::ITEM::DLX MOUSE
1. PRODUCT_PRIMARY::ITEM::EXT CD ROM
2. PRODUCT_PRIMARY::ITEM::OS DOC ITA
3. PRODUCT_PRIMARY::ITEM::OS DOC SPA
4. PRODUCT_PRIMARY::ITEM::INT CD USB
5. PRODUCT_PRIMARY::ITEM::ENVY EXT KBD
6. PRODUCT_PRIMARY::ITEM::19 SVGA
7. PRODUCT_PRIMARY::ITEM::OS DOC FRE
8. PRODUCT_PRIMARY::ITEM::OS DOC GER
9. PRODUCT_PRIMARY::ITEM::ENVY ABM
10. PRODUCT_PRIMARY::ITEM::INT CD ROM
11. PRODUCT_PRIMARY::ITEM::ENVY EXE
12. PRODUCT_PRIMARY::ITEM::OS DOC KAN
1. PRODUCT_PRIMARY::TOTAL_PRODUCT::TOTAL
2. PRODUCT_PRIMARY::CLASS::SFT
3. PRODUCT_PRIMARY::FAMILY::ACC
4. PRODUCT_PRIMARY::CLASS::HRD
5. PRODUCT_PRIMARY::FAMILY::MOD
6. PRODUCT_PRIMARY::FAMILY::OS
7. PRODUCT_PRIMARY::FAMILY::DISK
8. PRODUCT_PRIMARY::ITEM::MOUSE PAD
9. PRODUCT_PRIMARY::ITEM::OS 1 USER
10. PRODUCT_PRIMARY::ITEM::DLX MOUSE
11. PRODUCT_PRIMARY::ITEM::LT CASE
12. PRODUCT_PRIMARY::ITEM::56KPS MODEM
You can get the SQL generated for a Source by the Oracle OLAP SQL generator without
having to create a Cursor. To get the SQL for the Source, you create an SQLCursorManager by
using a createSQLCursorManager method of a DataProvider. You can then use classes
outside of the OLAP Java API, or other methods, to retrieve data using the generated SQL.
• Creating a Cursor
• Sources For Which You Cannot Create a Cursor
• Cursor Objects and Transaction Objects
behavior. You then create a CursorManager with a method that takes the Source and the
CursorInfoSpecification.
2. Creating a Cursor by calling the createCursor method of the CursorManager.
Creating a derived Source occurs in a write Transaction. Creating a Cursor occurs in a read
Transaction. After creating a derived Source, and before you can create a Cursor for that
Source, you must change the write Transaction into a read Transaction by calling the
commitCurrentTransaction methods of the TransactionProvider your application is using.
For information on Transaction and TransactionProvider objects, see Using a
TransactionProvider.
For a Cursor that you create for a query that includes a parameterized Source, you can change
the value of the Parameter object and then get the new values of the Cursor without having to
commit the Transaction again. For information on parameterized Source objects, see
Understanding Source Objects.
Interface Description
Cursor An abstract superclass that encapsulates the notion of a current position.
ValueCursor A Cursor that has a value at the current position. A ValueCursor has
no child Cursor objects.
Interface Description
CompoundCursor A Cursor that has child Cursor objects, which are a child ValueCursor
for the values of the Source associated with it and an output child
Cursor for each output of the Source.
• Structure of a Cursor
• Specifying the Behavior of a Cursor
The output of a Source is another Source. An output Source can itself have outputs. The child
Cursor for an output of a Source is a ValueCursor if the output Source does not have any
outputs and a CompoundCursor if it does.
Example 8-1 creates a query that specifies the prices of selected product items for selected
months. In the example, timeHier is a Source for a hierarchy of a dimension of time values,
and prodHier is a Source for a hierarchy of a dimension of product values.
If you create a Cursor for prodSel or for timeSel, then either Cursor is a ValueCursor because
both prodSel and timeSel have no outputs.
The unitPrice object is a Source for an MdmBaseMeasure that represents values for the price of
product units. The MdmBaseMeasure has as inputs the MdmPrimaryDimension objects
representing products and times, and the unitPrice Source has as inputs the Source objects
for those dimensions.
The example selects elements of the dimension hierarchies and then joins the Source objects
for the selections to that of the measure to produce querySource, which has prodSel and
timeSel as outputs.
The result set defined by querySource is the unit price values for the selected products for the
selected months. The results are organized by the outputs. Since timeSel is joined to the
Source produced by the [Link](prodSel) operation, timeSel is the slower varying
output, which means that the result set specifies the set of selected products for each selected
time value. For each time value the result set has three product values so the product values
vary faster than the time values. The values of the base ValueCursor of querySource are the
fastest varying of all, because there is one price value for each product for each day.
Example 9-1 in Retrieving Query Results, creates a Cursor, queryCursor, for querySource.
Since querySource has outputs, queryCursor is a CompoundCursor. The base ValueCursor of
queryCursor has values from unitPrice, which is the base Source of the operation that
created querySource. The values from unitPrice are those specified by the outputs. The
outputs for queryCursor are a ValueCursor that has values from prodSel and a ValueCursor
that has values from timeSel.
This figure illustrates the structure of queryCursor. The base ValueCursor and the two output
ValueCursor objects are the children of queryCursor, which is the parent CompoundCursor.
queryCursor
CompoundCursor
Base
Output 1 Output 2 ValueCursor
The following table displays the values from queryCursor in a table. The left column has time
values, the middle column has product values, and the right column has the unit price of the
product for the month.
For examples of getting the values from a ValueCursor, see Retrieving Query Results.
• getExtent
• getFetchSize
• getParentEnd
• getParentStart
• setFetchSize
For examples of specifying Cursor behavior, see Retrieving Query Results. For information on
fetch sizes, see "About Fetch Sizes". For information on the extent of a Cursor, see "What is
the Extent of a Cursor?". For information on the starting and ending positions in a parent
Cursor of the current value of a Cursor, see "About the Parent Starting and Ending Positions in
a Cursor".
Interface Description
CursorInfoSpecification An interface that specifies methods for
CursorSpecification objects.
CursorSpecification An abstract class that implements some methods of
the CursorInfoSpecification interface.
CompoundCursorSpecification A CursorSpecification for a Source that has
one or more outputs. A
CompoundCursorSpecification has component
child CursorSpecification objects.
CompoundInfoCursorSpecification An interface that specifies methods for
CompoundCursorSpecification objects.
ValueCursorSpecification A CursorSpecification for a Source that has
values and no outputs.
ValueCursorInfoSpecification An interface for ValueCursorSpecification
objects.
You can create more than one Cursor from the same CursorManager, which is useful for
displaying data from a result set in different formats such as a table or a graph. All of the
Cursor objects created by a CursorManager have the same specifications, such as the default
fetch sizes. Because the Cursor objects have the same specifications, they can share the data
managed by the CursorManager.
A SQLCursorManager has methods that return the SQL generated by the Oracle OLAP SQL
generator for a Source. You create one or more SQLCursorManager objects by calling the
createSQLCursorManager or createSQLCursorManagers methods of a DataProvider. You do
not use a SQLCursorManager to create a Cursor. Instead, you use the SQL returned by the
SQLCursorManager with classes outside of the OLAP Java API, or by other means, to retrieve
the data specified by the query.
• Updating the CursorInfoSpecification for a CursorManager
After creating a new CursorInfoSpecification, you can create a new CursorManager for the
Source. You do not, however, need to create a new CursorManager. You can call the
updateSpecification method of the existing CursorManager to replace the previous
CursorInfoSpecification with the new CursorInfoSpecification. You can then create a
new Cursor from the CursorManager.
Oracle OLAP does not validate the position that you set on the Cursor until you attempt an
operation on the Cursor, such as calling the getCurrentValue method. If you set the current
position to a negative value or to a value that is greater than the number of positions in the
Cursor and then attempt a Cursor operation, then the Cursor throws a
PositionOutOfBoundsException.
• Positions of a ValueCursor
• Positions of a CompoundCursor
• About the Parent Starting and Ending Positions in a Cursor
• What is the Extent of a Cursor?
The following example sets the current position of prodSelValCursor to 2 and retrieves the
value at that position.
[Link](2);
println([Link]());
For more examples of getting the current value of a ValueCursor, see Retrieving Query
Results.
For example, querySource, the Source created in Example 8-1, has values from a measure,
unitPrice. The values are the prices of product units at different times. The outputs of
querySource are Source objects that represent selections of four month values from a time
dimension and three product values from a product dimension.
The result set for querySource has one measure value for each tuple (each set of output
values), so the total number of values is twelve (one value for each of the three products for
each of the four months). Therefore, the queryCursor CompoundCursor created for
querySource has twelve positions.
Each position of queryCursor specifies one set of positions of the outputs and the base
ValueCursor. For example, position 1 of queryCursor defines the following set of positions for
the outputs and the base ValueCursor:
This example illustrates the positions of queryCursor CompoundCursor, the base ValueCursor,
and the outputs.
queryCursor
CompoundCursor
Positions
1 Output 1 = 1, Output 2 = 1, VC=1
2 Output 1 = 1, Output 2 = 2, VC=1
3 Output 1 = 1, Output 2 = 3, VC=1
4 Output 1 = 2, Output 2 = 1, VC=1
5 Output 1 = 2, Output 2 = 2, VC=1
6 Output 1 = 2, Output 2 = 3, VC=1
7 Output 1 = 3, Output 2 = 1, VC=1
8 Output 1 = 3, Output 2 = 2, VC=1
9 Output 1 = 3, Output 2 = 3, VC=1
10 Output 1 = 4, Output 2 = 1, VC=1
11 Output 1 = 4, Output 2 = 2, VC=1
12 Output 1 = 4, Output 2 = 3, VC=1
The ValueCursor for queryCursor has only one position because only one value of unitPrice
is specified by any one set of values of the outputs. For a query such as querySource, the
ValueCursor of the Cursor has only one value, and therefore only one position, at a time for
any one position of the root CompoundCursor.
This figure illustrates one possible display of the data from queryCursor. It is a crosstab view
with four columns and five rows. In the left column are the month values. In the top row are the
product values. In each of the intersecting cells of the crosstab is the price of the product for
the month.
Product
Month ENVY ABM ENVY EXE ENVY STD
2001.01 3042.22 3223.28 2426.07
2001.04 3026.12 3107.65 2412.42
2001.07 2892.18 3155.91 2505.57
2001.10 2892.18 3105.53 2337.30
A CompoundCursor coordinates the positions of the ValueCursor objects relative to each other.
The current position of the CompoundCursor specifies the current positions of the descendent
ValueCursor objects.
Example 8-2 Setting the CompoundCursor Position and Getting the Current Values
This example sets the position of queryCursor and then gets the current values and the
positions of the child Cursor objects.
CompoundCursor rootCursor = (CompoundCursor) queryCursor;
ValueCursor baseValueCursor = [Link]();
List outputs = [Link]();
ValueCursor output1 = (ValueCursor) [Link](0);
ValueCursor output2 = (ValueCursor) [Link](1);
int pos = 5;
[Link](pos);
println("CompoundCursor position set to " + pos + ".");
println("The current position of the CompoundCursor is = " +
[Link]() + ".");
println("Output 1 position = " + [Link]() +
", value = " + [Link]());
println("Output 2 position = " + [Link]() +
", value = " + [Link]());
println("VC position = " + [Link]() +
", value = " + [Link]());
The positions of queryCursor are symmetric in that the result set for querySource always has
three product values for each time value. The ValueCursor for prodSel, therefore, always has
three positions for each value of the timeSel ValueCursor. The timeSel output ValueCursor is
slower varying than the prodSel ValueCursor.
In an asymmetric case, however, the number of positions in a ValueCursor is not always the
same relative to the slower varying output. For example, if the price of units for product ENVY
ABM for month 2001.10 were null because that product was no longer being sold by that date,
and if null values were suppressed in the query, then queryCursor would only have eleven
positions. The ValueCursor for prodSel would only have two positions when the position of the
ValueCursor for timeSel was 4.
Example 8-3 demonstrates an asymmetric result set that is produced by selecting elements of
one dimension based on a comparison of measure values. The example uses the same
product and time selections as in Example 8-1. It uses a Source for a measure of product units
sold, units, that is dimensioned by product, time, sales channels, and customer dimensions.
The chanSel and custSel objects are selections of single values of the dimensions. The
example produces a Source, querySource2, that specifies which of the selected products sold
more than one unit for the selected time, channel, and customer values. Because
querySource2 is a derived Source, this example commits the current Transaction.
The example creates a Cursor for querySource2, loops through the positions of the
CompoundCursor, gets the position and current value of the first output ValueCursor and the
ValueCursor of the CompoundCursor, and displays the positions and values of the ValueCursor
objects. The getLocalValue method is a method in the program that extracts the local value
from a unique value.
Example 8-3 Positions in an Asymmetric Query
// Create the query
[Link](chanSel).join(custSel).join(timeSel).select([Link](1));
Because not every combination of product and time selections has unit sales greater than 1 for
the specified channel and customer selections, the number of elements of the ValueCursor for
the values derived from prodSel is not the same for each value of the output ValueCursor. For
time value 2001.01, all three products have sales greater than one, but for time value 2001.04,
only one of the products does. The other two time values, 2001.07 and 2001.10, have two
products that meet the criteria. Therefore, the ValueCursor for the CompoundCursor has three
positions for time 2001.01, only one position for time 2001.04, and two positions for times
2001.07 and 2001.10.
edge of a cube, then you might want to know how many columns to draw in the display for the
row.
To determine how many faster varying values exist for the current value of a child Cursor, you
find the starting and ending positions of that current value in the parent Cursor. Subtract the
starting position from the ending position and then add 1, as in the following.
long span = ([Link]() - [Link]()) + 1;
The result is the span of the current value of the child Cursor in the parent Cursor, which tells
you how many values of the fastest varying child Cursor exist for the current value. Calculating
the starting and ending positions is costly in time and computing resources, so you should only
specify that you want those calculations performed when your application needs the
information.
An Oracle OLAP Java API Cursor enables your application to have only the data that it is
currently displaying actually present on the client computer. For information on specifying the
amount of data for a Cursor, see "About Fetch Sizes".
From the data on the client computer, however, you cannot determine at what position of the
parent Cursor the current value of a child Cursor begins or ends. To get that information, you
use the getParentStart and getParentEnd methods of a Cursor.
To specify that you want Oracle OLAP to calculate the starting and ending positions of a value
of a child Cursor in the parent Cursor, call the setParentStartCalculationSpecified and
setParentEndCalculationSpecified methods of the CursorSpecification corresponding to
the Cursor. You can determine whether calculating the starting or ending positions is specified
by calling the isParentStartCalculationSpecified or isParentEndCalculationSpecified
methods of the CursorSpecification. For an example of specifying these calculations, see
Retrieving Query Results.
To specify that you want Oracle OLAP to calculate the extent for a Cursor, call the
setExtentCalculationSpecified method of the CursorSpecification corresponding to the
Cursor. You can determine whether calculating the extent is specified by calling the
isExtentCalculationSpecified method of the CursorSpecification. For an example of
specifying the calculation of the extent of a Cursor, see Retrieving Query Results.
your application needs them. By managing the virtual Cursor, the CursorManager relieves your
application of a substantial burden.
The amount of data that a Cursor retrieves in a single fetch operation is determined by the
fetch size specified for the Cursor. You specify a fetch size to limit the amount of data your
application needs to cache on the local computer and to maximize the efficiency of the fetch by
customizing it to meet the needs of your method of displaying the data.
You can also regulate the number of elements that Oracle OLAP returns by using Parameter
and parameterized Source objects in constructing your query. For more information on
Parameter objects, see Understanding Source Objects. For examples of using parameterized
Source objects, see Making Queries Using Source Methods.
When you create a CursorManager for a Source, Oracle OLAP specifies a default fetch size on
the root CursorSpecification. You can change the default fetch size with the
setDefaultFetchSize method of the root CursorSpecification.
You can create two or more Cursor objects from the same CursorManager and use both
Cursor objects simultaneously. Rather than having separate data caches, the Cursor objects
can share the data managed by the CursorManager.
An example is an application that displays the results of a query to the user as both a table and
a graph. The application creates a CursorManager for the Source. The application creates two
separate Cursor objects from the same CursorManager, one for a table view and one for a
graph view. The two views share the same query and display the same data, just in different
formats.
Figure 8-4 A Source and Two Cursors for Different Views of the Values
This figure illustrates the relationship between the Source, the Cursor objects, and the views.
queryCM : CursorManager
querySource : Source
1. Get a primary Source from an MdmObject or create a derived Source through operations on
a DataProvider or a Source. For information on getting or creating Source objects, see
Understanding Source Objects.
2. If the Source is a derived Source, then commit the Transaction in which you created the
Source. To commit the Transaction, call the commitCurrentTransaction method of your
TransactionProvider. For more information on committing a Transaction, see Using a
TransactionProvider. If the Source is a primary Source, then you do not need to commit the
Transaction.
3. Create a CursorManager by calling a createCursorManager method of your DataProvider
and passing that method the Source.
4. Create a Cursor by calling the createCursor method of the CursorManager.
Example 9-1 Creating a Cursor
This example creates a Cursor for the derived Source named querySource. The example uses
a DataProvider named dp. The example creates a CursorManager named cursorMngr and a
Cursor named queryCursor.
Finally, the example closes the CursorManager. When you have finished using the Cursor, you
should close the CursorManager to free resources.
CursorManager cursorMngr = [Link](querySource);
Cursor queryCursor = [Link]();
// Use the Cursor in some way, such as to display the values of it.
[Link]();
A ValueCursor is returned for a Source that has a single set of values. A ValueCursor has a
value at its current position, and it has methods for getting the value at the current position.
A CompoundCursor is created for a Source that has more than one set of values, which is a
Source that has one or more outputs. Each set of values of the Source is represented by a
child ValueCursor of the CompoundCursor. A CompoundCursor has methods for getting its child
Cursor objects.
The structure of the Source determines the structure of the Cursor. A Source can have nested
outputs, which occurs when one or more of the outputs of the Source is itself a Source with
outputs. If a Source has a nested output, then the CompoundCursor for that Source has a child
CompoundCursor for that nested output.
The CompoundCursor coordinates the positions of the child Cursor objects that it contains. The
current position of the CompoundCursor specifies one set of positions of the child Cursor
objects.
For an example of a Source that has only one level of output values, see Example 9-4. For an
example of a Source that has nested output values, see Example 9-5.
An example of a Source that represents a single set of values is one returned by the getSource
method of an MdmDimension, such as an MdmPrimaryDimension that represents product values.
Creating a Cursor for that Source returns a ValueCursor. Calling the getCurrentValue method
returns the product value at the current position of that ValueCursor.
// Product values are strings. Get the value at the current position.
String value = [Link]();
The example sets the position to the first position of the ValueCursor. The example loops
through the positions and uses the getCurrentValue method to get the value at the current
position.
// prodValues is the ValueCursor for prodSource.
[Link](1);
do
{
println([Link]);
} while([Link]());
The values of the result set represented by a CompoundCursor are in the child ValueCursor
objects of the CompoundCursor. To get those values, you must get the child ValueCursor
objects from the CompoundCursor.
// You can now get the values from the ValueCursor objects.
// When you have finished using the Cursor objects, close the CursorManager.
[Link]();
Example 9-5 uses the same units measure as Example 9-4, but it joins the dimension
selections to the measure differently. Example 9-5 joins two of the dimension selections
together. It then joins the result to the Source produced by joining the single dimension
selections to the measure. The resulting Source, unitsForSelections, represents a query has
nested outputs, which means it has more than one level of outputs.
The CompoundCursor that this example creates for unitsForSelections therefore also has
nested outputs. The CompoundCursor has a child base ValueCursor and has as outputs three
child ValueCursor objects and one child CompoundCursor.
Example 9-5 joins the selection of channel dimension values, chanSel, to the selection of
customer dimension values, custSel. The result is custByChanSel, a Source that has customer
values as the base values and channel values as the values of the output. The example joins
to units the selections of product and time values, and then joins custByChanSel. The
resulting query is represented by unitsForSelections.
The example commits the current Transaction and creates a CompoundCursor, named
unitsForSelCursor, for unitsForSelections.
The example gets the base ValueCursor and the outputs from the CompoundCursor. In the
example, dp is the DataProvider.
To display the results of a query in a table view, in which each row contains a value from each
output ValueCursor and from the base ValueCursor, you determine the position of the top-
level, or root, CompoundCursor and then iterate through its positions. Example 9-6 displays only
a portion of the result set at one time. It creates a Cursor for a Source that represents a query
that is based on a measure that has unit cost values. The dimensions of the measure are the
product and time dimensions. The creation of the primary Source objects and the derived
selections of the dimensions is not shown.
The example joins the Source objects representing the dimension value selections to the
Source representing the measure. It commits the current Transaction and then creates a
Cursor, casting it to a CompoundCursor. The example sets the position of the CompoundCursor,
iterates through twelve positions of the CompoundCursor, and prints out the values specified at
those positions. The DataProvider is dp.
If the time selection for the query has eight values, such as the first month of each calendar
quarter for the years 2001 and 2002, and the product selection has three values, then the
result set of the unitPriceByMonth query has twenty-four positions. The example displays the
following table, which has the values specified by positions 7 through 18 of the
CompoundCursor.
Month Product Unit Price
------- -------- ----------
2001.07 ENVY ABM 2892.18
2001.07 ENVY EXE 3155.91
2001.07 ENVY STD 2505.57
2001.10 ENVY ABM 2856.86
2001.10 ENVY EXE 3105.53
2001.10 ENVY STD 2337.3
2002.01 ENVY ABM 2896.77
2002.01 ENVY EXE 3008.95
2002.01 ENVY STD 2140.71
2002.04 ENVY ABM 2880.39
2002.04 ENVY EXE 2953.96
2002.04 ENVY STD 2130.88
{
String value = ((ValueCursor) columnCursor).getCurrentString();
print(getContext().getLocalValue(value) + " ");
} while ([Link]());
println("\n------- -------- -------- --------");
do
{
// Print the row dimension values.
String value = ((ValueCursor) rowCursor).getCurrentString();
print(getContext().getLocalValue(value) + " ");
// Loop over columns.
do
{
// Print data value.
print([Link]() + " ");
} while ([Link]());
println();
[Link]();
The following is a crosstab view of the values from the result set specified by the
unitPriceByMonth query. The first line labels the rightmost three columns as having product
values. The third line labels the first column as having month values and then labels each of
the rightmost three columns with the product value for that column. The remaining lines have
the month value in the left column and then have the data values from the units measure for
the specified month and product.
PRODUCT
---------------------------------
Month ENVY ABM ENVY EXE ENVY STD
------- -------- -------- --------
2001.01 3042.22 3223.28 2426.07
2001.04 3026.12 3107.65 2412.42
2001.07 2892.18 3155.91 2505.57
2001.10 2856.86 3105.53 2337.30
2002.01 2896.77 3008.95 2140.71
2002.04 2880.39 2953.96 2130.88
2002.07 2865.14 3002.34 2074.56
2002.10 2850.88 2943.96 1921.62
The query that results from joining the dimension selections to the measure Source represents
unit sold values as specified by the values of the outputs.
The example creates a Cursor for the query and then sends the Cursor to the
printAsCrosstab method, which prints the values from the Cursor in a crosstab. That method
calls other methods that print page, column, and row values.
The fastest-varying output of the Cursor is the selection of products, which has three values
(the product items ENVY ABM, ENVY EXE, and ENVY STD). The product values are the
column headings of the crosstab. The next fastest-varying output is the selection of customers,
which has three values (the customers COMP SERV TOK, COMP WHSE LON, and COMP
WHSE SD). Those three values are the row headings. The page dimensions are selections of
three time values (the months 2000.01, 2000.02, and 2000.03), and one channel value (DIR,
which is the direct sales channel).
The DataProvider is dp. The getLocalValue method gets the local value from a unique
dimension value.
// In someMethod.
Source unitsForSelections = [Link](prodSel)
.join(custSel)
.join(timeSel)
.join(chanSel);
// Commit the current Transaction (code not shown).
[Link]();
// The remainder of the code of someMethod is not shown.
The example displays the following values, formatted as a crosstab. The display has added
page, column, and row headings to identify the local values of the dimensions.
Channel DIR
Month 2001.01
Product
------------------------------
Customer ENVY ABM ENVY EXE ENVY STD
------------- -------- -------- --------
COMP WHSE SD 0 0 1
COMP SERV TOK 2 4 2
COMP WHSE LON 1 1 2
Channel DIR
Month 2000.02
Product
------------------------------
Customer ENVY ABM ENVY EXE ENVY STD
------------- -------- -------- --------
COMP WHSE SD 1 1 1
COMP SERV TOK 5 6 6
COMP WHSE LON 1 2 2
Channel DIR
Month 2000.03
Product
------------------------------
Customer ENVY ABM ENVY EXE ENVY STD
------------- -------- -------- --------
COMP WHSE SD 0 2 2
• The fetch size of a Cursor, which is the number of elements of the result set that the
Cursor retrieves during one fetch operation.
• Whether or not Oracle OLAP calculates the extent of the Cursor. The extent is the total
number of positions of the Cursor. The extent of a child Cursor of a CompoundCursor is
relative to any of the slower varying outputs of the CompoundCursor.
• Whether or not Oracle OLAP calculates the positions in the parent Cursor at which the
value of a child Cursor starts or ends.
To specify the behavior of Cursor, you use methods of a CursorSpecification that you
specify for that Cursor. A CursorSpecification implements the CursorInfoSpecification
interface.
You create a CursorSpecification for a Source by calling the
createCursorInfoSpecification method of the DataProvider. You use methods of the
CursorSpecification to set the characteristics that you want. You then create a
CursorManager by calling the appropriate createCursorManager method of the DataProvider.
Note
Specifying the calculation of the extent or the starting or ending position in a parent
Cursor of the current value of a child Cursor can be a very expensive operation. The
calculation can require considerable time and computing resources. You should only
specify these calculations when your application needs them.
Once you have the CursorSpecification objects, you can use their methods to specify the
behavior of the Cursor objects that correspond to them.
Example 9-10 specifies calculating the extent of a Cursor. The example uses the
CompoundCursorSpecification from Example 9-9.
Example 9-11 specifies calculating the starting and ending positions of the current value of a
child Cursor in the parent Cursor. The example uses the CompoundCursorSpecification from
Example 9-9.
Example 9-11 Specifying the Calculation of Starting and Ending Positions in a Parent
// Get the List of CursorSpecification objects for the outputs.
// Iterate through the list, specifying the calculation of the extent
// for each output CursorSpecification.
Iterator iterOutputSpecs = [Link]().iterator();
while([Link]())
{
ValueCursorSpecification valCursorSpec =
(ValueCursorSpecification)[Link]();
[Link](true);
[Link](true);
}
Example 9-12 determines the span of the positions in a parent CompoundCursor of the current
value of a child Cursor for two of the outputs of the CompoundCursor. The example uses the
unitForSelections Source from Example 9-8.
The example gets the starting and ending positions of the current values of the time and
product selections and then calculates the span of those values in the parent Cursor. The
parent is the root CompoundCursor. The DataProvider is dp.
Example 9-12 Calculating the Span of the Positions in the Parent of a Value
Source unitsForSelections = [Link](prodSel)
.join(custSel)
.join(timeSel)
.join(chanSel);
// Commit the current Transaction (code not shown).
// Get the values at the current position and determine the span
// of the values of the time and product outputs.
print([Link]() + ", ");
print([Link]() + ",\n ");
print([Link]() + ", ");
print([Link]() + ", ");
print([Link]());
println();
When a Source is created, Oracle OLAP automatically associates a SourceDefinition with it.
The SourceDefinition has information about the Source. Once created, the Source and the
associated SourceDefinition are associated immutably. The getSource method of a
SourceDefinition returns the Source associated with it.
The Source that a Template produces can change because the values, including other Source
objects, that the Template uses to create the Source can change. A Template stores those
values in a MetadataState. A Template provides methods to get the current state of the
MetadataState, to get or set a value, and to set the state. You use those methods to change
the data values that the MetadataState stores.
You use a DynamicDefinition to get the Source produced by a Template. If your application
changes the state of the values that the Template uses to create the Source, for example, in
response to end-user selections, then the application uses the same DynamicDefinition to get
the Source again, even though the new Source defines a result set different than the previous
Source.
The Source produced by a Template can be the result of a series of Source operations that
create other Source objects, such as a series of selections, sortings, calculations, and joins.
You put the code for those operations in the generateSource method of a SourceGenerator for
the Template. That method returns the Source produced by the Template. The operations use
the data stored in the MetadataState.
You might build an extremely complex query that involves the interactions of dynamic Source
objects produced by many different Template objects. The end result of the query building is a
Source that defines the entire complex query. If you change the state of any one of the
Template objects that you used to create the final Source, then the final Source represents a
result set that is different from that of the previous Source. You can thereby modify the final
query without having to reproduce all of the operations involved in defining the query.
10.1.2 About Translating User Interface Elements into OLAP Java API
Objects
You design Template objects to represent elements of the user interface of an application. Your
Template objects turn the selections that the end user makes into OLAP Java API query-
building operations that produce a Source. You then create a Cursor to fetch from Oracle
OLAP the result set defined by the Source. You get the values from the Cursor and display
them to the end user. When an end user makes changes to the selections, you change the
state of the Template. You then get the Source produced by the Template, create a new
Cursor, get the new values, and display them.
• What Is the Relationship Between the Classes That Produce a Dynamic Source?
• Template Class
• MetadataState Interface
• SourceGenerator Interface
• DynamicDefinition Class
• A Template has methods that create a DynamicDefinition and that get and set the current
state of a MetadataState. An extension to the Template abstract class adds methods that
get and set the values of fields on the MetadataState.
• The MetadataState implementation has fields for storing the data to use in generating the
Source for the Template. When you create a new Template, you pass the MetadataState
to the constructor of the Template. When you call the getSource method of the
DynamicDefinition, the MetadataState is passed to the generateSource method of the
SourceGenerator.
• The DataProvider is used in creating a Template and by the SourceGenerator in creating
new Source objects.
• The SourceGenerator implementation has a generateSource method that uses the current
state of the data in the MetadataState to produce a Source for the Template. You pass in
the SourceGenerator to the createDynamicDefinition method of the Template to create a
DynamicDefinition.
• The DynamicDefinition has a getSource method that gets the Source produced by the
SourceGenerator. The DynamicDefinition serves as a proxy for the SourceDefinition
that is immutably associated with the Source.
generateSource method uses the current state of the data represented by the MetadataState
for the Template.
To get the Source produced by the generateSource method, you create a DynamicDefinition
by passing the SourceGenerator to the createDynamicDefinition method of the Template.
You then get the Source by calling the getSource method of the DynamicDefinition.
A Template can create more than one DynamicDefinition, each with a differently implemented
SourceGenerator. The generateSource methods of the different SourceGenerator objects use
the same data, as defined by the current state of the MetadataState for the Template, to
produce Source objects that define different queries.
dimensions, the end user clicks an OK button on the second dialog box and returns to the
first dialog box.
• Click an OK button to generate the query. The results of the query appear.
To generate a Source that represents the query that the end user creates in the first dialog box,
you design a Template called TopBottomTemplate. You also design a second Template, called
SingleSelectionTemplate, to create a Source that represents the end user's selections of
single values for the dimensions other than the base dimension. The designs of your Template
objects reflect the user interface elements of the dialog boxes.
In designing the TopBottomTemplate and its MetadataState and SourceGenerator, you do the
following:
• Create a class called TopBottomTemplate that extends Template. To the class, you add
methods that get the current state of the Template, set the values specified by the user,
and then set the current state of the Template.
• Create a class called TopBottomTemplateState that implements MetadataState. You
provide fields on the class to store values for the SourceGenerator to use in generating the
Source produced by the Template. The values are set by methods of the
TopBottomTemplate.
• Create a class called TopBottomTemplateGenerator that implements SourceGenerator. In
the generateSource method of the class, you provide the operations that create the Source
specified by the end user's selections.
Using your application, an end user selects units sold as the measure and products as the
base dimension in the first dialog box. The end user also selects the Asia Pacific region, the
first quarter of 2001, and the direct sales channel as the single values for each of the
remaining dimensions.
The query that the end user has created requests the ten products that have the highest total
amount of units sold through the direct sales channel to customers in the Asia Pacific region
during the calendar year 2001.
For examples of implementations of the TopBottomTemplate, TopBottomTemplateState, and
TopBottomTemplateGenerator classes, and an example of an application that uses them, see
Example 10-1, Example 10-2, Example 10-3, and Example 10-4. The
TopBottomTemplateState and TopBottomTemplateGenerator classes are implemented as
inner classes of the TopBottomTemplate outer class.
/**
* Creates a TopBottomTemplateState, a TopBottomTemplateGenerator,
* and a DynamicDefinition.
* Gets the current state of the TopBottomTemplateState and the values
* that it stores.
* Sets the data values stored by the TopBottomTemplateState and sets the
* changed state as the current state.
*/
public class TopBottomTemplate extends Template
{
// Constants for specifying the selection of elements from the
// beginning or the end of the result set.
public static final int TOP_BOTTOM_TYPE_TOP = 0;
public static final int TOP_BOTTOM_TYPE_BOTTOM = 1;
/**
* Creates a TopBottomTemplate with a default type and number values
* and the specified base dimension.
*/
public TopBottomTemplate(Source base, DataProvider dataProvider)
{
super(new TopBottomTemplateState(base, TOP_BOTTOM_TYPE_TOP, 0),
dataProvider);
// Create the DynamicDefinition for this Template. Create the
// TopBottomTemplateGenerator that the DynamicDefinition uses.
dynamicDef =
createDynamicDefinition(new TopBottomTemplateGenerator(dataProvider));
}
/**
* Gets the Source produced by the TopBottomTemplateGenerator
* from the DynamicDefinition.
*/
public final Source getSource()
{
return [Link]();
}
/**
* Gets the Source that is the base of the elements in the result set.
* Returns null if the state has no base.
*/
public Source getBase()
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
return [Link];
}
/**
* Sets a Source as the base.
*/
public void setBase(Source base)
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
[Link] = base;
setCurrentState(state);
}
/**
* Gets the Source that specifies the measure and the single
* selections from the dimensions other than the base.
*/
public Source getCriterion()
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
return [Link];
}
/**
* Specifies a Source that defines the measure and the single values
* selected from the dimensions other than the base.
* The SingleSelectionTemplate produces such a Source.
*/
public void setCriterion(Source criterion)
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
[Link] = criterion;
setCurrentState(state);
}
/**
* Gets the type, which is either TOP_BOTTOM_TYPE_TOP or
* TOP_BOTTOM_TYPE_BOTTOM.
*/
public int getTopBottomType()
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
return [Link];
}
/**
* Sets the type.
*/
public void setTopBottomType(int topBottomType)
{
if ((topBottomType < TOP_BOTTOM_TYPE_TOP) ||
(topBottomType > TOP_BOTTOM_TYPE_BOTTOM ))
throw new IllegalArgumentException("InvalidTopBottomType");
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
[Link] = topBottomType;
setCurrentState(state);
}
/**
* Gets the number of values selected.
*/
public float getN()
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
return state.N;
}
/**
* Sets the number of values to select.
*/
public void setN(float N)
{
TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
state.N = N;
setCurrentState(state);
}
}
/**
* Creates a TopBottomTemplateState.
*/
public TopBottomTemplateState(Source base, int topBottomType, float N)
{
[Link] = base;
[Link] = topBottomType;
this.N = N;
}
/**
* Creates a copy of this TopBottomTemplateState.
*/
public final Object clone()
{
try
{
return [Link]();
}
catch(CloneNotSupportedException e)
{
return null;
}
}
}
/**
* Creates a TopBottomTemplateGenerator.
*/
/**
* Generates a Source for a TopBottomTemplate using the current
* state of the data values stored by the TopBottomTemplateState.
*/
public Source generateSource(MetadataState state)
{
TopBottomTemplateState castState = (TopBottomTemplateState) state;
if ([Link] == null)
throw new NullPointerException("CriterionParameterMissing");
Source sortedBase = null;
if ([Link] == TOP_BOTTOM_TYPE_TOP)
sortedBase = [Link]([Link], false);
else
sortedBase = [Link]([Link], true);
return [Link](1, [Link](castState.N));
}
}
/**
* Creates a query that specifies a number of elements from the top
* or bottom of a selection of dimension members, creates a Cursor
* for the query, and displays the values of the Cursor.
* The selected dimension members are those that have measure values
* that are specified by selected members of the other dimensions of
* the measure.
*/
public class TopBottomTest extends BaseExample11g
{
/**
* Gets the MdmMetadataProvider, the DataProvider, the MdmRootSchema, and the
* MdmDatabaseSchema for the current user.
* Gets the UNITS_CUBE_AWJ MdmCube.
* From the cube, gets the MdmBaseMeasure objects for the UNITS and SALES
* measures and the MdmPrimaryDimension objects that dimension them.
* Gets a hierarchy of the PRODUCT_AWJ dimension and the leaf level of the
* dimension.
* Gets the short description attribute of the dimension.
* Creates a SingleSelectionTemplate and adds selections to it.
* Creates a TopBottomTemplate and sets the properties of it.
* Gets the Source produced by the TopBottomTemplate, creates a Cursor
* for it, and displays the values of the Cursor.
* Changes the state of the SingleSelectionTemplate and the
* TopBottomTemplate, creates a new Cursor for the Source produced by the
* TopBottomTemplate, and displays the values of that Cursor.
*/
public void run() throws Exception
{
// Get the MdmMetadataProvider from the superclass.
MdmMetadataProvider metadataProvider = getMdmMetadataProvider();
// Get the DataProvider from the Context11g object of the superclass.
DataProvider dp = getContext().getDataProvider();
MdmCube unitsCube =
(MdmCube)[Link]("UNITS_CUBE_AWJ");
MdmBaseMeasure mdmUnits = [Link]("UNITS");
MdmBaseMeasure mdmSales = [Link]("SALES");
// Get the short description attribute for the PRODUCT_AWJ dimension and
// the Source for the attribute.
MdmAttribute mdmProdShortDescrAttr =
[Link]();
Source prodShortDescrAttr = [Link]();
// Specify whether to retrieve the elements from the beginning (top) or the
// end (bottom) of the selected elements of the base dimension.
[Link](TopBottomTemplate.TOP_BOTTOM_TYPE_TOP);
// Create a Cursor for the result and display the values of the Cursor.
getContext().displayTopBottomResult(result);
// Now change the measure to SALES, and get the top and bottom products by
// SALES.
[Link](sales);
// Change the number of elements selected.
[Link](7);
// Change the type of selection back to the top.
[Link](TopBottomTemplate.TOP_BOTTOM_TYPE_TOP);
topNBottomResult = [Link]();
result = [Link](topNBottomResult);
topNBottomResult = [Link]();
result = [Link](topNBottomResult);
/**
* Displays a description of the results of the query.
*
* @param singleSelections The SingleSelectionsTemplate used by the query.
*
* @param topNBottom The TopBottomTemplate used by the query.
*
* @param resultDescr A String that contains a description of the query.
*/
private void displayResultDescr(SingleSelectionTemplate singleSelections,
TopBottomTemplate topNBottom,
String resultDescr)
{
DataProvider dp = getContext().getDataProvider();
/**
* Runs the TopBottomTest application.
*
* @param args An array of String objects that provides the arguments
* required to connect to an Oracle Database instance, as
* specified in the Context11g class.
*/
public static void main(String[] args)
{
new TopBottomTest().execute(args);
}
}
The TopBottomTest program produces the following output.
The 10 products with the most units sold
for Asia Pacific, Direct Sales, 2001 are:
1. Mouse Pad
2. Unix/Windows 1-user pack
3. Deluxe Mouse
4. Laptop carrying case
5. 56Kbps V.90 Type II Modem
6. 56Kbps V.92 Type II Fax/Modem
7. Keyboard Wrist Rest
8. Internal - DVD-RW - 6X
9. O/S Documentation Set - English
10. External - DVD-RW - 8X
1. Sentinel Financial
2. Sentinel Standard
3. Envoy Executive
4. Sentinel Multimedia
5. Envoy Standard
6. Envoy Ambassador
7. 56Kbps V.90 Type II Modem
6. Standard Mouse
7. O/S Documentation Set - French
A.1 Overview
The OLAP Java API client software is a set of Java packages containing classes that
implement a Java programming interface to Oracle OLAP. An Oracle Database with the OLAP
option provides the OLAP Java API and other required class libraries as Java archive (JAR)
files. As an application developer, you must copy the required JAR files to the computer on
which you develop your Java application, or otherwise make them accessible to your
development environment.
When a Java application calls methods of OLAP Java API objects, it uses the OLAP Java API
client software to communicate with Oracle OLAP, which resides within an Oracle Database
instance. The communication between the OLAP Java API client software and Oracle OLAP is
provided through the Java Database Connectivity (JDBC) API, which is a standard Java
interface for connecting to relational databases. Another required JAR file provides support for
importing and exporting OLAP Java API metadata objects XML.
To use the OLAP Java API classes as you develop your application, import them into your
Java code. When you deliver your application to users, include the OLAP Java API classes
with the application. You must also ensure that users can access JDBC.
To develop an OLAP Java API application, you must have the Java Development Kit (JDK),
such as one in Oracle JDeveloper. Users must have a Java Runtime Environment (JRE)
whose version number is compatible with the JDK that you used for development.
• The [Link] file, which contains classes that provide XML parsing support.
• The Java Development Kit (JDK) version 1.6. The Oracle Database installation does not
provide the JDK. If you are using Oracle JDeveloper as your development environment,
then the JDK is already installed on your computer. However, ensure that you are using the
correct version of the JDK in JDeveloper. For information about obtaining and using some
other JDK, see the Oracle Technology Network Java website at [Link]
technetwork/java/[Link].
Table A-1 Required Class Libraries and Their Locations in the Oracle Installation
/**
* 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 [Link]();
}
/**
* Gets the Source for the measure stored by the SingleSelectionTemplateState.
*/
public Source getMeasure()
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
return [Link];
}
/**
* Specifies the Source for the measure stored by the
* SingleSelectionTemplateState.
*/
public void setMeasure(Source measure)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
[Link] = measure;
setCurrentState(state);
}
/**
* Gets the List of MdmDimensionMemberInfo objects for the selected members
* of the dimensions.
*/
public List getDimMemberInfos()
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
return [Link]([Link]);
}
/**
* Adds an MdmDimensionMemberInfo to the List of
* MdmDimensionMemberInfo objects.
*/
public void addDimMemberInfo(MdmDimensionMemberInfo mdmDimMemberInfo)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
[Link](mdmDimMemberInfo);
setCurrentState(state);
}
/**
* Changes the member specified for a dimension.
*/
public void changeSelection(MdmDimensionMemberInfo mdmDimMemberInfo)
{
SingleSelectionTemplateState state =
(SingleSelectionTemplateState)getCurrentState();
int i = 0;
(MdmDimensionMemberInfo)[Link]();
MdmPrimaryDimension mdmPrimDim1 = [Link]();
MdmPrimaryDimension mdmPrimDim2 =
[Link]();
//String value = (String)[Link]();
if ([Link]().equals([Link]()))
{
[Link](i);
[Link](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;
while([Link]())
{
MdmDimensionMemberInfo mdmDimMemInfo =
(MdmDimensionMemberInfo)[Link]();
MdmPrimaryDimension mdmPrimDim = [Link]();
MdmAttribute mdmShortDescrAttr =
[Link]();
Source shortDescrAttr = [Link]();
MdmHierarchy mdmHier = [Link]();
StringSource hierSrc = (StringSource) [Link]();
Source memberSel = [Link]([Link]());
Source shortDescrForMember = [Link](memberSel);
if(firsttime)
{
[Link](shortDescrForMemberVal);
firsttime = false;
}
else
{
[Link](", " + 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());
}
/**
* 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 = [Link];
inputs (continued) M
of a primary Source, 12
of a Source mapping
definition, 12 dimension levels, 3
deriving with the value method, 16 hierarchy levels, 4
matching with a Source, 13 measures, 9
obtaining, 12 objects contained by an MdmCube, 16
types of, 13 mapping package
interval method description, 3
example of, 23 matching an input with a Source
isSubType method example of, 15, 16
example of, 4 rules governing, 13
materialized views
for a cube, 16
J for OLAP metadata, 28
Java archive (JAR) files, required, A-1 including hierarchy lineage, 16
Java Development Kit, version required, A-1 populating attribute hierarchy lineage for, 26
JDBC prefixes for attribute columns in, 28
creating connections, 2 MDM metadata model
libraries required, A-1 description, 2
join method mdm package
description, 6, 2 description, 3
examples of, 2 MdmAttribute objects
full signature, 6 creating, 7
rules governing matching an input with a description, 22
Source, 13 example of the values of, 23
joined parameter inputs of, 12
of a join method, 6 MdmBaseAttribute class
joinHidden method description, 24
example of, 11, 20, 21 MdmBaseAttribute objects
creating, 24, 7
mapping, 25, 8
L mapping, example of, 3
lag method MdmBaseMeasure objects
example of, 21 creating, 9
languages description, 17
specifying for an attribute, 25 MdmCube class
leaves of a hierarchy description, 15
defined, 21 MdmCube objects
legacy metadata objects associations, 16
namespaces for, 5 corresponding to a fact table or view, 16
supporting, 4 example of creating, 8
level-based hierarchy, 21 MdmDatabaseSchema objects
levels creating, 2
as dimensional data objects, 4 definition, 13
creating, 4 owner of top-level objects, 8
MdmDimensionLevel objects, 20 MdmDerivedAttribute class
lineage description, 28
populating attribute hierarchy values, 26 MdmDerivedMeasure objects
list Source objects description, 18
definition, 2 MdmDescription objects, 6
example of creating, 6 associations, 6
local dimension member values, 6 MdmDescriptionType objects
associations, 6
creating, 6