RPAS Extension Development Guide - Volume 1 DB Server
RPAS Extension Development Guide - Volume 1 DB Server
Application Server
Developer Skill-Sets
An RPAS extensions developer must have sound knowledge of the C++ programming
language in its modern, standardized form. In particular, familiarity with the C++ Standard
Template Library (STL) is essential.
The developer should also have a working knowledge of the utilities mechanisms provided
by a POSIX-compliant command-line interface (CLI) environment to develop software. This
CLI is supplied by default in most UNIX-based operating systems, and it can be added to a
Windows-based environment.
Note: Oracle does not support any version of Solaris for the Intel
IA32 (x86) platform.
IBM AIX 5L
Oracle supports and develops on AIX 5L (version 5.3) and AIX 6 (version 6.1) for IBM’s
PowerPC-based platforms. Oracle cannot guarantee the behavior of RPAS extensions
development on any newer version of AIX.
Windows Platforms
Most Windows platforms do not have a POSIX-compliant CLI installed, but there are several
add-on products, including the downloadable Windows Services for UNIX package from
Microsoft (which can provide this feature). However, Oracle can only guarantee the behavior
of developing RPAS extensions using the Korn shell environment supplied with the MKS
Toolkit from Mortice Kern Systems (www.MKS.com).
OLDPATH=%PATH%
OLDLIB=%LIB%
rem Start over with a blank path, build it up just enough for RPAS work
set PATH=
set PATH=D:/MKS/mksnt
set PATH=%PATH%;D:/MKS/bin
set PATH=%PATH%;D:/dev-rpas/rpas/11/DeveloperUtilities/ExtractExports
set PATH=%PATH%;D:/dev-rpas/retek_labs/Applications/Version11.0/bin
set PATH=%PATH%;D:/dev-rpas/retek_labs/Applications/Version11.0/lib
set PATH=%PATH%;D:/dev-rpas/rpas/11/utils
set PATH=%PATH%;D:/Retek/RPAS12.0/RpasServer/bin
set PATH=%PATH%;D:/Retek/RPAS12.0/RpasServer/lib;D:/Retek/RPAS12.0/RpasServer/applib
set PATH=%PATH%;D:/Retek/RPAS12.0/ConfigTools/bin;D:/Retek/RPAS12.0/ConfigTools/lib
set PATH=%PATH%;C:/WINDOWS/system32
set PATH=%PATH%;C:/WINDOWS
set PATH=%PATH%;C:/WINDOWS/System32/Wbem
set PATH=D:/Retek/Acumate;%PATH%
set HOME=D:\MKS
D:\MKS\mksnt\sh.exe
C++ Compiler
This section describes suitable C++ Compilers.
UNIX Platforms
For the AIX, Solaris, and Linux platforms, Oracle uses and recommends g++, which is the
C++ compiler that is included with the open source-based GNU Compiler Collection (GCC,
http://GCC.GNU.org). Oracle uses specific versions of GCC depending on the platform, and
it will only support these specific versions. As newer versions of RPAS are released, Oracle
may opt (at its discretion) to upgrade the version of GCC required to develop extensions.
Oracle cannot guarantee the behavior of extensions developed with versions of GCC more
recent that those outlined below. Later versions may be incompatible with official RPAS
releases.
For the HPUX platform, Oracle uses and recommends the HP standard aCC C++ compiler.
Versions required for each platform are as follows:
Solaris 10 – GCC 4.2.3
AIX 5.3 – GCC 4.1.1
AIX 6.1 – GCC 4.3.3
Linux – GCC 4.1.2
HP-UX – aCC A.06.20
Windows Platforms
For Windows platforms, Oracle uses and recommends CL.EXE. This is the C++ compiler that
is included with Visual C++ .Net, which is an integrated development environment (IDE)
from Microsoft. Visual C++ is available as part of Visual Studio .Net 2003
http://msdn.microsoft.com/vstudio/Previous/2003/default.aspx.
Java Requirements
To make use of the Java Special Expression functionality, installation of a Java Developer Kit
(JDK) version 1.5 or later is required. The Java distribution must contain the jvm shared
library in order to allow RPAS to run the Java expression. For Windows distributions of Java,
this library should reside in the lib subdirectory of the Java distribution. On other platforms,
the location of the library may vary. Once the location of the jvm shared library is
determined, this location should be set as the value of the environment variable
RPAS_JAVA_VM_DIR. This location must be added to the library load path (for example,
PATH on Windows and SHLIB_PATH on HP-UX).
The Java Developer Kit contains the resources necessary to compile and package any
developed Java Expressions. However, developers are advised to make use of a Java IDE to
simplify the development process.
Obtain
The following describes how to obtain binaries and source for GCC.
Binaries
Although GNU Project does not distribute official binaries of their software products, several
third-party provide installable binary packages of GCC for various platforms. These
packages can be downloaded for free or at a nominal cost. Some of the more popular
vendors and distribution sites are listed at on this site:
http://GCC.GNU.org/install/binaries.html.
When obtaining the GCC binaries for your platform, see the operating system and GCC
version recommendations in the Summary of Basic Requirements section of this document. If
you are unable to find the version of GCC for your platform, you may need to install the
most recent version of GCC available for your platform to build the version that your
platform requires (see below).
Source
Oracle recommends that pre-built binaries of the GNU utilities be installed when possible. If
not possible, GCC must be built directly from the official GNU source code distribution.
GCC can be built from scratch, because it is an open source project; however, GCC requires a
C compiler to be installed and operable in order to build a bootstrapped version of GCC. The
C compiler can come from either another version of GCC or from a vendor-supplied
development package. Some C compilers included with certain operating system
distributions are based on pre-ANSI-standard notions of the C language. These types of
compilers are not sufficient for building the GCC bootstrap compiler.
Source “tarballs” (compressed file archives) of GCC are available directly from GNU or a
mirror archive. See http://GCC.GNU.org/releases.html for information.
Most source distribution sites make GCC available in two forms:
A giant tarball with every programming language supported by GCC.
Smaller, individual tarballs that represent each language component of GCC.
Oracle recommends downloading only the C (core) and C++ components to minimize the
amount of time and storage space required to build the compilers.
Install
The following describes how to install binaries and source for GCC.
Source
GCC includes a script used to configure settings that affect the way GCC will be built. The
script, named configure, uses a series of user-supplied switches and parameters to learn
about the target platform. See http://GCC.GNU.org/install/configure.html for more
information on using this script.
There are at least four main categories of build configuration switches:
Installation target location
With the --prefix parameter, users can change the default location target of the
installed GCC files. Or each type of file directory (bin, include, lib) can be
individually specified.
Linker and assembler
For platforms that require a GNU-specific assembler and/or linker (see Summary of
Basic Requirements), the --with-gnu-as and --with-gnu-ld switches are required.
However, if a GNU utility is specified in the configuration, but the compiler finds a
non-GNU version of that utility, the compiler will get confused. If desired, the --
with-as and --with-ld parameters can be used to lock in a particular variant of the
appropriate utility.
Specific programming languages
When building from the GCC “full distribution” tarball, several languages in
addition to C and C++ (such as Java, Fortran, and Ada) also will be built by default.
To avoid building these extra languages, the configuration script provides the --
enable-languages parameter for specifying only necessary language compilers. For
example, to build only C and C++,
--enable-languages=c,c++ should be specified.
Platform-specific switches
For AIX, these additional configuration parameters should be specified:
-enable-shared --enable-threads=posix --disable-nls
For HP-UX, the --enable-shared configuration switch also should be specified.
Use
Once GCC is properly obtained and installed, the g++ compiler should be ready. Most
development interactions will occur using the gmake command, but ensure that g++ is
operable. To detect problems, enter the g++ -v command to retrieve version and
configuration information on the GNU C++ compiler. Log out of the current command shell,
and log back in. This ensures that the configuration changes to the executable and that the
library paths will take effect.
Obtain
Visual C++ .NET 2003 and Visual Studio .NET 2003 (which includes Visual C++ .NET 2003)
are available from a variety of third-party software vendors. Contact the vendor for more
information. Oracle cannot guarantee the behavior of RPAS extensions development using
Visual Studio 6 or Visual Studio .NET 2002 or 2005.
Install
The installation for Visual C++ is relatively straightforward. It is a Windows-based product,
so the installation procedure is menu-driven. The default installation settings in the various
menus are acceptable choices, but additional items can also be installed if desired.
Configure
After the Visual C++ installation is complete, ensure that the system variables (PATH,
INCLUDE, and LIB) have been properly updated. These variables may be examined in
either of the following:
The system settings panel, which is accessible in Settings->Control Panel->System-
>Advanced->Environment Variables
In the MKS shell as UNIX-style variables
Use
Because build process requires gmake, ensure the accessibility of the command-line
development utilities within an MKS Korn shell as follows:
1. Launch a Korn shell.
applib
This subdirectory contains standard and custom RPAS extension libraries. These shared
libraries are typically registered to an RPAS domain with a regtemplate or regfunction
command. However, some libraries are actually support libraries upon which the registered
libraries are directly dependent.
bin
This subdirectory contains all RPAS-related executable binaries and shell scripts, including
commands for creating, manipulating, and querying RPAS domains. This directory also
includes the two main RPAS server daemons (DomainDaemon and RpasDbServer).
domain
This subdirectory contains all of the “bootstrap” files necessary for creating an RPAS domain
from scratch. It includes the minimal set of necessary database files. It also includes several
fixed-width flat files that are used to initialize the core hierarchies, dimensions, positions,
and measures, as well as a set of localized messages.
devkit
This subdirectory contains RPAS Makefile system files and a subdirectory called “include,”
which is described below. The devkit directory also contains the examples subdirectory. This
subdirectory contains examples of extensions written using the Java expression framework.
include
This subdirectory contains the header files that are necessary for the development of RPAS
extensions. This directory has separate sub directories for each functional cluster of header
files. Oracle Retail recommends including only this directory (as opposed to each individual
subdirectory) in an extension Makefile. The headers may be accessed with the standard
C/C++ notation. For example:
#include <rpas/String.h>
The top-level include directory contains only one file, FlexLexer.h. This file is normally
included with flex, which is an open source-based lexical analyzer. Only the Parser.h header
in the rpas subdirectory includes FlexLexer.h, which should never be directly included in
RPAS extension code.
boost
This directory contains header files from Boost (www.Boost.org), which is an open source-
based set of extensions to the standard C++ libraries. Although Boost headers installed on
your development platform prior to the installation of RPAS may be used, Oracle Retail
supports only the usage of version 1.30.2. Specifically, Oracle cannot guarantee the behavior
of RPAS extensions built with Boost version 1.31 or higher. Because Oracle does not use or
distribute any Boost-related libraries, Oracle does not redistribute any of the Boost non-
header source files.
cppunit
This directory contains header files from CppUnit(http://sourceforge.net/projects/cppunit),
which is a C++ unit testing framework.
rpas
This directory contains header files that collectively provide the RPAS API. There are several
subdirectories within this directory as well.
rtkapp
This directory contains header files that provide the API for the DynamicTemplate class,
which is used to construct an RPAS workbook template from a configuration file.
lib
This subdirectory contains the RPAS library and the libraries it depends on, as well as,
including the Zlib compression library. The lib directory also contains the
oracleRPASUtils.jar library that provides the interfaces classes used by Java Expressions.
doc
This subdirectory contains the JavaDoc description of the classes that make up the Java
expression APIs for development of RPAS Java Expressions. The index file for the JavaDocs
for the oracleRpasUtils package is found within the java subdirectory of the doc directory.
Base Classes
String
The String class is perhaps the most used class in the RPAS API, because several methods of
the other RPAS classes expect String parameters. Its functionality is a superset of the C++
STL class std::string. For example, you can perform an “addition” operation on a String to
achieve string concatenation:
String s1(“This string”);
s1 += “ has been added to.”);
In addition to the normal comparison and substring extraction methods, a number of utility
methods for converting to and from other data types (such as int, double, and bool) are
provided. There is also a method that is specifically geared for filling in the parameters of a
locale-specific message label.
File
The File class encapsulates the lower-level, operating system-specific file descriptor handle,
which identifies a unique I/O session performed on a particular file or directory. Methods
for opening, closing, reading, writing, and erasing the file are provided and typically
encapsulate the operating system’s file descriptor API. However, File goes a few steps
further by providing methods that can list, or even copy, the contents of a file directory. File
also provides several methods to lock, unlock, and check the lock status of the associated file.
FilePath
FilePath is typically associated with File, but it is also used by several other classes. The
FilePath class encapsulates the fully-qualified name path for a file residing in a file system
employing a hierarchical directory structure. This type of structure is indigenous in UNIX- or
Windows-based operating environments.
A key advantage of the FilePath class is the automatic handling of the character sequence for
separating directory hierarchies (for example, / in UNIX-style environments, and \ in DOS
and Windows). The FilePath class can also “flatten” a path where shorthand references to a
current or parent directory are taken out to create a fully-qualified filename. Methods are
provided to manipulate the filename extension (for instance, “.txt”) and query a file path’s
directory and base filename.
ArgReader
The ArgReader class encapsulates the contextual list of arguments that were specified as part
of the invocation of a new RPAS process. For example, when
loadMeasure –d /home/rpas/myDomain –meas TwPStrCnt
is invoked, the loadMeasure process can create an ArgReader object that will hold the –d and
–meas parameters and allow easier access to the arguments that are referenced by the
traditional C-style argc/argv method. The ArgReader class can be used to stipulate the valid
parameters and switches (which are parameterless directives such as –noWarn) and dictate
which of those must be specified on the command line.
Though much of the argument processing logic (aside from that specified above) must be
performed by the creator of the ArgReader object, ArgReader automatically handles one type
of argument: the –loglevel class, which specifies the level of granularity for statements
generated through the Logger class (see below).
InvalidArgException
This exception will be thrown if the ArgReader object notices a parameter or switch in the
process’s parameter list that was not previously registered with the ArgReader object.
DateTimeComponents
This companion class to DateTime allows a developer to access (in a read-only and a read-
write fashion) the individual date and time elements of a DateTime timestamp. The levels
that can be accessed are year, month, day within the month, hour, minute, second, and
millisecond. A DateTime object can generate a DateTimeComponents object, and a
DateTimeComponents object can generate a DateTime object.
DateTimeFormat
The DateTimeFormat class (also a companion class to the DateTime class) formats a
DateTime timestamp and generates a character String value suitable for display to users and
for parsing by back-office batch processes. A suitable default format is provided; however,
developers can provide alternate formats to further refine the display ability of the
timestamp.
The timestamp display format is specified as a String object containing one or more of the
following placeholder tokens into which the appropriate timestamp values are substituted.
All values are formatted as two digits unless otherwise specified:
%Y – Four-digit Gregorian calendar year
%y – Two least-significant digits of year (for example, 04 is 2004)
%m – Month (or example, 01 is January)
%B – Varying-length full name of the month
%h – Three-character abbreviation of the month name
%d – Day of the month (or example, 01 is the first day of the month)
%H – Hour of the day (or example, 22 represents 10 PM)
%M – Minutes past the hour
%S – Seconds past the current minute
%s – Three-digit milliseconds past the current second
%% – Treated as a single-character percent literal
Logger
The Logger class (the Logger singleton object accessor rpas::logger()) can be used to generate
non-interactive, “back-channel” feedback regarding the behavior and performance of one or
more sections of C++ code. The logger() accessor behaves like an output stream, so it can
initiate a chain of stream insertion operations. For example,
logger() << debug << “The query returned” << i
<< endl;
RpasVersionMacros.h header
Various C-preprocessor-style macros are defined in the header file RpasVersionMacros.h so
that libraries and binary executables will have a foolproof mechanism for self-discovering
the version of RPAS for which they were built. There are two constructors for the
RpasVersion object. One is designed for the RPAS Library and does not include the
parameter shown below that contains “Additional” in the name. For libraries and code
written outside of RPAS that requires additional version information, this additional
information can be provided as shown in the example. The parameters to the constructor
that have “Additional” in their name provide the version information for the library or code
written outside of RPAS while the other parameters provide the RPAS library version that
this library or code was complied against.
To include this information into a custom extension library, a C++ source file with the
following contents must be included. The developer can substitute more appropriate text in
the “name of your library here” space:
#include "rpas/RpasVersion.h"
namespace
{
static rpas::RpasVersion
rpasVersion
(
"name of your library here",
ADDITIONAL_VERSION_MAJOR,
ADDITIONAL_VERSION_REVISION,
ADDITIONAL_VERSION_MODTIME,
To display the version information in a binary, the code would look similar to this:
if (args["version"] == ArgReader::TRUE_ARG())
{
RpasVersion rpasVersion
(
"name of your binary here",
ADDITIONAL_VERSION_MAJOR,
ADDITIONAL_VERSION_REVISION,
ADDITIONAL_VERSION_MODTIME,
ADDITIONAL_VERSION_BUILD_DATE,
RPAS_VERSION_MAJOR,
RPAS_VERSION_REVISION,
RPAS_VERSION_MODTIME,
RPAS_VERSION_BUILD_DATE,
RPAS_VERSION_CLIENT_API,
RPAS_VERSION_MSPL_API,
RPAS_VERSION_COM_MSG_FORMAT
);
return 0;
}
Developing an Extension
Before it can be used, an extension must be:
1. Written
2. Compiled
3. Linked
4. Installed
5. Registered
Writing the extension requires writing C++ code and deciding what type of extension is
required: function or special expression. Compilation, linking, and installation can be done
all at once using gmake. This is covered in the next section.
Registration is done using the regfunction utility provided in the RPAS_HOME/bin folder.
Directory Structure
A Makefile must be stored in a directory before it is set up. Oracle Retail recommends
placing each extension to be developed in its own development directory. If multiple
extensions are being developed for a particular solution, each of these directories could
reside in a parent directory where a centralized Makefile can recursively invoke the Makefile
of each extension’s subdirectory.
Oracle Retail also recommends creating two subdirectories within each extension’s
development directory as follows:
One containing the source code for the extension
One containing the source code for any unit tests associated with the extension
The advantage to this method is that the same Makefile can manage the builds for both of
these subdirectory types.
Consider the following sample directory specifications:
/home/janedoe/RPASSolution
/home/janedoe/RPASSolution/Extension1
/home/janedoe/RPASSolution/Extension1/src
/home/janedoe/RPASSolution/Extension1/unittest
/home/janedoe/RPASSolution/Extension2
/home/janedoe/RPASSolution/Extension2/src
/home/janedoe/RPASSolution/Extension2/unittest
Environment Variables
The RPAS_HOME variable indicates the fully qualified directory location of the particular
distribution of RPAS on the system where extensions are to be developed. This should
already be set if RPAS was configured for use in your UNIX account or Windows command
shell.
Makefile Variables
The following Makefile variables are used by the RPAS Makefile system to ease the process
of developing RPAS extensions. See Sample Makefile for the proper assignment syntax of
these variables.
TARGET
This variable can be set to one of two possible values:
binary for executable images
shared for shareable intermediate object libraries
TARGET_BINARY
When the TARGET variable is set to binary, this variable should contain the base filename of
the executable image target to be created.
BASE_TARGET_NAME, TARGET_SHARED
When the TARGET variable is set to shared, these variables are used to indicate the filename
of the shared object library target to be created. The BASE_TARGET_NAME contains the
name of the library without any extension; TARGET_SHARED should contain
BASE_TARGET_NAME plus the $(SHARED_LIB_SUFFIX) variable to indicate the filename
extension for the current platform (.dll for Windows, .so for AIX and Solaris, .sl for HPUX).
RPAS recommends use of the $(LIB_PREFIX_NEVERD) variable to indicate the prefix for the
filename. Doing so yields “lib” for the Unix platforms and is empty for Windows. The
NEVERD indicates you do not wish to have a “d” prefix in the filename, even when building
a debug version of the code. NEVERD allows a domain with your library registered in it to
work with either a debug or a release build of the code. The string in the middle
(MyTemplateLib in the example above) represents the unique, developer-chosen part of the
library name.
Using the information in the Makefile (see Sample Makefile), gmake will determine that the
library name is libMyTemplateLib.so on AIX and MyTemplateLib.dll on Windows.
INSTALL_SHARED_LIB_DIR
This variable should contain the directory location where a target shared object library file is
to be installed. For most development situations, this should be set to
$(RPAS_HOME)/applib.
The system administrator for the development platform should configure this directory to
allow developers to insert extension libraries, but not to overwrite the other libraries in the
directory. If this is not possible, a private copy of the RPAS distribution must be created for
this purpose.
INCDIR
This variable should contain a space-separated list of include directives where each directive
is in this form: -includeDirectory
where includeDirectory represents the location of a directory that the C++ compiler should
use for looking for header files. The RPAS Makefile system will automatically include the
directories for the standard RPAS includes, so only application-specific directories should be
added here.
OBJS
This variable should contain a space-separated list of intermediate object filenames. The
filenames may be specified relative to the directory location of the Makefile. The RPAS
Makefile system uses this variable for determining the source-to-object and the object-to-
target dependencies.
DEVKIT
For nearly all RPAS application and extension library development, the DEVKIT variable
should be set to True. This indicates to the RPAS Makefile system that your RPAS include
files, and shared libraries are coming from an RPAS_HOME release build (rather than from a
checked-out copy of the RPAS source tree).
USES_CORE
There are several variables for selecting the level of RPAS library support that your library or
application requires. For nearly all application and library developers, USES_CORE is the
correct level. It links your code against the RPAS support libraries for system/platform
dependencies (RpasBase), the RPAS database system (RpasArray), and domain, measure,
and workbook capabilities (RpasCore).
If you want to build a very simple utility that requires only the RPAS system/platform
support, you may specify USES_BASE. If your application accesses RPAS databases and
arrays but does not need domain- or measure-level access, you may specify USES_ARRAY.
The USES level is cumulative, so if you specify USES_CORE, you get the BASE and ARRAY
support automatically. There is no need to specify all three.
Makefile.arch
Makefile.arch is an include file that heuristically discovers the platform on which gmake is
being invoked. It sets certain internal critical variables accordingly. This file should always
be included after the setting of RPAS_HOME, and the TARGET* series of variables.
However, it should also be included before the setting of INSTALL_SHARED_LIB_DIR,
INCDIR, and OBJS.
Makefile.rules
Makefile.rules is an include file generates the basic dependency rules. It supplies the gmake
invocation with its eventual targets. It should always be included at the end of a Makefile.
Note that both Makefile.arch and Makefile.rules (and other files subsequently included by
them) will be located in the “devkit” directory of any official RPAS release. You may assume
that they are located at $RPAS_HOME/devkit/Makefile.arch and
$RPAS_HOME/devkit/Makefile.rules.
Sample Makefile
The following sample represents the contents of a Makefile for a typical extension
development situation, where a shared library is being developed. See Makefile Variables for
explanations of the variables shown in this example.
gmake install
This is the same as above, except that it copies the library or executable to the default
installation target directory and makes permissions adjustments as needed. This type of
build is suitable for problem resolution and normal testing.
gmake clean
This removes any intermediate and final products of the build process, which allows for a
complete build of extensions and unit tests from scratch.
Standard Functions
See the Appendix C of the Oracle Retail Predictive Application Server Configuration Tools User
Guide (RPAS 12 Rule Functions Reference Guide) for a description of standard functions.
Custom Functionality
RPAS supports four techniques for implementing custom functions and procedures. This
section contains a brief summary of each technique.
results.at(i) = lastNonErrorValue;
}
}
virtual SemanticInformation::EvaluationModeType
evaluationMode() const
{
return SemanticInformation::VECTOR;
}
};
This function calls the AssignEvalNodeFactory function getEvalNode using the pointer
stored in the ParseNode from the AssignParseNode’s chaining constructor. The factory then
calls getEvalNode on its children (VarParseNode A and BinaryOpParseNode +), which use
their factories and recursive invocation to build the eval tree.
All nodes in the eval tree are descendants of the EvalNode class, which implements two
principle recursive tree functions: eval and evalNA. Each node allocates a buffer of strongly
typed space to be used to hold the value of the calculation at that node.
Each node should be able to run in Single Cell mode (calculates one cell at a time) or Vector
mode (calculates a vector of cells at a time). Evaluation takes place using similar recursive
techniques. Both algorithms descend the tree traveling to the leaves of the tree (which are
either constants or VarEvalNodes), setting those EvalNode buffers to the correct values.
Interface Description
Interface Description
In both cases, the ParseNode will have the label attribute set to the value before the colon. If
no attribute is set, a numeric string corresponding to the position will be returned as the
label.
Example
The following example illustrates how a custom Java expression should be invoked when
writing rules, given that destMeas, srcMeas, and cellCountMeas are measures in the domain.
Note that because of the use of argument labels, the order of arguments to javaexpression is
not important. However, it is still necessary to differentiate between left side and right side
measures.
destMeasure:destMeas <- javaexpression(class:”copyMeasure”, srcMeasure:srcMeas,
popMeasure:cellCountMeas)
The class for copyMeasure could be implemented as follows:
if (!map.containsKey("popMeasure"))
{
invalidArg("Missing label 'popMeasure'");
}
if (srcMeasure.isLhs())
{
invalidArg("srcMeasure is not on right handle side");
}
if (dstMeasure.isRhs())
{
invalidArg("dstMeasure is not on left handle side");
}
if (srcMeasure.getName().equalsIgnoreCase(dstMeasure.getName()))
{
invalidArg("srcMeasure and dstMeasure must be two different measures");
}
if (0 != srcType.compareTo(dstType))
{
invalidArg("source and destination measure must be of the same type");
}
if (!type.isInteger())
{
invalidArg("popMeasure must be integer scalar measure");
}
if (!srcIntersection.isConforming(dstIntersection))
{
invalidArg("src and dst intersections are not conforming");
}
}
timer.start();
if (!inc)
{
dstData.fill(srcData.getNaValue());
}
if (map.containsKey("useObject"))
{
srcType = MeasureType.String;
}
while (srcIter.next())
{
double cell = srcIter.getCellAsDouble();
while (subIter.next())
{
popCount++;
accessor.setCellToDouble(cell);
}
}
}
else
{
CellAccessor accessor = dstData.getCellAccessor(srcIter, inc);
while (srcIter.next())
{
popCount++;
accessor.setCellToDouble(srcIter.getCellAsDouble());
}
}
}
else if (srcType.isBoolean())
{
// Boolean case
if (dstData.needsSubCubeIterator(srcIter))
{
IterativeAccessor subIter = dstData.getSubCubeIterator(srcIter);
CellAccessor accessor = dstData.getCellAccessor(subIter, inc);
while (srcIter.next())
{
boolean cell = srcIter.getCellAsBoolean();
while (subIter.next())
accessor.setCellToBoolean(cell);
}
}
}
else
{
CellAccessor accessor = dstData.getCellAccessor(srcIter, inc);
while (srcIter.next())
{
popCount++;
accessor.setCellToBoolean(srcIter.getCellAsBoolean());
}
}
}
else
{
// Object case.
if (dstData.needsSubCubeIterator(srcIter))
{
IterativeAccessor subIter = dstData.getSubCubeIterator(srcIter);
CellAccessor accessor = dstData.getCellAccessor(subIter, inc);
while (srcIter.next())
{
Object cell = srcIter.getCell();
while (subIter.next())
{
popCount++;
accessor.setCell(cell);
}
}
}
else
{
CellAccessor accessor = dstData.getCellAccessor(srcIter, inc);
while (srcIter.next())
{
popCount++;
accessor.setCell(srcIter.getCell());
}
}
}
popMeasure.setCellToInteger(popCount);
timer.stop();
timer.logElapseTime("CopyMeasure");
}
type Base types: int, real, string, date, Boolean. The Not updateable
numeric representations of these types are 1, 2,
3, 4, and 6 respectively.
Note: This is a required property for adding a
measure.
navalue Suggested value for unpopulated (na) cells. Not updateable
Defaults according to type. Initially, the base
array of a measure is defined with this naval.
This is subject to change to optimize the
compression factor.
baseint Base intersection for measure. Concatenation of Not updateable
all dimension names (4 characters, suffixed by
“_” as necessary). Dimensions are ordered
according to the hierarchy to which they
belong. In [Measure]SFX array, baseint is
prefixed by I (simply I for scalar measures).
Note: This is a required property for adding a
measure.
defagg Default aggregation method. See Rule Updateable
Functions document for master list.
Note: Changes to defagg will only be reflected
in new or rebuilt workbooks.
defspread Default spread method. Updateable
Note: Changes to defspread will only be
reflected in new or rebuilt workbooks.
allowedaggs Permitted aggregation methods. Updateable
Syntax is MAX MIN TOTAL.
Notes
Virtual Measures
In RPAS, measures such as Opening Stock (OS), Begin of Period (BOP), End of Period (EOP),
and Closing stock (CS), have a predefined relationship that is always True for predictive
applications. Assuming that data is stored from a starting point to an ending point, this
relationship is characterized as follows:
OS is equal to the first element of BOP across the time dimension.
The relationship also states that nth + 1 element of BOP is equal to the nth element of
EOP across the time dimension.
The relationship also states that the last element of EOP across the time dimension is
equal to CS.
To support this predefined relationship between OS, BOP, EOP, and CS, the RPAS 11 client
supports the concept of virtual measures. Virtual measures are defined by a set of rules that
allow the client to calculate the data for virtual measures from stored measures. This set of
rules is created to implement the relationship between OS, BOP, EOP, and CS. For any
implementation, both OS and EOP are stored measures with BOP and CS virtual measures,
or BOP and CS are stored measures with EOP and OS virtual measures.
Editing
If a virtual measure is edited, the edit will be translated to the corresponding cell address of
the stored measure that is related to the virtual measure. The calculation engine cannot
handle virtual measures being changed.
Protection
When the read/write state of a virtual measure is calculated, the cell address of the stored
measure corresponding to the cell address of the virtual measure is used.
Deferred Calculation
When the deferred calculation queue is applied to a visible grid, all stored measures that
have a cell edit that corresponds to a visible virtual measure address are displayed in the
visible cell of the virtual measure.
Token Measures
Example:
@a = @b + c / d , where a and b are token measures.
Assumptions
Token measures are string-type scalar measures. They cannot appear on the right-
hand side or the left-hand side of expressions without the indirection operator @.
Token measures cannot be aggregated or calculated. An expression including non-
indirected token measures (without @ prefix) will not be valid. Expression parser
will not validate such expressions.
Each token measure must be initialized with the name of a valid non-token measure.
This must be done before running processes that create tokenized expressions.
Examples of such processes are alert-manager and domain configuration processes.
RPAS provides a C++ api and a utility called regTokenMeasure for assigning values
to token measures. This api will register non-existing token measures and populate
them with the provided values.
Token measures do not need to be registered by RPAS applications. Registration of
these measures is done internally by regTokenMeasure utility. Refer to the domain
utility regTokenMeasure.
Measure Attributes
Several RPAS applications require the ability to register sets of mostly identical measures
that slightly vary from each other based on application specific attributes. RPAS supports
this ability by introducing the concept of “measure attribute” (that is, single level roll-ups
along data hierarchy above the measure dimension). Measure attributes are valid dimensions
in the domain and their name should not consist of more than four characters. The interfaces
for dynamic registration of measure attributes and using a set of attributes to allow existence
testing, creation, and retrieval of measures are defined.
Function Description
Function Description
A position may be added for an attribute multiple times, although it will only appear once in
the dimension position list for the attribute. With the exception of the lastMeasName
measure (if it is not empty string), any attempt to remove an attribute position that is in use
as a roll-up for a measure will throw a MeasureAttributeException exception.
Function Description
Function Description
Function Description
All of these functions could issue a MeasureAttributeException to indicate a bad map with
the details manifested in the exception message.
For an existing measure, the following functions of Measure class can be used to set and
retrieve measure attribute information on the basis that measure attributes and positions
were properly registered and added. Otherwise, MeasureAttributeException exception will
be thrown.
Function Description
Function Description
Workbook Templates
The Dynamic Template Library takes care of the static workbooks (where the non-
hierarchical content of the displayed workbook does not depend on the wizard selections)
built with standard two-tree wizard pages (simple ranging down of the hierarchies in the
workbook). It also takes care of the display aspect of the custom wizards. To minimize the
coding effort, custom workbook templates should be built on the functionality defined by the
Dynamic Template Library.
The Dynamic Template Library was developed as a configuration aid for deployment of
workbooks. It uses configuration files (flat text files outputted from the Configuration tools)
and converts them into the workbook templates. See Appendix: Configuration Repository for
the layout of such configuration files.
1 Wizard Page
Win Info Widget Info
0..*
0..* 0..*
Contains
Template Registration Factory Template Factory -Creates Dynamic Template Dynamic Wizard
1 1
The Template Registration Factory registers and creates templates. It searches the
repos/templates (see Appendix: Configuration Repository) directory for tmpl.cfg files. Each
tmpl.cfg is an individual workbook template residing in the <workbook template group
name>/<workbook template name>/tmpl.cfg. All configuration files are loaded at once
when the client establishes connection with the domain.
Template Factory
The Template Factory parses all individual tmpl.cfg files and builds individual info objects
and relationships within these objects. It creates a String to String Vector map to contain all
of the attributes that are in the cfg files and passes it to the constructor of the appropriate
BaseInfo derived class.
DynamicTemplate
This template converts the parsed information objects into RPAS objects and implements the
RPAS workbook template with them. It is derived from the Workbook Template Class.
Dynamic Wizard
This class is derived from the RPAS WizardPage class and is responsible for converting the
parsed WizardInfo into WizardPage object and the WidgetInfo objects into proper RPAS
controls. It does not contain any processing logic for the controls. It is the derived custom
dynamic wizard’s responsibility to define the processing of these custom wizards.
CustomTemplateRegistrationFactory
Typically, it inherits all of its functionality from its baseclass TemplateRegistrationFactory
except for two methods: getTemplateFactory and getTemplateFilePath. The following is a
sampleCustomTemplateRegistrationFactory.
CustomTemplateRegistrationFactory class
class CustomTemplateRegistrationFactory
: public rtkapp::cnfg::TemplateRegistrationFactory
{
TemplateRegistrationFactory::TemplateFactoryCPtr
getTemplateFactory() const
{
return TemplateFactoryCPtr( new CustomTemplateFactory() );
}
FilePath getTemplateFilePath() const
{
FilePath filePath = DomainState::instance().pathToDomain();
filePath.addSub( "repos" );
filePath.addSub( "customtemplates" );
return filePath;
}
}
// Constructor
CustomDynamicTemplate(const TemplateInfoCPtr& cpTemplateInfo);
// Destructor
virtual ~CustomDynamicTemplate();
WizardFinish* finishWizard();
protected:
// Overload to change the behavior once the workbook is built but before it is
displayed
virtual void postWorkbookBuild(Workbook& workBook);
Template Configuration
The tables in this section describe object types and attributes.
File Format
Each configuration file represents one template. The template configuration file format is as
follows:
Template configuration file format
<object type> <name> = {
<attribute> = <value>…;
<attribute> = <value>…;
<attribute> = <value>…;
};
Object: Group
Attribute Type Required or Optional Description
Label String Required Label displayed to the user on the group tab.
Object: Template
Attribute Type Required or Optional Description
PreRangeMask Identifier Optional The name of the measure to be used for pre-
range masking within the wizards of the
template.
Label String Optional The label displayed to the user in the group
listbox.
If missing or empty, it defaults to the name.
LoadRule String Optional The name of the existing rule group in the
domain to use to load data into measures.
CalcRule String Optional The name of the existing rule group in the
domain to use to calculate data.
CommitRule String Optional The name of the existing rule group in the
domain to use to commit data.
Object: Sheet
Attribute Type Required or Optional Description
Object: Window
Attribute Type Required or Optional Description
Object: HierMod
Attribute Type Required or Optional Description
Object: PositionQuery
Attribute Type Required or Optional Description
Object: DynamicHier
Attribute Type Required or Description
Optional
LabelMeasure Identifier Required The name of the label measure for the Dynamic Hier.
Measure Identifier Required The name of the measure for the Dynamic Hier.
MeasureHier Identifier Required The name of the measure hierarchy for the Dynamic
Hier.
MeasureDim Identifier Required The name of the measure dimension for the Dynamic
Hier.
Hier Identifier Required The name of the hierarchy for the Dynamic Hier.
Dim Identifier Required The name of the dimension for the Dynamic Hier.
ModifiedDim Identifier Required The name of the dimension modified by the
Dynamic Hier.
Object: Axis
Attribute Type Required or Optional Description
Object: Tab
Attribute Type Required or Optional Description
Object: Measure
Attribute Type Required or Description
Optional
Object: Wizard
Attribute Type Required or Description
Optional
Object: Widget
Attribute Type Required or Description
Optional
Object: Menu
Attribute Type Required or Description
Optional
Object: MenuItem
Attribute Type Required or Description
Optional
Object: Logger
Attribute Type Required or Description
Optional
Level String Required The level in which to set the logger object.
This is useful for debugging.
Valid values are All, Profile, Debug, Information,
Warning, and Error.
axis z2 = {
hier = LOC;
dim = “str”;
level = 1;
};
Worldwide Inquiries:
Phone: +1.650.506.7000
Fax: +1.650.506.7200
oracle.com