SlideShare a Scribd company logo
Report Engine Java Developer Guide




                    BusinessObjects Enterprise XI R2

                                 Windows and UNIX
Copyright      If you find any problems with this documentation, please report them to Business Objects
               S.A. in writing at documentation@businessobjects.com.
               Copyright © Business Objects S.A. 2004. All rights reserved.

Trademarks     Business Objects, the Business Objects logo, Crystal Reports, and Crystal Enterprise are
               trademarks or registered trademarks of Business Objects SA or its affiliated companies in the
               United States and other countries. All other names mentioned herein may be trademarks of
               their respective owners.

Patents        Business Objects owns the following U.S. patents, which may cover products that are offered
               and sold by Business Objects: 5,555,403, 6,247,008 B1, 6,578,027 B2, 6,490,593 and
               6,289,352.

Third-party    Business Objects products in this release may contain redistributions of software licensed
contributors   from third-party contributors. Some of these individual components may also be available
               under alternative licenses. A partial listing of third-party contributors that have requested or
               permitted acknowledgments, as well as required notices, can be found at:
               http://www.businessobjects.com/thirdparty
Contents
Chapter 1   Introduction                                                                                                 7

Chapter 2   Introduction to ReportEngine SDK                                                                             9
            Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
            Packages for customizing BusinessObjects Enterprise XI R2 . . . . . . . . . . 10
            Migrating to BusinessObjects XI R2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
            A typical ReportEngine SDK application . . . . . . . . . . . . . . . . . . . . . . . . . . 11
            Installing ReportEngine SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

Chapter 3   Application Essentials                                                                                     15
            Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
            “Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
            BusinessObjects Enterprise sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
            Implementing “Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
            User preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
            Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
            Reporting essentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Chapter 4   Document Management                                                                                        33
            Document types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
            Document state: storage tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
            Organizing documents in categories and folders . . . . . . . . . . . . . . . . . . . . 38
            Working with documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
            Document properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Chapter 5   Viewing Reports                                                                                            59
            Viewing reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
            Handling prompts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
            Displaying a report map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74




                                               Developing with Web Intelligence Report Engine SDK 3
Chapter 6   Drilling in Web Intelligence Reports                                                                      77



             Introduction to drilling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
             Drilling in reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

 Chapter 7   Building and Editing Data Providers                                                                       89
             Data providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
             Building a data provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
             Executing queries and retrieving the data . . . . . . . . . . . . . . . . . . . . . . . . 100

 Chapter 8   Formatting Reports                                                                                      101
             Creating and editing the document structure . . . . . . . . . . . . . . . . . . . . . . 102
             Creating and editing cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
             Page layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

Appendix A   Working with Recordsets                                                                                 117
             Anatomy of a recordset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

Appendix B   Business Objects Information Resources                                                                  121
             Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
             Customer support, consulting and training . . . . . . . . . . . . . . . . . . . . . . . . 123
             Useful addresses at a glance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Appendix C   Logging with ReportEngine SDK Overview                                                                  127
             Logging Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
             Activating logging by editing the configuration files . . . . . . . . . . . . . . . . . 129

Appendix D   Configuring ReportEngine using webi.properties                                                          135




                                                Developing with Web Intelligence Report Engine SDK 4
Examples
Referencing BusinessObjects Enterprise SDK 17
Instantiating the ISessionMgr class 18
HTML form for gathering a user’s login information 19
Establishing a session 20
Printing a user’s preferences 26
Setting a user’s report panel preference to Java 27
Adding a new preference to a user’s profile 29
Referencing the ReportEngine SDK 30
Instantiating a ReportEngine an IReportEngine object 31
Instantiating a ReportEngine objects depending on file type 31
Storage token life cycle 36
how to check that a user has the right to create categories 40
Traversing the category tree recursively 41
Retrieve a user’s Inbox and Favorites folder IDs 43
Creating a new folder or category 44
Moving and renaming categories or folders 45
Retrieve the properties for a category 45
Displaying a document list 47
Save a document 48
Scheduling a document 49
Retrieve the list of groups to which a user belongs 51
Sending a document to folders and categories 52
Send a document to the inbox of groups of users 54
Getting the name of a document 56
Adding a property to a document 57
Viewing all the reports in a Web Intelligence document 61
Viewing a report in a Web Intelligence document 62
Viewing a report in Microsoft Excel format 63
Handling a single, simple prompt 64


                                  Developing with Web Intelligence Report Engine SDK 5
Examples




Dynamically creating input names 66
Handling many, simple prompts 66
Displaying a simple list of values 68
Handling multivalued prompts 70
Handling multicolumn lists of values 70
Order of filling a hierarchy of nested prompts 72
Handling nested prompts 72
Refreshing a list of values containing nested prompts 73
Traversing the report map for a Web Intelligence document 74
Defining the query string parameters 82
Setting the drill path 84
Displaying the drilled report 86
Launching the Java Report Panel 94
Building a data provider 96
Creating a simple condition 98
Structure of a complex condition 99
Including a prompt in a condition 99
Creating a blank document 102
Creating a document structure 105
Creating an attachment 107
Editing the sections of a report 107
Building a report: adding expressions to axes 110
Accessing the values in a recordset 119




6 Developing with Web Intelligence Report Engine SDK
ReportEngine Developer Guide


Introduction




                               chapter
1   Introduction
    About this guide



    About this guide
                       This guide describes the processes and procedures for creating web
                       applications using BusinessObjects Enterprise SDK and the ReportEngine
                       SDK package.


    Who should read this guide
                       To use the BusinessObjects Enterprise SDK and ReportEngine SDKs you
                       need a working knowledge of the concepts of distributed computing systems,
                       HTTP server technology, and JSP development. You also need a basic
                       knowledge of the products in the BusinessObjects product line. Familiarity
                       with BusinessObjects Enterprise is assumed.


    Business Objects information resources
                       For more information and assistance, see “Business Objects Information
                       Resources” on page 121. This appendix describes the Business Objects
                       documentation, customer support, training, and consulting services, with links
                       to online resources.




    8 ReportEngine Developer Guide
ReportEngine Developer Guide


Introduction to
ReportEngine SDK




                               chapter
1   Introduction to ReportEngine SDK
    Overview



    Overview
                    ReportEngine SDK consists of a number of Java packages. Typically, every
                    application that uses these packages must implement the same kinds of
                    workflows.
                    This chapter briefly introduces ReportEngine SDK and the workflows a typical
                    application needs to implement.


    Packages for customizing BusinessObjects
    Enterprise XI R2
                    There are two packages for customizing BusinessObjects Enterprise:
                    •    BusinessObjects Enterprise SDK
                             The "platform package," provides platform functions of the Business
                             Objects servers, and document scheduling.
                    •    ReportEngine SDK
                            This package plugs into Business Objects Enterprise SDK. It
                            provides the functions of the Web Intelligence and Desktop
                            Intelligence Report Engines.



                         BusinessObjects Enterprise SDK            ReportEngine SDK

                        Crystal Enterprise Documents        Web Intelligence documents
                          View                               View
                          Refresh                            Refresh
                          Analyze                            Analyze
                                                             Create†
                                                             Format†
                        Platform functions
                          Manage sessions and users         Desktop Intelligence documents
                                                              View
                          Manage documents and categories
                                                              Refresh
                          List universes and folders
                          Schedule documents                  Analyze†
                                                            Metadata (universe)
                                                              Explore†

                        †Web   Intelligence Documents for REBean Only

                    BusinessObjects Enterprise SDK is called the platform package because it
                    exposes the platform functions of the Business Objects servers. ReportEngine
                    SDK exposes the functions of the Desktop Intelligence and Web Intelligence
                    Report Engines.



    10   ReportEngine Developer Guide
Introduction to ReportEngine SDK
                                                           Migrating to BusinessObjects XI R2    1
Migrating to BusinessObjects XI R2
             If you already have a business intelligence solution based on previous
             versions of ReportEngine SDK you might need to migrate your solution.
             Migration affects the following areas:
             •   referencing components of the BusinessObjects Enterprise platform
             •   controlling user sessions
             •   listing and navigating through folders and categories
             •   managing and viewing documents
             •   handling security commands
             •   using the various dictionaries
             •   deploying your application
             For more information on migration issues see the Migrating Business Objects
             Customized Applications to BusinessObjects XI R2 guide.


A typical ReportEngine SDK application
             Not all applications that use ReportEngine SDK have the same features, but
             all typically provide features for listing and viewing documents contained in the
             BusinessObjects Enterprise Central Management System (CMS). A more
             sophisticated application could also include features such as document
             creation and report formatting.

Application essentials
             Every application that uses ReportEngine SDK needs to perform common
             tasks such as importing the appropriate packages, and creating and managing
             the user’s BusinessObjects Enterprise session (login).
             Every application should also take user profiles into account and ensure that
             errors are handled properly. See “User rights for categories and folders” on
             page 39 and “User preferences” on page 24.

Document management
             Document management features include the ability to list the documents that
             the current user can view, and, depending on the user’s rights, allowing the
             user to browse and manage categories and folders used to organize the
             documents.
             Document management can also include features such as saving, and
             scheduling documents.


                                                          ReportEngine Developer Guide 11
1   Introduction to ReportEngine SDK
    A typical ReportEngine SDK application


    Viewing reports
                     An application that provides for viewing documents can display them using the
                     default DHTML format. It is easy to extend this to handle documents that
                     contain prompts, and to provide drilling functions. These extended functions
                     have to be handled when a document is refreshed.
                     How you provide viewing features depends on the type of document opened.
                     The report-viewing part of the application should include routines for viewing
                     reports in the following document types:
                     •   Web Intelligence (*.wid)
                     •   Crystal Reports documents
                     •   Desktop Intelligence (*.rep)
                     •   other document types, for example Adobe® Acrobat®, Microsoft® Excel
                         or XML format.
                     See “Viewing reports” on page 60 for a full listing of available formats.

    Creating documents: building and editing data providers
                     To give users the ability to create documents and generate their own reports,
                     you need to provide them with tools to build and edit data providers.
                     A data provider encapsulates information about an information source and the
                     query that defines the information retrieved. Creating a document essentially
                     means creating a data provider. You can use the same classes to provide
                     different features for editing a query, such as adding conditions and changing
                     the scope of analysis.

    Formatting documents
                     Formatting documents involves creating and positioning the elements of a
                     report (blocks, sections, and cells) in the appropriate report structure. Using
                     ReportEngine SDK you can build reports from scratch.
                     ReportEngine SDK includes classes for controlling report page decoration
                     (fonts, colors, headers, and footers) and layout.




    12   ReportEngine Developer Guide
Introduction to ReportEngine SDK
                                                       A typical ReportEngine SDK application       1
Open document workflow
            The following diagram shows the workflow for opening a document.
               Client                                                             Report Engine
               pages                                                                  SDK


                                              open a document
                                              check for prompts
                                fill prompts until there are none left unfilled


            fill document
                 toolbar                     get the report map
              fill report
                  map
                                  get the report in the requested format
            fill rendering
                  area


Refresh document workflow
            The following diagram shows the workflow for refreshing a document.
              Client                                                              Report Engine
              pages                                                                   SDK



                                        <open document workflow>

              update
             document
              toolbar
                                             refresh the report
                                                                                          refresh
                                              check for prompts
                                fill prompts until there are none left unfilled
                                              set the position
            fill document
                 toolbar
                                             get the report map
               fill report
                   map
            fill rendering        get the report in the requested format
                   area




                                                           ReportEngine Developer Guide 13
1   Introduction to ReportEngine SDK
    Installing ReportEngine SDK



    Installing ReportEngine SDK
    Installing Business Objects components
                    ReportEngine SDK components are added to the development machine
                    when BusinessObjects Enterprise XI R2 is installed on the system. To
                    develop a custom ReportEngine SDK application it is necessary to connect to
                    a running BusinessObjects Enterprise server, however, the development
                    environment does not have to be on the same machine as the
                    BusinessObjects Enterprise Server. Install ReportEngine SDK components
                    on a development machine by:
                    1.   Run BusinessObjects Enterprise XI R2 installer.
                    2.   Click Next on the BusinessObjects Enterprise XI R2 Installation Wizard
                         panel.
                    3.   Select the I accept the License Agreement button in the License
                         Agreement panel.
                    4.   Click Next.
                    5.   Select the Perform Server Installation
                    6.   Click Next.
                    7.   Enter your corporate information and keycode.
                    8.   Click Next.
                    9.   Specify the destination folder in the Destination folder text box.
                    10. Click Next.
                    11. Select the Custom button
                    12. Click Next.
                    13. Deselect all BusinessObjects Enterprise Features.
                    14. Enable the SDK products feature.
                         To install J2EE components only, deselect the SDK products feature and
                         install the Java features sub-component.
                    15. Click Next.
                    16. Click Next.
                    This installs all components necessary to develop custom Business Objects
                    applications; Java libraries are installed and registered correctly.




    14   ReportEngine Developer Guide
ReportEngine Developer Guide


Application Essentials




                               chapter
2   Application Essentials
    Overview



    Overview
                     Before providing viewing, reporting, and editing functions ReportEngine SDK
                     applications need to perform basic tasks, such as referencing the appropriate
                     package and creating a BusinessObjects Enterprise session for the user.
                     This chapter covers the essential concepts and tasks that all applications that
                     customize BusinessObjects Enterprise must use.


    “Hello World”
                     The simplest application you can write with BusinessObjects Enterprise SDK
                     is one that creates a BusinessObjects Enterprise session, that is, provides log
                     in and log out functions.
                     This is the basis for building much more sophisticated applications that
                     provide, for example, functions to list, view and create documents, and attach
                     them to hierarchical categories.



                                    get name and                               open a
                                    password          Name = “janderson”       session
                                    from user
                                                        Pass = “*******”




                                    close session                              display “Hello
                                                                               World” and a
                                                                               logout link




                     Table 2-1 Application for logging in and out of BusinessObjects Enterprise
                     This application gathers login details from the user, and sends the details to
                     another page which uses BusinessObjects Enterprise SDK to try to open a
                     BusinessObjects Enterprise session. If the session is successfully created, the
                     application displays a “Hello World” message and the option to log out. When




    16   ReportEngine Developer Guide
Application Essentials
                                                                           “Hello World”   2
            the user clicks the logout link, the application closes the user’s
            BusinessObjects Enterprise session with BusinessObjects Enterprise SDK
            and displays the first page again.
            Each page that uses BusinessObjects Enterprise SDK must:
            •   reference BusinessObjects Enterprise SDK
            •   create or reference an IEnterpriseSession object
            •   create or reference an IInfoStore object
            See “Implementing “Hello World”” on page 21 for code that implements this
            application.

Referencing BusinessObjects Enterprise SDK
            Referencing BusinessObjects Enterprise SDK gives your web application
            access to the BusinessObjects Enterprise platform functions exposed by the
            SDK.
            Note: You must use BusinessObjects Enterprise SDK prior to using
            ReportEngine SDK.
            To develop a Java application Business Objects recomments that you add all
            libraries found in the <BusinessObjectsHome>common3.5javalib into the
            WEB-INFlib directory of your JSP project.
            Referencing BusinessObjects Enterprise SDK
            To reference BusinessObjects Enterprise SDK, import the BusinessObjects
            Enterprise packages.
            Example: Referencing BusinessObjects Enterprise SDK
            To import BusinessObjects Enterprise SDK packages, add the following line
            to pages that use the packages.
            <% page import="com.crystaldecisions.sdk.framework.*,
               com.crystaldecisions.sdk.occa.infostore.*,
               com.crystaldecisions.sdk.occa.pluginmgr.*,
               com.crystaldecisions.sdk.plugin.*,
               com.crystaldecisions.sdk.plugin.desktop.server.*,
               com.crystaldecisions.sdk.occa.infostore.*,
               com.crystaldecisions.sdk.plugin.destination.smtp.*,
               com.crystaldecisions.sdk.plugin.destination.managed.*,
               com.crystaldecisions.sdk.exception.SDKException,
               com.crystaldecisions.sdk.occa.security.*,
               com.crystaldecisions.sdk.plugin.desktop.user.*,
               com.crystaldecisions.sdk.properties.*,
            com.businessobjects.sdk.plugin.desktop.webintelligence.CeWeb
               IntelligenceRightID"%>




                                                     ReportEngine Developer Guide 17
2   Application Essentials
    BusinessObjects Enterprise sessions


                    You need to include this line in every page that uses BusinessObjects
                    Enterprise SDK.

    Creating an new user session
                    In BusinessObjects Enterprise SDK the ISessionMgr lets a user to log in to
                    the BusinessObjects Enterprise server and create a session. Session
                    information is stored in the IEnterpriseSession object returned by this
                    method. Every session has a corresponding IEnterpriseSession object
                    which is used to access ReportEngine SDK.
                    Creating an ISessionMgr object
                    To create a user session for an application that uses BusinessObjects
                    Enterprise SDK, you must first instantiate a new ISessionMgr object.
                    Example: Instantiating the ISessionMgr class
                    ISessionMgr mySessionMgr =
                       CrystalEnterprise.getSessionMgr();



    BusinessObjects Enterprise sessions
                    Every user of InfoView requires a BusinessObjects Enterprise session before
                    entering and using the system. The BusinessObjects Enterprise session
                    represents the user’s current interaction with BusinessObjects Enterprise. A
                    user’s BusinessObjects Enterprise session provides access to the user’s
                    details, and objects that are subject to the rights of the user, for example, the
                    list of universes that the current user can use to create documents.
                    You must create a BusinessObjects Enterprise session for the user: it is the
                    key part of the log in and authentication process.
                    To create a session for a user:
                    1.   Get the user’s login information:
                         •   name
                         •   password
                         •   the Central Management System (CMS) the user wishes to log into
                         •   authentication type (Enterprise, LDAP, winAD)
                    2.   Establish a valid BusinessObjects Enterprise session for the user.




    18   ReportEngine Developer Guide
Application Essentials
                                                       BusinessObjects Enterprise sessions    2
Getting login information
             The simplest way to get a user’s login information is to use an HTML form into
             which the user enters a name and a password. When the user submits the
             form, the values for the fields are passed via the query string to a page that
             processes the values.
             Example: HTML form for gathering a user’s login information
             <FORM name="LoginForm" action="Login.jsp" method="POST">
                <TABLE><TR>
                    <TD>Name:</TD>
                    <TD><input name="Name"></TD>
                </TR>
                <TR>
                    <TD>Password:</TD>
                    <TD><input type="password" name="pass"></TD>
                </TR>
                <TR>
                    <TD>Central Management System:</TD>
                    <TD><input name="CMS"></TD>
                </TR>
                <TR>
                    <TD>Authentication:</TD>
                    <TD>
                       <select name='auth'>
                       <option value='secEnterprise'>Enterprise</option>
                       <option value='secLDAP'>LDAP</option>
                       <option value='secLDAP'>WinAD</option>
                       </select>
                    </TD>
                </TR>
                <TR>
                    <TD><input id=submit1 name=submit1
                           type=submit value="Login"></TD>
                </TR></TABLE>
             </FORM>
             When the user enters login information and clicks the Login button, the values
             for the fields are passed to Login.jsp in the query string parameters Name and
             Pass. Since the method attribute of the form is set to POST, these values will
             not be visible in the URL.



             Authentication
             The way you monitor passwords depends on how BusinessObjects Enterprise
             passwords have been set up by the BusinessObjects Enterprise system
             administrator.
             There are two settings available to the system administrator which you can use
             as the basis for the login procedure in your own application:



                                                        ReportEngine Developer Guide 19
2   Application Essentials
    BusinessObjects Enterprise sessions


                    •    Enterprise Mode
                         This mode requires from the user to submit a user name and password
                         which are unique to BusinessObjects Enterprise (and may be different
                         from their network name/password combination).
                    •    LDAP Mode
                         This mode requires the user to submit a user name and password which
                         are stored on a corporate LDAP server.
                    •    WinAD Mode
                         This mode requires the user to submit a user name and password which
                         are stored on a Windows Authentication Server.
                    For more information on authentication in Windows, see the BusinessObjects
                    Enterprise XI R2 Administrator’s Guide.

    Establishing a valid BusinessObjects Enterprise user’s session
                    To establish a valid BusinessObjects Enterprise user’s session:
                    1.   Try to create an IEnterpriseSession object for the user.
                    2.   If the IEnterpriseSession object is valid, store this object in the user’s
                         session attributes.
                    3.   Create an IInfoStore object and store in the user’s session attributes.
                    These steps are usually done together and are normally followed by
                    redirecting the user to an appropriate page: a welcome page or back to the
                    login page, depending on the validity of the session.
                    Example: Establishing a session
                    The following code fragment illustrates how to establish a BusinessObjects
                    Enterprise session.
                    ISessionMgr mySessionMgr =
                              CrystalEnterprise.getSessionMgr();
                    IEnterpriseSession eSession;
                    try {
                       eSession = mySessionMgr.logon(name, password, CMS, auth);
                       if (eSession != null){
                           session.setAttribute("EnterpriseSession",
                                  enterpriseSession);
                    IInfoStore iStore = (IInfoStore)
                                  enterpriseSession.getService("InfoStore");
                           session.setAttribute("InfoStore", iStore);
                    } catch (SDKException sdkEx){
                       ;
                    }




    20   ReportEngine Developer Guide
Application Essentials
                                                                  Implementing “Hello World”    2
Retrieving a BusinessObjects Enterprise session
             Once you have established a valid BusinessObjects Enterprise session for the
             user, you can retrieve it from the user’s session attributes.

Closing a BusinessObjects Enterprise session
             To close a session, that is, log a user out of BusinessObjects Enterprise, use
             IEnterpriseSession.logoff.
             Closing a session is important:
             •   It frees the resources held by the user’s BusinessObjects Enterprise
                 session.
             •   It forces other users to start their own sessions rather than just taking
                 over an existing session.
             Note: See “logout.jsp” on page 24 for an example of how to close a
             BusinessObjects Enterprise session.

BusinessObjects Enterprise session time-out
             The time-out of a Business Objects Enterprise SDK Session is the life time of
             the IEnterpriseSession object; the session is destroyed when the object is
             destroyed.
             Business Objects recommends that you store the users IEnterpriseSession
             object in the application server session objects, in this way the user session
             have the exact same time out as the Application server session.


Implementing “Hello World”
             Following is an implementation of the Hello World application discussed on
             page 16. To run this application you need to have installed BusinessObjects
             Enterprise and established a Business Objects Central Management System.
             For more information, see the Installation and Configuration Guide for
             Windows or UNIX.




                                                         ReportEngine Developer Guide 21
2   Application Essentials
    Implementing “Hello World”




                             index.jsp                          login.jsp


                                         Name = “janderson”

                                           Pass = “********”




                            logout.jsp                         home.html

                     In this implementation index.jsp displays a form which collects the user’s login
                     information which is passed to login.jsp. Login.jsp attempts to create a session
                     and IInfoObject for the user. If the operation is successful, login.jsp
                     redirects to home.html which displays the “Hello World” message and a link to
                     logout.jsp. When the user clicks the logout link, logout.jsp closes the session
                     and displays index.jsp again.

    index.jsp
                     <html>
                     <body>
                     <h1>Create a BusinessObjects Enterprise Session</h1>
                     <form name="LoginForm" action="login.jsp" method="POST">
                        <table><tr>
                            <td>Name: </td>
                            <td><input name="Name"></td>
                        </tr>
                        <tr>
                            <td>Password: </td>
                            <td><input type="password" name="Pass"></td>
                        </tr>
                        <TR>
                            <TD>Crystal Management System:</TD>
                            <TD><input name="CMS"></TD>
                        </TR>
                        <TR>
                            <TD>Authentication:</TD>
                            <TD>
                               <select name='auth'>
                                   <option value='secEnterprise'>Enterprise</
                        option>
                                   <option value='secLDAP'>LDAP</option>
                               </select>
                            </TD>


    22   ReportEngine Developer Guide
Application Essentials
                                                           Implementing “Hello World”    2
               </TR>
               <tr>
                   <td><input id=s1 name=s1 type=submit value="Login"></
               td>
               </tr></table>
            </form>
            </body>
            </html>

login.jsp
            This page is opened when the user clicks Login in the form LoginForm
            described on page 19. The user name and password used for the login are
            passed from the HTML form in the query string parameters Name and Pass.
            <%@ page
               import="com.crystaldecisions.sdk.framework.CrystalEnterp
               rise" %>
            <%@ page
               import="com.crystaldecisions.sdk.framework.IEnterpriseSe
               ssion" %>
            <%@ page
               import="com.crystaldecisions.sdk.framework.ISessionMgr"
               %>
            <%@ page
               import="com.crystaldecisions.sdk.exception.SDKException"
               %>
            <%
               String CMS = request.getParameter("cms");
               String userID = request.getParameter("user");
               String password = request.getParameter("password");
               String auth = request.getParameter("auth");
               if   (   CMS == null) CMS = "";
               if   (   userID == null) userID = "";
               if   (   password == null) password = "";
               if   (   auth == null) auth = "";

               IEnterpriseSession enterpriseSession;
               try
               {
                   ISessionMgr mySessionMgr =
                          CrystalEnterprise.getSessionMgr();
                   enterpriseSession =
                      mySessionMgr.logon(userID, password, CMS,auth);
                   if (enterpriseSession != null)
                   {//Create and store useful objects for the session.
                      session.setAttribute("EnterpriseSession",
                          enterpriseSession);
                      IInfoStore iStore = (IInfoStore)
                          enterpriseSession.getService("InfoStore");
                      session.setAttribute("InfoStore", iStore);
                      response.sendRedirect("home.html");
                   }
                   else response.sendRedirect("index.jsp");



                                                    ReportEngine Developer Guide 23
2   Application Essentials
    User preferences


                             }
                             catch( SDKException mySDKExept)
                             {
                                response.sendRedirect("index.jsp");
                             }
                     %>

    home.html
                     <html>
                     <body>
                     <h1>Create a Web Intelligence Session: Home Page</h1>
                     <p>Hello World!</p>
                     <a href="logout.jsp">Log out</a>
                     </body>
                     </html>

    logout.jsp
                     <%@ page
                        import="com.crystaldecisions.sdk.framework.IEnterpriseSe
                        ssion" %>

                     <%
                             IEnterpriseSession enterpriseSession;
                             enterpriseSession =(IEnterpriseSession)
                                    session.getAttribute("EnterpriseSession");
                             session.removeAttribute("EnterpriseSession");
                             if(enterpriseSession != null)
                             {
                                enterpriseSession.logoff();
                                enterpriseSession = null;
                             }
                     %>



    User preferences
                     Users can set their InfoView and ReportEngine viewing options using the
                     Preferences page in InfoView or BusinessObjects Enterprise SDK.
                     When designing a ReportEngine SDK application you should take this into
                     account. For example, if the user wants to use the Java version of the Report
                     Panel for creating and editing documents, then you need to design your
                     application so that it can display the Java Report Panel rather than the DHTML
                     Report Panel.




    24   ReportEngine Developer Guide
Application Essentials
                                                                      User preferences      2
Accessing InfoView user preferences
         With BusinessObjects Enterprise SDK you can get, set and add new
         preferences in a user’s profile. Standard preferences and possible settings
         are:
         BusinessObjects Enterprise user preference variables, values and meaning.

         Variable Name                           Possible     Meaning
                                                 Values
         webi_view                                P           View documents in PDF
                                                              format.
                                                  I           View Documents in
                                                              Interactive format.
                                                  H           View Documents in
                                                              DHTML format.
                                                              (default)
         webi_panel                               java        Create documents
                                                              using the Java Report
                                                              Panel.
                                                              (default)
                                                  html        Create documents
                                                              using the HTML Report
                                                              Panel.
         DOCUMENT_WIStartNewDrill                 duplicate   Start the drill action in a
                                                              duplicate report.
                                                  existing    Start the Drill action in
                                                              the current report.
                                                              (default)
         DOCUMENT_WIPromptDrillOutScope N                     Prompt if drill requires
                                                              additional data.
                                                              (default)
                                                  Y           Do not prompt if Drill
                                                              requires additional data.
         DOCUMENT_WISyncDrillBlocks               N           Synchronize Drill on
                                                              report blocks.
                                                              (default)
                                                  Y           Do not Synchronize Drill
                                                              on report blocks.




                                                      ReportEngine Developer Guide 25
2   Application Essentials
    User preferences


                      Variable Name                                Possible   Meaning
                                                                   Values
                      DOCUMENT_WIDrillBar                          N          Show the Drill bar.
                                                                   Y          Hide the Drill bar.
                                                                              (default)
                     Note: other applications may have their own user settings which are stored
                     in the user profile. For more information see “Adding custom options to a
                     user’s profile” on page 28.

    Getting a user’s InfoView preferences
                     To read the value of a user’s option:
                     1.      Get the current user’s IUser object using an IInfoStore query.
                     2.      Get the "desktopsettings" profile string.
                     3.      Convert the profile string to a Map for easy manipulation and printing.
                     Example: Printing a user’s preferences
                     The following code functions show how to retrieve a user’s BusinessObjects
                     Enterprise preferences and print them to an HTML response stream.
                     <%!
                     //Return a string containing a user’s Web Intelligence
                         Preferences
                     String getWebiPrefs(IInfoStore iStore, int uId){
                         String prefs = "";
                         String sQuery = "SELECT SI_ID, SI_NAME, SI_DATA FROM”
                                    + “ CI_SYSTEMOBJECTS WHERE SI_ID = '"
                                    + uId + "'";
                         IInfoObjects users = null;
                         try{
                             users = iStore.query(sQuery);
                             if (users.size() > 0){
                                IUser user = (IUser)users.iterator().next();
                                prefs = user.getProfileString("desktopsettings");
                             }
                         }catch(SDKException sEx){
                             return ““;
                         }
                         return prefs;
                     }
                     //Convert a String of preferences to a Map
                     Map webiPrefsToMap(String prefs){
                         StringTokenizer st = new StringTokenizer (prefs, "&");
                          Map webiPrefs = null;
                          while (st.hasMoreTokens()) {
                            String s2 = st.nextToken();
                            StringTokenizer st2 = new StringTokenizer (s2, "=");
                            if (st2.countTokens() == 2)



    26   ReportEngine Developer Guide
Application Essentials
                                                                           User preferences     2
                       webiPrefs.put(st2.nextToken(), st2.nextToken());
                   }
                   return webiPrefs;
              }
              %>


              The following code fragment shows how to use the functions declared above
              to print a user’s BusinessObjects Enterprise preferences to an HTML stream.
              <%
              int userID = myIEnterpriseSession.getUserInfo().getUserID();
              PrintWriter myWriter = response.getWriter();
              String prefs = getWebiPrefs(myIInfoStore, userID);
              Map prefsMap = webiPrefsToMap(prefs);
              if (prefsMap != null){
                 Iterator itr = prefsMap.entrySet().iterator();
                 while(itr.hasNext()) {
                     Map.Entry current = (Map.Entry)itr.next();
                     myWriter.print (
                        current.getKey()
                        + "="
                        + current.getValue() + "<br>");
                 }
              }
              %>



Setting an option in a user profile
              To set an option:
              1.   Get a user’s preferences.
              2.   Update a standard option in the Map continuing the user preferences.
              3.   Convert the Map to a String.
              4.   Update the user profile with IInfoStore.commit.
              Example: Setting a user’s report panel preference to Java
              The following code functions enables a user’s profile to be updated to use the
              Java Report Panel.
              <%!
              //Update the user’s Web Intelligence preferences.
              void setWebiPrefs(IInfoStore iStore, String prefs, int uId)
              {
                  String sQuery = "SELECT SI_ID, SI_NAME, SI_DATA FROM
                  CI_SYSTEMOBJECTS WHERE SI_ID = '"
                            + uId + "'";
                  IInfoObjects users = null;
                  try{
                     users = iStore.query(sQuery);
                     if (users.size() > 0){



                                                         ReportEngine Developer Guide 27
2   Application Essentials
    User preferences


                                     IUser user = (IUser)users.iterator().next();
                                     user.setProfileString("desktopsettings", prefs);
                                     iStore.commit(users);
                                }
                             }catch(SDKException sEx){
                                ;
                             }
                     }

                     //Convert a preferences Map to a string
                     String webiPrefsToSting(Map wPrefs){
                           StringBuffer sbWebiPrefs = new StringBuffer();
                           Iterator itr = wPrefs.entrySet().iterator();
                           while(itr.hasNext()) {
                             Map.Entry current = (Map.Entry)itr.next();
                             if(sbWebiPrefs.length() != 0)
                               sbWebiPrefs.append("&");

                                   sbWebiPrefs.append(current.getKey());
                                   sbWebiPrefs.append("=");
                                   sbWebiPrefs.append(current.getValue());
                                }
                                return sbWebiPrefs.toString();
                     }
                     %>

                     The following code fragment shows how to use the functions declared above
                     to update a user’s Web Intelligence preferences.
                     <%
                     //Update a user’s Web Intelligence preferences
                     int userID = myIEnterpriseSession.getUserInfo().getUserID();
                     String prefs = getWebiPrefs(myIInfoStore, userID);
                     Map prefsMap = webiPrefsToMap(prefs);
                     prefsMap.put( "webi_panel", "java");
                     setWebiPrefs(iStore, webiPrefsToSting(prefsMap), userID);
                     %>

                     Note: The functions getWebiPrefs and webiPrefsToMap are declared in the
                     example “Printing a user’s preferences” on page 26


    Adding custom options to a user’s profile
                     To add custom options to a user’s profile:
                     1.      Get a user’s preferences.
                     2.      Set the custom option with Map.put.
                             When you set an option that does not exist in the user profile, Map.put
                             creates a new option and sets it to the value you specify.
                     3.      Convert the Map to a String.



    28   ReportEngine Developer Guide
Application Essentials
                                                                   Exception handling     2
       4.   Update the user profile with IInfoStore.commit.
       Example: Adding a new preference to a user’s profile
       The following code fragment sets a custom preference.
       <%
       //Add a custom Web Intelligence preference using functions
          defined in the previous examples
       int userID = myIEnterpriseSession.getUserInfo().getUserID();
       String prefs = getWebiPrefs(myIInfoStore, userID);
       Map prefsMap = webiPrefsToMap(prefs);
       prefsMap.put( "MyPreference", "tea");
       setWebiPrefs(iStore, webiPrefsToSting(prefsMap), userID);
       %>

       Note: The functions getWebiPrefs and webiPrefsToMap are declared in the
       example “Printing a user’s preferences” on page 26.



Exception handling
       BusinessObjects Enterprise SDK generates exceptions of the type
       REException.
       Depending on the cause of the exception, ReportEngine SDK generates
       exceptions of the following type:
       •    CommunicationException
       •    ConfigurationException
       •    CustomSortException
       •    DSObjectSynchroException
       •    FilterConditionException
       •    NotImplementedException
       Exceptions and their descriptions are listed in the online reference
       documentation.
       Note: All exception classes (above) are subclasses of the REException
       class, Business Objects recommends using the REException.getCode
       when testing code.
       Note: You can return localized error messages message by calling
       REException.getLocalizedMessage.




                                                   ReportEngine Developer Guide 29
2   Application Essentials
    Reporting essentials



    Reporting essentials
                     All applications that view, edit or format Web Intelligence and Desktop
                     Intelligence documents need to:
                     •       reference ReportEngine SDK
                     •       retrieve the ReportEngines service
                     •       retrieve the ReportEngine instance
                             This links the ReportEngine and platform packages.
                     •       close the ReportEngines object
                     Note: You use Report Engine SDK to:
                     •       View, refresh, fill prompt, drill, edit query and format Web Intelligence
                             documents.
                     •       View refresh, fill prompt Desktop Intelligence documents.

    Referencing ReportEngine SDK
                     Referencing the ReportEngine packages gives your web application access to
                     the ReportEngine SDK functions.
                     ReportEngine SDK allows users to work with both Web Intelligence and
                     Desktop Intelligence documents. Use the ReportEngines factory object to
                     retrieve the ReportEngine instance necessary to open the document type
                     required.
                     If the web application uses J2EE it must reference REBean.
                     Example: Referencing the ReportEngine SDK
                     To import the REBean package, add the following line to JSP pages that use
                     REBean.
                     <%@ page import= "com.businessobjects.rebean.wi.*" %>
                     You need to include this line in every JSP page that uses REBean classes.



    Creating a ReportEngine object
                     To create a ReportEngine object for an application that uses ReportEngine
                     SDK, retrieve the ReportEngines object from the user’s
                     IEnterpriseSession. Using the ReportEngines object you can retrieve a
                     ReportEngine instance to open either Web Intelligence or Desktop
                     Intelligence documents.




    30   ReportEngine Developer Guide
Application Essentials
                                                           Reporting essentials    2
Once instantiated, manipulation of a ReportEngine instance is essentially the
same, regardless of whether the current user has opened a Web Intelligence
or Desktop Intelligence document. This eliminates the need for repeated
conditional statements to check the document type and allows simpler, more
streamlined code to be written.
Example: Instantiating a ReportEngine an IReportEngine object
To instantiate the ReportEngine object, add the following lines to one page
of the web application that uses the reporting features of the ReportEngine
SDK.
ISessionMgr mySessionMgr =
   CrystalEnterprise.getSessionMgr();
enterpriseSession =
   mySessionMgr.logon(userID, password, CMS,auth);
if (enterpriseSession != null)
{
   ILogonTokenMgr iLManager =
       enterpriseSession.getLogonTokenMgr() ;
   ReportEngines repEngines = (ReportEngines)
       enterpriseSession.getService("ReportEngines");
   ReportEngine widocRepEngine =
       (ReportEngine)repEngines.getService(
          ReportEngines.ReportEngineType.WI_REPORT_ENGINE);
   session.setAttribute("widReportEngine", widocRepEngine);
}
Use the “kind” attribute of a document IInfoObject to see if a Web Intelligence
or Desktop Intelligence ReportEngine needs to be opened.
Example: Instantiating a ReportEngine objects depending on file type
String strQuery = "Select SI_KIND from CI_INFOOBJECTS”
              + “where SI_ID=" + strDocId;
IInfoObjects iDocObjects = iStore.Query(strQuery);
IInfoObject iDocObject = null;
try
{
    iDocObject = (InfoObject) iDocObjects[0];
}
catch
{
    ...
}
String strKind = iDocObject.Kind;
ReportEngine reportEngine = null;
if(strKind.Equals("Webi"))
{
    reportEngine = reportEngines.getService(
           ReportEngineType.WI_ReportEngine);
}
else
{
    reportEngine = reportEngines.getService(



                                            ReportEngine Developer Guide 31
2   Application Essentials
    Reporting essentials


                                 ReportEngineType.FC_ReportEngine);
                     }


    Closing a ReportEngines object
                     Just as you need to close a BusinessObjects Enterprise session, you should
                     also close a ReportEngines when you have finished with it. To close a report
                     engine object use ReportEngines.close(). This method deallocates the
                     memory assigned to the object and should be called before you call
                     IEnterpriseSession.logoff().




    32   ReportEngine Developer Guide
ReportEngine Developer Guide


Document Management




                               chapter
3   Document Management
    Overview



    Overview
                    Two key parts of a typical ReportEngine SDK application are listing the
                    documents that the user can view, and depending on the user’s rights, allowing
                    the user to browse and manage categories and folders used to organize the
                    documents.
                    This chapter explains how to open, list, and work with documents.


    Document types
                    With BusinessObjects Enterprise SDK you can work with:
                    •   Web Intelligence documents
                    •   Desktop Intelligence documents
                    •   Crystal Reports documents
                    •   third-party documents, for example Microsoft Excel (.xls), and Adobe
                        Acrobat (.pdf) files
                    Using ReportEngine SDK you can do everything Web Intelligence users can
                    do with Web Intelligence documents:
                    •   view as DHTML
                    •   view as PDF
                    •   view as Excel
                    •   view as XML
                    •   refresh
                    •   create
                    •   categorize
                    •   delete
                    •   drill
                    •   save
                    •   schedule
                    •   send




    34   ReportEngine Developer Guide
Document Management
                                                              Document state: storage tokens   3
Document state: storage tokens
              Storage tokens represent a state of a document at a particular stage, each
              time a document is edited, for example refreshed, the document state
              changes. Storage tokens are used to:
              •   Retrieve the document state from page to page.
              •   Simulate an undo action in a customized application.

Storage token life cycle
              ReportEngine SDK generates a storage token:
              •   when you open a document
              •   when the microcube contents are modified or formatted
              When you open a document, ReportEngine SDK creates a
              DocumentInstance object that has a storage token. ReportEngine SDK also
              creates a temporary state that contain information about the document’s
              current state.

              Temporary files                Executing file              doc object


                                            open doc
                                                                           StorageToken = r0

                  r0




                                                 view1

              A storage token is self descriptive with regards to the type of ReportEngine
              required to open the associated document. This means that you do not need
              to check the document type before opening. For information on how to control
              storage token, see “Configuring ReportEngine using webi.properties” on
              page 135.
              As the document changes state through the execution of JSP files, the storage
              token changes too, and more temporary states, representing the document’s
              states, are created.




                                                         ReportEngine Developer Guide 35
3   Document Management
    Document state: storage tokens


                    You can retrieve the maximum storage stack size, that is to say, the maximum
                    number of storage tokens that can be created as a document changes state
                    programmatically and validate that a storage token is valid by calling
                    ReportEngine.getStorageTokenStackSize() or
                    ReportEngine.IsStorageTokenValid.
                    ReportEngine SDK generates a new storage token and corresponding set of
                    temporary files at the following triggers:

                     User interface Triggers              SDK Triggers
                     refreshing the document              calling DocumentInstance.getView
                     drilling                             modifying the DrillPath object
                     creating and editing a document      calling DataProvider.getResult
                     applying new formats                 calling DataProvider.runQuery
                                                          IDataProvider.RunQuery
                     running a query                      opening a document

                    Note: Setting a password and filling in a prompt does not cause a new token
                    to be generated directly. However, a new storage token is generated when
                    you commit the change using DocumentInstance.getView.
                    Example: Storage token life cycle
                    The following diagram shows how storage tokens change according to triggers
                    in the user interface and the object model. It also shows how the storage
                    tokens are passed between web pages and refer file states stored in memory
                    that can be used to reconstruct the DocumentInstance object using the call
                    ReportEngine.getDocumentFromStoratagetoken. In the diagram below,
                    this call name is shortened to “get doc”.
                    Using the storage token as an identifier for a document state, you can restore
                    the document to any of its saved states.




    36   ReportEngine Developer Guide
Document Management
                                            Document state: storage tokens   3
  e.




Temporary files       Executing files                docInstance object

                  1
                      open docInstance
                                                     StorageToken = r0

   r0
          GIF         run query
                                                     StorageToken = r0-s0

       r0-s0


                              view1

                              r0-s0

                  2
                      get doc(r0-s0)
          GIF
          GIF         drill                          StorageToken = r0-s1

       r0-s1




                              view2

                              r0-s1

                  3
                      get doc(r0-s1)

          GIF         drill                          StorageToken = r0-s2

       r0-s2



          GIF         commit change                  StorageToken = r0-s3
                              view3
       r0-s3




                                         ReportEngine Developer Guide 37
3   Document Management
    Organizing documents in categories and folders


                     Table 3-1 Storage token life cycle

    Advantages of storage tokens
                     Performance
                     Using a storage token is to refer to document states is fast and optimized for
                     memory usage.
                     Lifetime
                     A storage token in the file system lasts as long as the ReportEngines object
                     used to create ReportEngine instances. Business Objects recommended
                     that you store a ReportEngines object in the session object once it is created
                     and retrieve it again as required for document storage tokens to be valid
                     throughout an application.
                     Browser navigation back and forward
                     After progressing through several document states, users can go back and
                     forwards in their browser to a previous document state and continue working
                     from that state.
                     Undo mechanism
                     You can build an undo mechanism by passing the storage token from the
                     previous action perform on the document to the next web page.


    Organizing documents in categories and
    folders
                     In InfoView, categories and folders are used to classify documents in the
                     central management system. Documents organized in the hierarchical
                     category and folder structures are easier for users to find; A user can save a
                     document to selected categories and folders. A document can be assigned to
                     one or more public or personal categories.




    38   ReportEngine Developer Guide
Document Management
                                                Organizing documents in categories and folders   3




             Table 3-2 Categorized documents.
             Using the BusinessObjects Enterprise query mechanism you can navigate a
             category or folder hierarchy and retrieve IInfoObjects containing the
             individual categories and folders. These in turn enable you to:
             •   create, rename and delete categories and folders
             •   get the details of a categories and folders

User rights for categories and folders
             A System administrator, using BusinessObjects Enterprise Central
             Management Console, can set how much control a user or group has over
             categories and folders. User rights settings are updated in the Advanced
             Rights page of the InfoView section for BusinessObjects Enterprise
             Applications of the Central Management Console.
             The following table lists an InfoView user’s possible rights.
             Folder and category-related settings in a Web Intelligence user’s rights

              InfoView Advanced Right           Variable Name
              User can change preferences CeInfoViewRightID.PREFERENCE

              User can move and copy            CeInfoViewRightID.ORGANIZE
              objects, create shortcuts and
              add object to the favorites
              folder.
              Can use InfoView simple           CeInfoViewRightID.SIMPLESEARCH
              search
              Can use InfoView advanced         CeInfoViewRightID.ADVANCEDSEARCH
              search




                                                           ReportEngine Developer Guide 39
3   Document Management
    Organizing documents in categories and folders


                     InfoView Advanced Right         Variable Name
                      Can use InfoView filter feature CeInfoViewRightID.FILTER

                      User has a favorites folder    CeInfoViewRightID.FAVORITES

                      User can view inbox contents CeInfoViewRightID.VIEWINBOX

                      User can create categories     CeInfoViewRightID.CREATECATEGORIES

                      User can assign categories to CeInfoViewRightID.ASSIGNCATEGORIES
                      users or groups
                      User can send documents to     CeInfoViewRightID.SENDDOCUMENTS
                      users and groups
                      User can create dashboards     CeInfoViewRightID.CREATEDASHBOARDS

                      User can create folders        CeInfoViewRightID.CREATEFOLDERS

                     A list of a user’s rights over an object in the IInfoStore can be recovered by
                     retrieving the user’s ISecurityInfo object for a certain BusinessObjects
                     Enterprise application.
                     Example: how to check that a user has the right to create categories
                     This code fragment shows how to validate a user has the right to create
                     categories.
                     <%
                          IInfoStore iStore =
                                     (IInfoStore)session.getAttribute("InfoStore");
                          IInfoObject infoView = null;
                          String query = "SELECT STATIC FROM CI_APPOBJECTS,”
                                     + “ CI_SYSTEMOBJECTS WHERE”
                                     + “ (SI_PARENTID = 99 AND SI_KIND='"
                                     + CeKind.INFOVIEW + "')";
                          try{
                             IInfoObjects appObjects = iStore.query( query);
                             if (appObjects.size() > 0)
                                 infoView = (IInfoObject )appObjects.get(0);
                             if (infoView != null){
                                 ISecurityInfo secInfo =
                                     infoView.getSecurityInfo();
                                 if (secInfo.checkCustomRight(
                                     CeInfoViewRightID.CREATECATEGORIES,
                                     infoView.getKind()))
                                 {
                                 ...
                                 }
                             }



    40   ReportEngine Developer Guide
Document Management
                                              Organizing documents in categories and folders     3
                  }catch (Exception exc){
                     ...
                  }
             %>
             Note: Before trying to manage categories, check that the user who started
             the session has the appropriate rights.
             Note: A list of a rights for other BusinessObjects Enterprise applications can
             be found by changing the CeKind being searched for. For example, to search
             for a user’s Web Intelligence rights the query string would include
             CeKind.WEBINTELLIGENCE in the place of CeKind.INFOVIEW.

Navigating categories and folders
             Categories and folders in a Central Management System are represented as
             a tree. Personal and Public are root nodes for categories. Home is the root
             node for folders.
             To access the category or folder trees, query the repository to retrieve the ID
             of the parent node for categories or folders. Use this ID to navigate the child
             nodes.
             Example: Traversing the category tree recursively
             The following example shows functions that use BusinessObjects Enterprise
             SDK to recover the ID of the parent folder for a user’s personal categories.
             Using this ID a bulleted list containing the hierarchical structure of the user’s
             personal categories is generated.
             <%! //Return the ID of a specific folder
             public int getFolderParentId(IInfoStore iStore, int userID,
                           String kind){
                int FolderID = 0;
                IInfoObjects folders = null;
                String query = "SELECT SI_PARENTID FROM CI_INFOOBJECTS”
                       + “ WHERE SI_KIND='" + kind + "'"
                       + “ AND SI_OWNERID=" + userID;
                try{
                    folders = iStore.query(query);
                    if(folders.size() > 0)
                       FolderID=
                           ((IInfoObject)folders.get(0)).getParentID();
                }catch (SDKException sdke){
                    return FolderID;}
                return FolderID;
             }
             //Return a selectable list of categories or folders
             String getCategoryList(IInfoStore iStore,
                           int id, String kind ){
                String results = "";
                IInfoObject category;
                if (id == -1) id = 0;
                String sQuery = "SELECT SI_ID, SI_NAME, SI_PARENTID FROM”



                                                          ReportEngine Developer Guide 41
3   Document Management
    Organizing documents in categories and folders


                                        + “ CI_INFOOBJECTS WHERE SI_PARENTID=" + id
                                        + " AND SI_KIND= '"+ kind + "'" ;
                          try{
                            IInfoObjects categories = iStore.query(sQuery);
                            if (!categories.isEmpty()){
                              results += "<ul>";
                              for(int i = 0; i < categories.size(); i++){
                                  category = (IInfoObject)categories.get(i);
                                  String name = category.getTitle();
                                  int catID = category.getID() ;
                                  results += "<li><input type="radio" name=""
                                     + kind + "" value=""
                                     + catID + "" >" + name + "</li>n";
                                  results += getCategoryList(iStore,
                                     category.getID(), kind);
                              }
                              results += "</ul>";
                            }
                          }catch (SDKException sdke){
                                  results = null;
                          }
                          return results;
                     }
                     %>
                     The following code fragment shows how to use the functions declared above
                     to print personal categories for a user.
                     <%
                     IEnterpriseSession enterpriseSession =(IEnterpriseSession)
                                   session.getAttribute("EnterpriseSession");
                     IInfoStore iStore=
                                   (IInfoStore)session.getAttribute("InfoStore");
                     int userID = enterpriseSession.getUserInfo().getUserID();
                     int persoCatsfolderID = getFolderParentId(
                                   iStore,userID,(String)CeKind.PERSONALCAT);
                     String catButtons =
                            getCategoryList(
                                   iStore, (String)CeKind.PERSONALCAT));
                     %>
                     Note: For an example of how to list documents in a folder, see “Displaying a
                     document list” on page 47.


    Retrieving Inbox and favorites folder IDs
                     Each BusinessObjects Enterprise user has unique personal directories. The
                     Inbox and Favorites directories contain documents sent to a specific user or
                     saved for personal rather than corporate use. To list the contents of these
                     folders you need to retrieve the ID for each user’s personal directories. Once
                     the root directory ID is retrieved, you can list and navigate the contents in the
                     same way corporate folders are navigated.




    42   ReportEngine Developer Guide
Document Management
                               Organizing documents in categories and folders   3
Example: Retrieve a user’s Inbox and Favorites folder IDs
The following example shows functions that use BusinessObjects Enterprise
SDK to recover the ID of the parent folder for a user’s Inbox and Favorites
folders.
<%!
//Retrieve the ID for any type of personal folder
public int getFolderId(IInfoStore iStore, int userID,
              String kind){
    int FolderID = 0;
    IInfoObjects folders = null;
    String query = "SELECT SI_ID" +
           " FROM CI_INFOOBJECTS" +
           " WHERE SI_KIND='" + kind + "'" +
           " AND SI_OWNERID=" + userID;
    try{
       folders = iStore.query(query);
       if(folders.size() > 0)
           FolderID = ((IInfoObject)folders.get(0)).getID();
    }catch(SDKException sdke){
       FolderID = -1;
    }
    return FolderID;
}
//Retrieve the ID of a user’s Inbox
int getInboxFolderId(IInfoStore iStore, int userID){
    return getFolderId(iStore,userID,(String)CeKind.INBOX);
}
//Retrieve the ID of a user’s favorites folder
int getFavoritesPFolderID(IInfoStore iStore, int userID){
    return
       getFolderId(iStore,userID,(String)CeKind.FAVORITESF);
}
%>

//The following example shows how to retrieve a list of
   documents in the current user’s Inbox. See “Displaying a
   document list” on page 47 for the definition of getList.
<%
IEnterpriseSession enterpriseSession;
IInfoObjects docList = null;
enterpriseSession = (IEnterpriseSession)
             session.getAttribute("EnterpriseSession");
IInfoStore iStore = (IInfoStore)
             session.getAttribute("InfoStore");
int userID = enterpriseSession.getUserInfo().getUserID();
int inboxID = getInboxFolderId(iStore, userID);

docList =
       getList(iStore, inboxID, (String)CeKind.WEBI );

%>




                                          ReportEngine Developer Guide 43
3   Document Management
    Organizing documents in categories and folders


                     Note: See “Displaying a document list” on page 47 for the definition of
                     getList.

    Creating categories and folders
                     You can add categories and folders by:
                     •   getting the ID of the folder or category in which you wish to create a node
                     •   getting the correct plug-in to create a node
                     •   committing the new object to the Central Management System
                     Example: Creating a new folder or category
                     The following example shows functions that use BusinessObjects Enterprise
                     SDK to create a new folder or category.
                     <%!
                     int addFolderOrCategory(IInfoStore iStore,
                                   int parentFolderID,String name,
                                   String description, String type){
                         int objectID = 0;
                         IPluginInfo plugin;
                         try{
                            IPluginMgr pluginMgr = iStore.getPluginMgr();
                            plugin = pluginMgr.getPluginInfo(type);
                            IInfoObjects newInfoObjects =
                                   iStore.newInfoObjectCollection();
                            newInfoObjects.add(plugin);
                            IInfoObject infoObject = (IInfoObject)
                                   newInfoObjects.get(0);
                            infoObject.setTitle (name);
                            infoObject.setDescription (description);
                            objectID = infoObject.getID();
                            infoObject.properties().setProperty(
                                   CePropertyID.SI_PARENTID, parentFolderID);
                            iStore.commit (newInfoObjects);
                         }catch (SDKException e) {
                            throw new Error("Failed to add the object.");
                         }
                         return objectID;
                     }
                     %>
                     The following code fragment shows how to use the functions declared above
                     to create a new personal category and a new folder.
                     <%//How to use this function
                     //Create a new personal category
                     addFolderOrCategory(iStore, categoryParentID,
                        "Category Name", "Keywords",CeKind.PERSONALCAT);
                     //Create a new personal folder
                     addFolderOrCategory(iStore, categoryParentID,
                        "Folder Name", "Keywords", CeKind.FOLDERS);%>




    44   ReportEngine Developer Guide
Document Management
                                               Organizing documents in categories and folders     3
Moving and renaming categories and folders
             You can move categories and folders from one parent to another using the
             IInfoObject.setParentID method. You can rename categories and
             folders using the IInfoObject.setTitle method.
             After the category or folder has been renamed or moved,
             IInfoStore.commit must be called with the changed IInfoObject passed as
             a parameter.
             Example: Moving and renaming categories or folders
             The following function changes the name of a folder or category and moves it
             in the folder or category hierarchy respectively.
             <%!
             String   changeNameMove(IInfoStore iStore, int ID, String
                           newName, int newParentID){
                 String query;
                 IInfoObjects result;
                 String res = "";
                 query = "Select SI_NAME, SI_ID From CI_INFOOBJECTS “
                        + “ Where SI_ID=" + ID;
                 try{
                    result = iStore.query(query);
                    if ( result.size() > 0 ){
                        IInfoObject currResult;
                        currResult = (IInfoObject)result.get(0);
                        currResult.setTitle(newName);
                        currResult.setParentID(newParentID);
                        iStore.commit(result);
                    }
                 }
                 catch(SDKException e){
                    ;
                 }
                 return res;
             }


Getting the properties of a category
             Each IInfoObject in the BusinessObjects Enterprise IInfoStore contains a
             collection of all properties assigned to that object, known as a “properties bag.”
             To retrieve IInfoObject details, request SI_NAME, SI_DESCRIPTION,
             SI_KEYWORD in the query string used to recuperate the IInfoObject
             representing a category or folder.
             Example: Retrieve the properties for a category
             The following method returns the properties of a category, folder, or document
             as an IInfoObject:
             <%!
             IInfoObject getProps(IInfoStore iStore, int ID){



                                                          ReportEngine Developer Guide 45
3   Document Management
    Working with documents


                         String query;
                         IInfoObjects result = null;
                         IInfoObject properties = null;
                         String res = "";
                         query = "SELECT SI_FILES, SI_DESCRIPTION,”
                                + ” SI_KEYWORD, SI_KIND";
                         query += " FROM CI_INFOOBJECTS WHERE SI_ID=" + ID;
                         try{
                            result = iStore.query(query);
                            if (result.size() > 0){
                                properties = (IInfoObject)result.get(0);
                            }
                         }
                         catch(SDKException e){
                            return null;
                         }
                         return properties;
                    }
                    %>
                    The following code fragment shows how to use the functions declared above
                    to print the description and keywords of an IInfoObject object to an HTTP
                    stream.
                    <%
                    int ID = Integer.parseInt(request.getParameter("ID"));
                    PrintWriter myWriter = response.getWriter();
                    IInfoStore iStore = (IInfoStore)
                                 session.getAttribute("InfoStore");
                    IInfoObject fProperties = getProps(iStore, ID);
                    myWriter.print( fProperties.getDescription() + "<br>n");
                    myWriter.print( fProperties.getKeyword() + "<br>n");

                    //Another way to retrieve the keyword IInfoObject Property
                    myWriter.print(
                       fProperties.properties().getProperty(
                              CePropertyID.SI_KEYWORD).getValue().toString());
                    %>



    Working with documents
                    Working with documents involves opening and listing the documents, then
                    providing facilities for saving, sending, scheduling, and organizing documents.

    Opening documents
                    After establishing a session for a user (see “Establishing a valid
                    BusinessObjects Enterprise user’s session” on page 20) you can open a
                    document on behalf of the user.
                    In general, to open a document you:



    46   ReportEngine Developer Guide
Document Management
                                                                    Working with documents     3
             1.   Establish a BusinessObjects Enterprise session for the user.
             2.   Get an identifier for the document.
                  The identifier can be a storage token (see “Document state: storage
                  tokens” on page 35), or more simply the document’s ID.
             3.   Retrieve the ReportEngineinstance relating to the type of document to
                  be opened.
             4.   Open the document using the ReportEngine.openDocument method
                  for Web Intelligence or Desktop Intelligence documents. See
                  “Instantiating a ReportEngine objects depending on file type” on page 31
                  for an example of how this is done.
             Taking into account user rights and profiles
             Because your Web Intelligence application acts on behalf of a user, what your
             application can do with the document is subject to the user’s rights. They are
             set in the BusinessObjects Enterprise Central Management Console. You
             should take these rights into account in your application.
             You should also take into account the settings in the user’s profile. See “User
             preferences” on page 24.

Displaying document lists
             To display a list of documents you:
             1.   Use the IInfoStore.query method to return the list of IInfoObjectss
                  representing the root directory of the user’s folders and documents.
             2.   Loop through the IInfoObject list and print the values of the fields of
                  each row.
             3.   Allow navigation through the folders.
             Note: IInfoObject is the base BusinessObjects Enterprise type. An
             IInfoObject can be used to store any type of object in the central
             management system.

Refreshing a document list
             A document list is refreshed every time IInfoStore.query is called. The
             results come directly from the BusinessObjects Enterprise Central
             Management System (CMS) with no intermediary cache.
             Example: Displaying a document list
             The following code fragment is a helper function called getList. This function
             is passed an IInfoObject object as a parameter, which is then used to return
             a list of IInfoObject objects of a required type, in this case Folders or Web
             Intelligence documents.


                                                          ReportEngine Developer Guide 47
3   Document Management
    Working with documents


                    This function is placed either at the head of the listfolders.jsp script or in a file
                    containing helper functions included in listfolders.jsp.
                    <%!
                    IInfoObjects getList(IInfoStore iStore,
                                  int searchID, String kind){
                        IInfoObjects list = null;
                        String query = "SELECT SI_ID, SI_NAME, SI_PARENTID,”
                                  + “ SI_KIND, SI_INSTANCE, SI_DESCRIPTION FROM”
                                  + “ CI_INFOOBJECTS WHERE SI_PARENTID="
                                  + searchID + " AND SI_KIND = '" + kind + "'";
                        try{
                           list = iStore.query(query);
                        }
                        catch (SDKException sdke){
                           list = null;
                        }
                        return list;
                    }
                    %>
                    The function getInfoList is called from listfolders.jsp. The following code
                    fragment shows returns a list of Web Intelligence documents in the document
                    root folder.
                    <%
                         int iID= 0; //ID of the root folder
                         IInfoObjects webiDocs = null;
                         String searchID=request.getParameter("sID");
                         if (searchID!=null) iID=Integer.parseInt(searchID);
                         IInfoStore iStore =
                                (IInfoStore)session.getAttribute("InfoStore");
                         webiDocs=getList(iStore,iID,(String)CeKind.WEBI);
                         ...
                    %>




    Saving documents
                    To save a document use DocumentInstance.save and
                    DocumentInstance.saveAs.
                    Example: Save a document
                    The following example shows how to open a document to be worked on, then
                    open and save the original version of the document.
                    <%
                    DocumentInstance doc =
                                 myReportEngine.openDocument(docID);
                    String docToken doc.getStorageToken();
                    //User perform actions on document doc...
                    //Open the first version of the document and save.
                    DocumentInstance docToSave =



    48   ReportEngine Developer Guide
Document Management
                                                                   Working with documents     3
              theReportEngines.getDocumentFromStorageToken(docToken);
           docToSave.save();
           %>
           Note: Go to “Sending documents to users, groups and categories” on
           page 50 to see how to use the saveAs method.



Scheduling documents
           Scheduling refreshes a document automatically at a specified time or times.
           When a scheduled document refreshes successfully, an instance is created.
           An instance is a version of the document containing data available at the time
           it is refreshed. Instances created later contain more recent data. By scheduling
           and viewing instances, a user can have the latest information available for
           viewing, printing, and distributing. For example, you can schedule a document
           to run every night so data viewed first thing in the morning is sure to be up to
           date.
           To schedule a document you need to:
           1.   Query the IInfoStore to get the IInfoObject representing the
                specific document.
           2.   Get the document’s ISchedulingInfo object.
           3.   Set the type and frequency of the scheduling.
           4.   Use the IInfoStore to schedule the document.


           Note: The schedule action refreshes data in a document. This means that
           Prompt, Context, and Drill actions have to be handled automatically at run
           time using information gathered from the user when the schedule action is
           created.
           Example: Scheduling a document
           The following function shows how to schedule a document to run once
           immediately or recurrently on a specific interval of days. The document
           instance created is stored in the list of document instances attached to a
           document.
           <%!
           boolean scheduleDocument(IInfoStore iStore, int documentID,
               int days){
               IInfoObjects documentList;
               ISchedulingInfo schedulingInfo;
               IInfoObject document;
               String res = "";
               boolean success = true;


                                                       ReportEngine Developer Guide 49
3   Document Management
    Working with documents


                         try {
                            String schedQuery = "Select SI_schedulingInfo From”
                                   + “ CI_INFOOBJECTS Where SI_ID="
                                   + documentID;
                            documentList = iStore.query( schedQuery);
                            if ( documentList.size() > 0 ){
                                document= (IInfoObject) documentList.get(0);
                                schedulingInfo = document.getSchedulingInfo();
                                if (days == -1){
                                   schedulingInfo.setType(CeScheduleType.ONCE);
                                   schedulingInfo.setRightNow(true);
                                } else {
                                   schedulingInfo.setIntervalDays(days);
                                   schedulingInfo.setType(
                                   CeScheduleType.DAILY );
                                }
                                iStore.schedule(documentList);
                            }
                         } catch( SDKException e ) {
                            success = false ;
                         }
                         return success;
                    }
                    %>
                    The following code fragment shows how to call the scheduleDocument
                    function to schedule a document to be run once immediately.
                    <%
                    String docId = request.getParameter("docID");
                    IInfoStore iStore =
                       (IInfoStore)session.getAttribute("InfoStore");

                    scheduleDocument(iStore, Integer.parseInt(docId), -1);
                    %>


    Sending documents to users, groups and categories
                    The list of BusinessObjects Enterprise users to whom a document can be sent
                    depends on the groups to which the current user belongs, and the current
                    user’s permissions.




    50   ReportEngine Developer Guide
Document Management
                                                       Working with documents     3
Action              To these groups and/or Depending on the current
                    users …                user’s settings for these
                                           permissions…
Save to Groups       groups and categories to DocumentInstance.saveAs
and Categories       which the current user
                     has access
Send to Inbox,       groups to which the       IInfoStore.schedule
FTP, email,          current user belongs,
groups.              and/or the other users in
                     those groups
Example: Retrieve the list of groups to which a user belongs
The following JSP function shows how to retrieve the list of groups the current
user belongs to.
<%!
IInfoObjects getUserGroups(IInfoStore iStore)
{
    IInfoObjects groups = null;
    String query = "SELECT SI_ID, SI_NAME" +
           " FROM CI_SYSTEMOBJECTS" +
           " WHERE SI_KIND='" + CeKind.USERGROUP + "'" ;
    try{
       groups = iStore.query(query);
    } catch (SDKException sdke){
       groups = null;
    }
    return groups;
}
%>

BusinessObjects Enterprise uses object security, which means that security is
set for each object in the system and not for each user. Thus, for a particular
object, certain users and certain groups have the rights to different actions,
depending on the object’s settings. Access to folders and categories can be
restricted to specific groups and individual users. Saving a document to a
specific folder and category is a way of publishing a document to a group of
users.
These permissions are controlled by the system administrator using
BusinessObjects Enterprise Central Management Console.
Procedure for sending a document to folders and categories
BusinessObjects Enterprise documents are organized by folder and category.




                                            ReportEngine Developer Guide 51
3   Document Management
    Working with documents


                    To send a document to folders use DocumentInstance.saveAs. Typically,
                    however, to send a document, you need to gather the appropriate information
                    from the current user before sending. To do this you need two web pages:
                    In the first page:
                    1.   Display the name of the document to be sent.
                    2.   Retrieve the IDs of:
                         •   corporate folders and categories
                         •   the root directory of the current user's personal categories
                    3.   Get and display the list of folders and categories to which the current user
                         can send documents.
                    4.   Pass this information to the second page.
                    Then, in the second page:
                    1.   Get the details entered by the user.
                    2.   Call DocumentInstance.saveAs.
                    Example: Sending a document to folders and categories
                    The following code fragments are used to save a document in specific
                    folders and categories. saveDocAs.jsp is called by a page that passes the
                    name and ID of the document in the query string. In saveDocAs.jsp the user
                    selects the folders and categories the document is to be saved in. When the
                    user clicks “Save Document” in the form, saveDocAs.jsp is executed and the
                    document is sent according to the user’s selections.
                    Note: The function getCatOrFoldersRadioButtons and webiPrefsToMap is
                    declared in the example “Traversing the category tree recursively” on
                    page 41.
                    <%!
                    //Return the ID of a specific folder
                    public int getFolderParentId(IInfoStore iStore, int userID,
                                  String kind){
                        int FolderID = 0;
                        IInfoObjects folders = null;
                        String query = "SELECT SI_PARENTID FROM “
                           + “ CI_INFOOBJECTS WHERE SI_Kind='"
                           + kind + "'" + AND SI_OWNERID=" + userID;
                        try{
                         folders = iStore.query(query);
                         if(folders.size() > 0)
                         FolderID=((IInfoObject)folders.get(0)).getParentID();
                        }catch (SDKException sdke){
                           return FolderID;}
                        return FolderID;
                    }
                    %>



    52   ReportEngine Developer Guide
Document Management
                                                                    Working with documents    3
             The following code fragment shows how to use the functions declared above
             to create a form used to select the folders and categories in which a document
             will be saved.
             In saveDoc.jsp
             <%
             //get the parameters from the request object
             String docId = request.getParameter("docID");
             String docName = request.getParameter("docName");
             String docParentFolderID =
                request.getParameter("corpFolder");
             String corpCategID = request.getParameter("corpCategory");
             String persoCatedID = request.getParameter("persoCategory");
             List ccIDlist = new ArrayList();
             List pcIDlist = new ArrayList();
             //Validate the parameters
             if (corpCategID != null)
                ccIDlist.add(Integer.decode(corpCategID));
             if (persoCatedID != null)
                pcIDlist.add(Integer.decode(persoCatedID));
             if (docId != null && docParentFolderID != null){
             //Open and save the document
                DocumentInstance docToSave =
                    webiRepEngine.openDocument(Integer.parseInt(docId));
                if( docToSave != null)
                    docToSave.saveAs( docName,
                           Integer.parseInt(docParentFolderID),
                           ccIDlist,pcIDlist);
             }
             %>
             Note: corpCategories and persoCategories are strings containing the ID’s of
             the corportate and personal category chosen by the active user to store the
             document in.

Sending a document to the Inbox of users or groups
             If the current user has the appropriate permissions, you can schedule a
             document to be send to the inboxes of users or groups of users to which the
             current user belongs.
             Procedure for sending a document to inboxes
             To schedule a document, you need to gather the appropriate information from
             the current user before sending. To do this you need to:
             1.   Query the IInfoStore to get the IInfoObject representing the
                  document to be sent.
             2.   Get the document’s ISchedulingInfo object.
             3.   Retrieve the Inbox plugin used to send a document to users.
             4.   Set the destination and send options for the Inbox plugin.



                                                         ReportEngine Developer Guide 53
3   Document Management
    Working with documents


                    5.   Create a Set containing the IDs of users or groups to which the current
                         user can send the document.
                    6.   Allow the user to choose the users/groups to send the document to.
                    7.   Add the set of IDs created in the previous step to the Inbox plugin
                         options.
                    8.   Set the type and frequency of the scheduling.
                    9.   Schedule the document.
                    Note: In the InfoView user interface, this action is called “Send to
                    BusinessObjects Inbox.”
                    You get the list of groups to which the current user can publish documents by
                    querying the IInfoStore. The returned IInfoObjects object contains the
                    ID’s of all groups the current user has the right to send to.
                    Example: Send a document to the inbox of groups of users
                    <%!
                    //This function retrieves the Inbox destination plugin
                    IDestinationPlugin getInboxDestPlugin(IInfoStore iStore){
                        int PLUGIN_ROOT = 29;
                        IDestinationPlugin inboxPlugin = null;
                        String[] pluginsToLoad = new String[]
                        {CeKind.DISKUNMANAGED, CeKind.SMTP, CeKind.FTP,
                               Kind.MANAGED_DEST};
                        String pluginString = "";
                        for (int i = pluginsToLoad.length - 1; i >= 0; i--){
                           pluginString += "'" + pluginsToLoad[i] + "'";
                               if (i != 0) pluginString += ", ";
                        }
                        String pluginQuery = "SELECT * FROM CI_SYSTEMOBJECTS”
                                   + “ WHERE SI_PARENTID=” + PLUGIN_ROOT
                                   + “ AND SI_NAME in "
                                   + "(" + pluginString + ")";
                        try{
                           IInfoObjects destPlugins = iStore.query(pluginQuery);
                           for (int i = 0; i < destPlugins.size(); i++){
                             IInfoObject plugin =
                               (IInfoObject)destPlugins.get(i);
                             if (
                               CeKind.MANAGED_DEST.equals(plugin.getTitle()) )
                               inboxPlugin = (IDestinationPlugin)(plugin);
                           }
                        } catch (SDKException e){
                           inboxPlugin = null;
                        }
                        return inboxPlugin;
                    }

                    //This function retrieves the IDs of the groups the current
                    //user can schedule to
                    Set getUserGroupIDs(IInfoStore iStore){
                       IInfoObjects groups = null;


    54   ReportEngine Developer Guide
Document Management
                                                      Working with documents     3
     Set IDs = new Set();
     String query = "SELECT SI_ID, SI_KIND, SI_NAME"
            + " FROM CI_SYSTEMOBJECTS"
            + " WHERE SI_Kind='" + CeKind.USERGROUP + "'";
     try{
        groups = iStore.query(query);
        int size = groups.size();
        for (int i = 0; i < size; i++) {
            IInfoObject obj = (IInfoObject)groups.get(i);
            if (CeKind.USERGROUP.equals(obj.getKind())) {
               IDs.add(new Integer(obj.getID()));
            }
        }
     } catch (SDKException sdke){
        IDs = null;
     }
     return IDs;
}
%>
The following code fragment shows how to send the copy of a document to the
inbox of all users in the groups the current user is allowed to post to once a
week.
<%
     String docId = request.getParameter("docID");
     IInfoStore iStore =
               (IInfoStore)session.getAttribute("InfoStore");

     IDestinationPlugin inboxPlugin = null;
     IManagedOptions destOptions = null;
     ISchedulingInfo schedulingInfo = null;
     IInfoObjects documentList = null;
     IInfoObject document = null;
     try {
        String docQuery = "Select SI_schedulingInfo FROM”
               + “ CI_INFOOBJECTS Where SI_ID=" + docId;
        documentList = iStore.query(docQuery);
        if ( documentList.size() > 0 ) {
            document= (IInfoObject)documentList.get(0);
            schedulingInfo = document.getSchedulingInfo();
            inboxPlugin = getInboxDestPlugin(iStore);
            IDestination destination =
               schedulingInfo.getDestination();
            if (inboxPlugin != null){
             destOptions =(IManagedOptions)
               inboxPlugin.getScheduleOptions();
             destOptions.setDestinationOption(
               IManagedOptions.CeDestinationOption.ceInbox);
             destOptions.setSendOption(
               IManagedOptions.CeManagedSendOption.ceCopy);
             Set IDs = getUserGroupIDs(iStore);
             Set destinationIDs =
               destOptions.getDestinations();
             destinationIDs.clear();
             destinationIDs.addAll(IDs);


                                           ReportEngine Developer Guide 55
3   Document Management
    Document properties


                                   destination.setFromPlugin(inboxPlugin);
                                   schedulingInfo.setIntervalDays(7);
                                   schedulingInfo.setType(CeScheduleType.DAILY);
                                   iStore.schedule(documentList);
                                  }
                            }
                         } catch( SDKException e ) {
                                throw e;
                    }
                    %>



    Document properties
                    Some important characteristics of Web Intelligence and Desktop Intelligence
                    documents are stored as part of the document. You can access these
                    properties using the DocumentInstance object.
                    ForReportEngine SDK the process for accessing a property of a Web
                    Intelligence document is:
                    1.   Get the collection of properties.
                    2.   Set/Read the property.
                    3.   Commit the change, if any, to the collection of properties.

    Working with properties
                    Using ReportEngine SDK, you can access a document’s properties with
                    DocumentInstance.getProperties and
                    DocumentInstance.setProperties. These methods make use of the
                    java.util.Properties class.
                    There are predefined properties defined in PropertiesType. You can also
                    add you own properties to the document.
                    To avoid confusion in the central management system,
                    PropertiesType.NAME is read only.


                    Example: Getting the name of a document
                    The following code fragment illustrates how to get the NAME property of a Web
                    Intelligence document.
                    DocumentInstance doc =
                                 myReportEngine.openDocument(docID);
                    java.util.Properties props = doc.getProperties ();
                    String dName = props.getProperty (PropertiesType.NAME);




    56   ReportEngine Developer Guide
Document Management
                                                                      Document properties     3
Adding your own properties to the document
            Use Properties.setProperty to add your own properties to the document.
            Example: Adding a property to a document
            The following code fragment illustrates how to add the RefreshCount property
            to a Web Intelligence document.
            DocumentInstance doc =
                              myReportEngine.openDocument(docID);
            java.util.Properties props = doc.getProperties ();
            props.setProperty ("RefreshCount", "12");
            doc.setProperties (props);
            If you create a new Properties collection and add properties to that
            collection, when you call DocumentInstance.setProperties the values in
            the new object are added to the standard property collection. Permanent
            properties such as NAME and AUTHOR are not erased in the merge. Values
            for the properties that you have set in the new collection take precedence over
            those in the one attached to the DocumentInstance.




                                                        ReportEngine Developer Guide 57
3   Document Management
    Document properties




    58   ReportEngine Developer Guide
ReportEngine Developer Guide


Viewing Reports




                               chapter
4   Viewing Reports
    Overview



    Overview
                      Web Intelligence Report Engine SDK contains classes and methods for
                      viewing documents. Applications for viewing Web Intelligence and Desktop
                      Intelligence documents handle prompts, and provide report and section
                      navigation using the ReportMap.
                      This chapter discusses how to use Report Engine SDKto view Web
                      Intelligence and Desktop Intelligence reports.
                      See also and “Formatting Reports” on page 101.


    Viewing reports
                      You can view complete documents, that is to say, including all reports or
                      individual reports or report pages in a variety of different formats. The following
                      tables show the different formats available
                      Desktop Intelligence Documents

                            BINARY  EXCEL       EXCEL PDF CSV XML DHTML HTML
                            CONTENT DataCentric
    DOCUMENT                Y                            Y         Y
    REPORT                                               Y         Y             Y     Y          Y
    REPORT_PAGE                                                                  Y     Y          Y
    DATA_PROVIDERS                                                               Y
    DATA_PROVIDER                                                         Y      Y
                      Web Intelligence Documents

                           BINARY  EXCEL       EXCEL PDF CSV XML DHTML HTML
                           CONTENT DataCentric
    DOCUMENT               Y             Y               Y         Y
    REPORT                               Y               Y         Y             Y     Y         Y
    REPORT_PAGE                                                                        Y         Y
    DATA_PROVIDERS                                                               Y
    DATA_PROVIDER                                                         Y      Y
                      To view an entire document, call DocumentInstance.getView, to view an
                      individual report, call Report.getView. If you want to view all the reports in a
                      document in DHTML format, you need to get views of each report in DHTML




    60   ReportEngine Developer Guide
Viewing Reports
                                                                            Viewing reports   4
             and display those separately. See “Viewing an individual report in DHTML” on
             page 62. More information can be found in the API doc for the
             SupportedViews interface.
             Note: Calling DocumentInstance.getView and Report.getView
             generates a new storage token. For more information on storage tokens see
             “Document state: storage tokens” on page 35.

Viewing all the reports in a document
             To view all the reports in a document:
             1.   Open the document.
             2.   Get a binary view of the document.
                  You can get a binary view of a document in PDF or Microsoft Excel
                  format. When ReportEngine SDK converts the document into PDF it
                  places reports on separate pages and creates a bookmark for each
                  report. In Microsoft Excel format the reports of a Web Intelligence
                  document appear on separate sheets.
             3.   Output the binary view of the document via the implicit response object.
             You need to prepare the response object to receive the appropriate content
             type. For Adobe Acrobat format set the content type to “application/pdf”. For
             Microsoft Excel format, set the content type to “application/vnd.ms-excel”.
             Example: Viewing all the reports in a Web Intelligence document
             The following code fragment displays all the reports in a document in Adobe
             Acrobat format. In this example, the name of the document is stored in
             docName and the ID is stored in docID. Typically these would be passed
             to the script in the query string.
             <%
             // get the document
             String strDocID = request.getParameter("DocID");
             int intDocID = Integer.parseInt(strDocID)
             String strQuery = "Select SI_KIND from CI_INFOOBJECTS "
                          + "where SI_ID=" + strDocID;
             IInfoObjects iDocuments = iStore.query(strQuery);
             IInfoObject iDocument = (IInfoObject) iDocObjects.get(0);
             String strKind = iDocObject.getKind();

             // Instantiate appropriate ReportEngine according to
             // document type
             ReportEngine repEng = null;
             if (strKind.equals("Webi"))
                repEng = reportEngines.getService(
                    ReportEngineType.WI_REPORT_ENGINE);
             else
                repEng = reportEngines.getService(
                    ReportEngineType.FC_REPORT_ENGINE);



                                                        ReportEngine Developer Guide 61
4   Viewing Reports
    Viewing reports


                      // Open the document using its repository ID
                      DocumentInstance doc = repEng.openDocument(intDocID);
                      BinaryView docBinaryView = (BinaryView)
                         doc.getView(OutputFormatType.PDF);
                      //Parameterize the response
                      response.setContentType("application/pdf");
                      response.setHeader("Content-Type", "application/pdf");
                      response.setDateHeader("expires", 0);
                      //output the binary stream via the response object
                      docBinaryView.getContent(response.getOutputStream());
                      %>
                      Note: This example starts Adobe Acrobat Reader® and displays the
                      document using this application. Depending on the user’s browser
                      configuration, the document will appear in either in the browser or in a
                      separate application window.


    Viewing an individual report in DHTML
                      HTML is the standard format for viewing reports.
                      The standard viewing format is DHTML.
                      To view an individual report in DHTML format:
                      1.   Get a document instance.
                      2.   Set the report.
                      3.   Get a view of the report in DHTML format.
                      4.   Display the report.
                      Example: Viewing a report in a Web Intelligence document
                      The following code fragment displays a selected report in a Web Intelligence
                      document in DHTML format.
                      <%
                      // Get query string parameters and initialize variables
                      String sToken = request.getParameter("token");
                      String sRepID = request.getParameter("reportID");
                      DocumentInstance doc = null;
                      Report rep = null; //the report to be viewed
                      int iRepID = 0; //index of the selected report

                      // Get the document
                      doc = reportEngine.getDocumentFromStorageToken(sToken);
                      // Set the report
                      if ((sRepID != null)&&(!(sRepID.equals(""))))
                         iRepID = Integer.parseInt(sRepID);
                      else iRepID = 0;//set to the first report in the document

                      rep = doc.getReports().getItem(iRepID);




    62   ReportEngine Developer Guide
Viewing Reports
                                                                               Viewing reports   4
             //get a view of the report in DHTML format
             HTMLView docHtmlView = null;
             docHtmlView = (HTMLView)rep.getView(OutputFormatType.DHTML);
             // Set user agent (IE, Netscape…)
             String strUserAgent = request.getHeader("User-Agent");
             docHtmlView.setUserAgent(strUserAgent);
             // Full Report HTML to the output stream
             docHtmlView.getContent(out, “”, “”);

             %>
             <%=docHTMLView%>
             Note: In this example, reportEngine is an initialized ReportEngine object.

Viewing an individual report in another format
             You can view reports in Adobe Acrobat or Microsoft Excel format. The
             procedure is the same as for DHTML format (described above) except that, as
             for viewing all the reports in a document, you must get the content of the report
             as a binary stream which you can output via the response object.
             To view a report in a non-DHTML format:
             1.   Get a binary view of the report.
             2.   Output the binary view of the document via the implicit response object.
             You need to prepare the response object to receive the appropriate content
             type. For Adobe Acrobat format set the content type to “application/pdf”. For
             Microsoft Excel format, set the content type to “application/vnd.ms-excel”.
             Example: Viewing a report in Microsoft Excel format
             The following code fragment displays all the reports in a Web Intelligence
             document in Microsoft Excel format.
             //get the report to view (Report rep)
             ...
             //get the report contents as a binary stream in Excel format
             BinaryView docBinaryView =
                          (BinaryView)rep.getView(OutputFormatType.XLS);
             //output the binary stream via the response object
             response.setContentType("application/vnd.ms-excel");
             response.setHeader("Content-Type",
                          "application/vnd.ms-excel");
             response.setDateHeader("expires", 0);
             //output the binary stream via the response object
             byte[] abyBinaryContent = docBinaryView.getContent();

             //output the binary stream via the response object
             outputStream.write(abyBinaryContent);




                                                          ReportEngine Developer Guide 63
4   Viewing Reports
    Handling prompts



    Handling prompts
                       Prompts are a way to get supplementary information into a query before
                       executing. In Report Engine SDK, how you handle prompts depends on the
                       type of document you are working with. This section discusses how to handle
                       prompts in Web Intelligence and Desktop Intelligence documents.
                       Prompts are usually raised when a document is refreshed using
                       DocumentInstance.refresh if scheduled. The refresh operation executes
                       the query and, therefore, needs to collect the supplementary information that
                       resolves filters and contexts.
                       Note: Prompts that resolve universe contexts must be filled before standard
                       prompts. See “Handling context prompts” on page 74.

    Documents with a single simple prompt
                       One of the simplest and most common prompts is one that resolves a query
                       filter. For example, “Enter the year: “ to which a user responds “2003” and the
                       data retrieved by the query is restricted to the year 2003.
                       Example: Handling a single, simple prompt
                       The following code fragment illustrates how to handle a single, simple prompt.
                       (“Simple prompt” means standard, text-entry prompts only.)
                       The code in this example is from a JSP called refresh.jsp. When the user
                       chooses to refresh a document, refresh.jsp is executed, then, when the prompt
                       have been filled, view.jsp is executed.


                       DocumentInstance doc =
                          reportEngines.getServiceFromStorageToken(Token);
                       if (doRefresh) doc.refresh(); //refresh first time only
                       Prompts prompts = doc.getPrompts();

                       //try to enter values and set prompts
                       String[] values = request.getParameterValues("PromptInput");
                       if ((values != null)&&(!(values[0].equals("")))){
                          prompts.getItem(0).enterValues(values);
                          doc.setPrompts(); //also sets getMustFillPrompts to false
                       }

                       //get user input
                       if (doc.getMustFillPrompts()) {
                          //build a form to get user input for the prompt
                          %>
                          <formname="PromptsForm"
                              action="refresh.jsp?Token=<%=doc.getStorageToken()%>"
                              method="post">
                              <input name="PromptInput" type="text"/>



    64   ReportEngine Developer Guide
Viewing Reports
                                                                              Handling prompts   4
                     <input name="Submit" type="submit" value="OK" />
                  </form>
                  <%
             }
             Response.sendRedirect("view.jsp?
                          Token="+doc.getStorageToken());
             Response.sendRedirect
             Note: This example does not show how to set how to set the Boolean
             variable doRefresh. One way to set this variable is to include an extra
             parameter in the query string for refresh.jsp; when DoRefresh is ”F”,
             doRefresh is false.


             The workflow for refresh.jsp for a document with one, simple prompt is
             therefore:
             1.   Get the DocumentInstance object for the document.
             2.   Get the Prompts collection for the document.
             3.   Try to enter values and set the Prompts for the document.
                  The first time refresh.jsp is executed, this step will not work as the user
                  has not yet entered a value for the Prompt.
             4.   Either:
                  •   if the Prompt is not filled, display a form to get a value from the user
                      This is the case the first time the file is executed.
                      The form’s action parameter is set to refresh.jsp so that this file is
                      executed when the user clicks the submit (OK) button.
                  •   otherwise, execute view.jsp to display the document’s reports

Using the storage token to retrieve a DocumentInstance
             When handling any kind of prompt, if you use the storage token to retrieve the
             document, you must be careful to use the correct token. The storage token
             changes after calls to DocumentInstance.refresh, and
             DocumentInstance.setPrompts.
             For more information on storage tokens see “Document state: storage tokens”
             on page 35.

Documents with many simple prompts
             To handle many simple prompt objects you can extend the workflow for a
             single simple prompt (page 64) with a form into which the user can enter
             values for all the prompts, and a script that handles these values.




                                                           ReportEngine Developer Guide 65
4   Viewing Reports
    Handling prompts


                       One problem this extension raises is that you need to dynamically set the
                       names of the inputs in the form that carry the values of each prompt. To do this
                       you can construct a name using a string constant, for example “PV”, and the
                       position of the prompt in the prompts collection.
                       Example: Dynamically creating input names
                       The following code fragment illustrates how to dynamically create names for
                       the inputs of a form.
                       <form name="PromptsForm" action="refresh.jsp" method="post">
                          <table><%
                              for (int i = 0; i < prompts.getCount(); i++) {
                              %><tr>
                                 <td>Enter a value for prompt number <%=i%>:</td>
                                 <td><input name=<%="PV"+i%> type="text"/></td>
                              </tr><%
                              }
                              %><tr><td>
                                 <input name="Submit" type="submit" value="OK" />
                              </tr></td>
                          </table>
                       </form>
                       Note: See the following example for an illustration of how to retrieve the
                       values in these inputs from the query string.
                       Example: Handling many, simple prompts
                       The following code fragment illustrates how to handle many, simple prompts
                       in a Web Intelligence or Desktop Intelligence document. (“Simple prompt”
                       means standard, text-entry prompts only.
                       The code in this example is from a page called refresh.jsp. When the user
                       chooses to refresh a document, refresh.jsp is executed, then, when the prompt
                       have been filled, view.jsp is executed.


                       <%
                       //get the document and its prompts
                       DocumentInstance doc =
                          reportEngine.getServiceFromStorageToken(token);
                       if (doRefresh) doc.refresh(); //refresh first time only
                       Prompts prompts = doc.getPrompts();

                       //try to get and enter values from the query string
                       // valuesSelected is true when the user completes the form
                       if (valuesSelected) {
                          for (int j = 0; j < prompts.getCount(); j++) {
                          //use (recreate) the parameter names created in the form
                              String[] values =
                                 request.getParameterValues(("PV" + j));
                              if ((values != null)&&(values.length != 0))
                                 prompts.getItem(j).enterValues(values);
                          }



    66   ReportEngine Developer Guide
Viewing Reports
                                                            Handling prompts    4
    doc.setPrompts(); //also sets getMustFillPrompts to false
}

//get user input
if (doc.getMustFillPrompts()) {
   //build a form to get user input for the prompt
   %>
   <form
          name="PromptsForm"
          action="refresh.jsp"
          method="post">
       <table>
          <%
          //add a row to the table for each prompt
          // the names of inputs are created dynamically
          for (int i = 0; i < prompts.getCount(); i++) {
          %>
              <tr>
              <td><%=prompts.getItem(i).getName()%></td>
              <td><input name=<%="PV"+i%> type="text"/></td>
              </tr>
          <%
          }
          //and add a row to the table for the submit button
          // DoRefresh and ValuesSelected help keep track of
          // where we are in the workflow
          %><tr><td>
              <input name="Token" type="hidden"
              value="<%=doc.getStorageToken()%>" />
              <input name="DoRefresh" type="hidden"
              value="false" />
              <input name="ValuesSelected" type="hidden"
              value="true" />
              <input name="Submit" type="submit" value="OK">
          </tr></td>
       </table>
   </form>
   <%
}
else //all prompts are filled and can now display the report
   response.sendRedirect("view.jsp?
              Token="+doc.getStorageToken());
%>
Note: A flag is now needed to determine if there are prompt values in the
query string. This example uses a hidden input in the form, ValuesSelected,
which is converted to a boolean when it is retrieved, however, you could also
use the first prompt parameter PV0 for this purpose.




                                           ReportEngine Developer Guide 67
4   Viewing Reports
    Handling prompts


    Prompts with simple lists of values
                       A List Of Values (Lov) is a set of values associated with a universe object.
                       These values are the corresponding values found for the object in the
                       database. The universe designer can edit this set as part of creating the object
                       in the universe. For example, the Quarter object could have the following list
                       of values {Q1, Q2, Q3, Q4}, and the Customer object could have a list of values
                       like this: {Adams, Arkwright, Baker, Bean, ..., Zane}. These values are defined
                       when the designer creates the object, but can be refreshed, to accommodate
                       changes in the database, automatically or manually. For information on
                       refreshing lists of values, see “Chunking long lists of values” on page 72.




                                                                              list of values for the Quarter object
                                                                              in the eFashion universe




                       Table 4-1 Viewing the list of values for the Quarter object in Universe Designer.
                       Handling prompts that contain Lov objects involves extending the workflow for
                       many, simple prompts (page 65). To do this you detect if the prompt object has
                       an associated Lov by calling Prompt.hasLOVIPrompt., if there is a list of
                       values for the prompt, get the values in the list with Lov.getAllValues, then
                       display them in the user input form, with Lov.getValues, as options of an
                       HTML select tag.
                       Note: Prompt.getLOV automatically refreshes the report, this can cause
                       problems with nested prompts which need to be handled. See “Handling
                       nested prompts” on page 72.
                       The select tag for the list uses the same dynamic input naming described in
                       “Dynamically creating input names” on page 66.
                       Example: Displaying a simple list of values
                       The following code fragment illustrates how to get the values of a Lov object
                       and display them in a form.
                       //get user input
                       if (doc.getMustFillPrompts()) {
                          //build a form to get user input for the prompt
                          %><form
                                 name="PromptsForm"
                                 action="refresh.jsp"
                                 method="post">



    68   ReportEngine Developer Guide
Viewing Reports
                                                                          Handling prompts    4
                  <table><%
                  for (int i = 0; i < prompts.getCount(); i++) {
                      Prompt prompt = prompts.getItem(i);
                      if (prompt.hasLOV()) {
                       Values lovValues =
                         prompt.getLOV().getAllValues();
                      %>
                         <tr>
                         <td><%=prompt.getName()%></td>
                         <td>
                         <select name=<%="PV"+i%> size=1>
                         <%
                         for (int k=0; k < lovValues.getCount(); k++){
                         %>
                         <option
                         value="<%=lovValues.getValue(k)%>">
                         <%=lovValues.getValue(k)%>
                         </option><%
                         }%>
                         </select>
                         </td>
                         </tr><%
                      }
                  }
                      %><tr><td>
                         <input name="Submit" type="submit" value="OK">
                      </tr></td>
                  </table>
               </form>
            <%}%>


            Note: The example “Handling multivalued prompts” on page 70 shows how
            to modify the select tag to handle multivalued prompts.


Constrained prompts
            A prompt is constrained if the answer must come from the prompt’s list of
            values (Lov). In Web Intelligence, users create constrained prompts by
            selecting Select Only From List when creating a prompt filter for a query.
            You can detect if a prompt is constrained with Prompt.isConstrained.

Multivalued prompts
            Until now we have considered only prompts that can have one value, however,
            some prompts can require several values before being filled. For example, the
            prompt, Store name in list, can have one or many responses before it is filled,
            whereas the prompt, Year equals, can have only one response.




                                                        ReportEngine Developer Guide 69
4   Viewing Reports
    Handling prompts


                       Note: For prompts that use the Between operator, such as, Sales revenue is
                       between X and Y, the user must specify both X and Y before the prompt can
                       be considered complete. However, Web Intelligence forms these kinds of
                       prompts as two separate prompts, you do not need to treat them as a
                       multivalued prompt.
                       To detect how many values the prompt requires use PromptType.getType. A
                       prompt can either be PromptType.Mono or PromptType.Multi.
                       Example: Handling multivalued prompts
                       The following code fragment illustrates how to modify the <select> tag of the
                       previous example (page 68) to handle multivalued prompts.
                       <td><%
                          if (prompt.getType() == PromptType.Mono) {%>
                              <select name=<%="PV"+i%> size=1><%
                          }
                          //multivalued LOV needs a different select statement
                          else {%>
                              <select name=<%="PV"+i%> multiple size=5><%
                          }
                          //add values in LOV to the select list
                          for (int k = 0; k < lovValues.getCount(); k++) { %>
                              <option value="<%=lovValues.getValue(k)%>">
                                 <%=lovValues.getValue(k)%>
                              </option><%
                          }%>
                          </select>
                       </td>


    Prompts with multicolumn lists of values
                       A universe designer can create a list of values that has many columns.
                       You detect a list of values with more than one column using
                       Values.isMultiColumns.
                       A multicolumn list of values is represented inReportEngine SDK as rows in a
                       table with the RowValues interface. To display the values in the list you use
                       Values.getRowValue to get a row in the table, and then
                       RowValue.getHeader and RowValue.getItem display the values in the list.
                       Note: Prompt.enterValues uses only the first value in each row to identify
                       the row. When the user selects a row, make sure you pass just the value in
                       the first column (index = 0) of the row to Prompt.enterValues. The example
                       below illustrates this.
                       Example: Handling multicolumn lists of values
                       The following code fragment illustrates how to display multicolumn lists of
                       values in the select block of the example on page 68.



    70   ReportEngine Developer Guide
Viewing Reports
                                                            Handling prompts   4
if (prompt.hasLOV()) { //display the list of values
   Values lovValues = prompt.getLOV().getAllValues();
   %><tr>
       <td><%=prompt.getName()%></td>
       <td><%
           if (lovValues.isMultiColumns()) {
       //MULTICOLUMN VALUES (1/2) display the column names
              String colNames = "";
              for (int m = 0;
              m < lovValues.getRowValue(0).getCount(); m ++)
              colNames = colNames + " | " +
              lovValues.getRowValue(0).getHeader(m);
              %><%=colNames%><br><%
           }
           //assume multivalue LOV
           %><select name=<%="PromptValue"+i%>
              multiple size=5>
           <%
           //get value and text for the option tag
           for (int k = 0; k < lovValues.getCount(); k++) {
              String value = lovValues.getValue(k);
              String valueText = value;
              if (lovValues.isMultiColumns()) {
                //MULTICOLUMN VALUES (2/2) option is a row
                RowValue row = lovValues.getRowValue(k);
               value = row.getItem(0);
               valueText = "";
                for (int n = 0;n < row.getCount(); n++) {
               //build a string to display the <option> tag
                if (n == 0) valueText = row.getItem(n);
                else valueText = valueText + " | " +
               row.getItem(n);
              }
           }
           %><option value="<%=value%>">
              <%=valueText%>
           </option><%
       }%>
       </select>
   </td>
   </tr>
}

Note: value and valueText are different in multicolumn lists of values. The
variable value contains just the first value in the row, which is passed to
Prompt.enterValues to fill the prompt, whereas valueText displays all the
values in the row.




                                          ReportEngine Developer Guide 71
4   Viewing Reports
    Handling prompts


    Chunking long lists of values
                       Some objects, for example Customer name, can have a very long list of
                       values. The Lov interface has methods that you can use to divide long lists
                       of values into “chunks” that are easier to display, and easier for the user to
                       browse:
                       •   Lov.getCurrentBatchIndex
                       •   Lov.getValues
                       •   Lov.getCurrentBatchName
                       •   Lov.setBatchSize

    Handling nested prompts
                       Sometimes a list of values contains its own prompts. A prompt in a list of values
                       is called a nested prompt. Nested prompts can be raised when a document
                       containing prompts is refreshed and the prompts have lists of values that
                       contain their own prompts.
                       If a list of values contains prompts, those prompts must be filled before you can
                       fill the prompts in the next level up.
                       Example: Order of filling a hierarchy of nested prompts
                       Consider the following set of prompts:
                       Select a town from the list: (prompt in query)
                          Select a state from the list: (prompt on list of towns)
                              Select a country from the list: (prompt on list of states)
                       Each prompt qualifies the one above it in the hierarchy; the country must be
                       defined before a state can be defined and, similarly, a state must be defined
                       before a town can be defined.


                       You use Lov.mustFillNestedPrompts to detect if a list of values contains
                       its own prompts, then Lov.getNestedPrompts, Prompt.enterValues
                       IPrompt.EnterValues and Lov.setNestedPrompts to enter values for
                       and set the nested prompts.
                       Example: Handling nested prompts
                       The following code fragment illustrates the recommended method for handling
                       nested prompts. In this example, prompts and nested prompts are handled by
                       the recursive function fillPrompts.
                       //get the document and its prompts
                       DocumentInstance doc =
                          re.getDocumentFromStorageToken(token);
                       if (doRefresh) doc.refresh(); //refresh first time only
                       Prompts prompts = doc.getPrompts();
                       //if there are prompts, fill them
                       if (doc.getMustFillPrompts()) {


    72   ReportEngine Developer Guide
Viewing Reports
                                                                            Handling prompts    4
                  this.fillPrompts (prompts, null);
                  doc.setPrompts();
              }
              else //all prompts are filled and can now display the report
                 response.sendRedirect("view.jsp?
                           Token="+doc.getStorageToken());
              //FUNCTION - fill prompts and handle nested prompts

              public void fillPrompts (Prompts pmts, Lov parentLOV) {
              //pmts is the set of prompts or nested prompts to be filled
              //parentLOV is a LOV for which there are unfilled nested
                 prompts
                 for (int i = 0; i < pmts.getCount(); i++) {
                     Lov lov = pmts.getItem(i).getLOV();
                     if (lov.mustFillNestedPrompts()) {
                        Prompts nestedPrompts = lov.getNestedPrompts();
                        fillPrompts (nestedPrompts , lov);
                     }
                     //get user input for pmts
                     //enter values for pmts
                 }
                 if (parentLOV != null) parentLOV.setNestedPrompts();
              }
              Note: You can use the methods described in “Prompts with simple lists of
              values” on page 68 to get the user input and enter the values for nested
              prompts.


Refreshing a list of values
              If the document contains lists of values with prompts, the prompts on the lists
              of values must be filled every time the document is refreshed, however, to
              make sure that the lists are up to date, you can use Lov.refresh to provide
              a “Refresh List” button so that the user can update the list manually.
              Note: This process is independent of the document refresh mechanism.
              After calling Lov.refresh, the next time you call Lov.getValues or
              Lov.getAllValues, the list of values will be refreshed.

Refreshing a list of values containing nested prompts
              If you provide a manual refresh option, you can handle any nested prompts
              contained in the list of values with the fillPrompts function described in the
              example “Handling nested prompts” on page 72.
              Example: Refreshing a list of values containing nested prompts
              The following code fragment shows how to use the fillPrompts function
              described in the example “Handling nested prompts” on page 72 to handle
              nested prompts raised when the list of values is refreshed manually.



                                                          ReportEngine Developer Guide 73
4   Viewing Reports
    Displaying a report map


                     //get and display the LOV
                     //if the user clicks "Refresh List"
                     lov.refresh();
                     Prompts nestedPmts = lov.getNestedPrompts();
                     this.fillPrompts (nestedPmts, lov);


    Handling context prompts
                     Universe designers define context prompts in universes to ensure users
                     retrieve the appropriate data when there is more than one way to get the
                     results of a query. For more information about defining contexts see
                     Designer’s Guide.
                     The classes and methods, and hence the process, for filling a context prompt
                     is similar to that for filling many, simple prompts (page 65). The contexts in a
                     document are represented by the Contexts collection, and you can detect if
                     a document has contexts to fill with
                     DocumentInstance.getMustFillContexts.
                     To fill a context prompt:
                     If contexts must be filled,
                     1.   Get contexts.
                     2.   Display the possible values for each context and get the user’s response.
                     3.   Enter the values for the context provided by the user.
                     4.   Set the contexts.
                     5.   View the report.
                          “Viewing reports” on page 60 explains how to view reports.


    Displaying a report map
                     A ReportMap is a representation of the reports and report sections in a Web
                     Intelligence or Desktop Intelligence document.
                     There are two modes for calculating the contents of a report map: incremental
                     and non-incremental. In incremental mode only the requested information is
                     calculated, and in non-incremental mode the whole report map is calculated in
                     one step.
                     To get the report map for a document, call
                     DocumentInstance.getReportMap.
                     Example: Traversing the report map for a Web Intelligence document
                     The following code fragment traverses the following report structure and gets
                     a section as DHTML.


    74   ReportEngine Developer Guide
Viewing Reports
                                                   Displaying a report map   4

                                        Section1


                          Report1       Section2         Section1
  map.getStructure()
                          Report2                        Section2


                          Report3       Section1


                       ReportMapNodes   Section2


      = ReportMapNode


// Get the ReportMap from the document instance
ReportMap map = doc.getReportMap();
//point to the root node of the structure
ReportMapNodes root = map.getStructure();
// Get the number of reports in the document
// There are three in this case: Report1, Report2, and
   Report3
int count = root.getChildCount();
// Get the first report
ReportMapNode report1 = root.getChildAt(0);
// Get the name of the report (Report1)
String reportName = report1.getName();
// Get the report path (0)
String reportPath = report1.getPath();
// Check if the report contains sections (true in this case)
boolean leaf = report1.isLeaf();
// Get the number of sections in the report
// There are two in this case: Section1, Section2
int section_count = report1.getChildCount();
// Get the first section
ReportMapNode section1 =
   (ReportMapNode)report1.getChildAt(0);
// Get the section name (Section1)
String sectionName = section1.getName();
// Get the section path (0/0)
String sectionPath = section1.getPath();
// Get the DHTML page associated with this section
Report report = doc.setPath(sectionPath);
HTMLView view = report.getView(OutputFormatType.DHTML);




                                        ReportEngine Developer Guide 75
4   Viewing Reports
    Displaying a report map




    76   ReportEngine Developer Guide
ReportEngine Developer Guide


Drilling in Web Intelligence
Reports




                               chapter
5   Drilling in Web Intelligence Reports
    Overview



    Overview
                      Drilling is one of the key features of Web Intelligence documents, helping users
                      analyze document data.
                      This chapter discusses how to provide drilling facilities for Web Intelligence
                      documents.
                      Note: you cannot drill in a Desktop Intelligence document.


    Introduction to drilling
                      Drilling is a way for a user to control the amount of detail in a report.
                      Universe designers create hierarchies of dimensions when they create
                      universes, for example Country, State, City, Zip Code, Street. When users
                      view reports, they can adjust the amount of detail in the reports by entering drill
                      mode and drilling up or down according to the dimension hierarchies (often
                      called “drill hierarchies).
                      Note: Depending on their user rights, some users might not have access to
                      the drilling functions.
                      Users set the scope of analysis to control how much data Web Intelligence
                      includes in the DataProvider(cube) it creates when a query is executed.
                      When a user executes a query, Web Intelligence retrieves data for the
                      dimensions in the query, but also for the dimensions that the user has included
                      in the scope of analysis. This means that when a user drills through a
                      dimension hierarchy the information for the new report is in the
                      DataProvider, and it is not necessary to execute a new query to display the
                      drilled report. See also “Drilling out of scope: the scope of analysis” on
                      page 80.
                      Note: The user executing the query might not be the user that set the scope
                      of analysis.
                      You use ReportEngine SDK to drill in Web Intelligence reports.

    The drilling process
                      To provide users with a drill function, implement the following process:
                      1.   User requests a drill operation by clicking on a drill link in a report.
                           The request contains information about the drill operation. For example,
                           the name of the script that will handle the request, from which dimension
                           the drill starts, and to which dimension it goes.




    78   ReportEngine Developer Guide
Drilling in Web Intelligence Reports
                                                                             Introduction to drilling   5
              2.    The script defines the drill operation by initializing the document’s drilling
                    objects with the information passed in the drill request.
              3.    The script instructs Web Intelligence to generate the HTML for the drilled
                    report.
                    Web Intelligence uses the information in the document’s drilling classes
                    to generate the drilled view.
              4.    The script displays the drilled view generated by Web Intelligence.
              5.    Repeat steps 2 to 4 for each request for a drill operation.

                                                                                       1

                                                                               st
                                                                             ue
                                                                          eq
                                                                      ll r
                   Drill Option                                 dri



                                      2 Define drill            dri
                                                                   ll   re q
                                                                            ue
                                                                               s   t
                                      3 Generate DHTML
                    Drill Path                                                         5
                                         View report   4




              Table 5-1 The process you need to implement to provide a drilling function

Defining the drill operation
              You can only define drill operations for drillable documents. A document is
              considered drillable if the dimensions used to form the query are part of a
              dimension hierarchy.
              Defining the drill operation involves:
              •     getting the parameters of the drill request
              •     defining the query string parameters
              •     entering and leaving drill mode
              •     setting the drill path



                                                             ReportEngine Developer Guide 79
5   Drilling in Web Intelligence Reports
    Drilling in reports


                      The details of how you define the drill operation depend on the type of report.
                      For information on defining the drill operation for Web Intelligence reports see
                      page 81.

    Generating the HTML and viewing a drilled report
                      This step in the drilling process involves generating the HTML for the report
                      using the drill operation you have defined. Once you have done this you can
                      view the report as HTML using the normal workflows.

    Drilling out of scope: the scope of analysis
                      An out of scope drill is one that goes up or down to a dimension that is not in
                      the DataProvider. To fulfill this request the query must be reformed and
                      rerun to retrieve the requested data.
                      You can handle out of scope drills manually or transparently. How you
                      manually handle out of scope drills depends on the type of report, however the
                      mechanism for transparently handling out of scope drills does not depend on
                      the report type.
                      For information on manually handling out of scope drills for Web Intelligence
                      reports see page 87.

    Transparent Drill Outside of Cube
                      The Web Intelligence facility for automatically handling out of scope drill
                      requests is called Transparent Drill Outside of Cube. When this is functioning,
                      the scope of analysis of the Query is automatically reset to incorporate the data
                      for the requested dimension.
                      Supervisors can control a user’s access to this facility using Supervisor.

    Drill hierarchies
                      Hierarchies contain dimensions and are defined by universe designers. You
                      can see drill hierarchies in the Report Panel.
                      A dimension contains a list of values. When a value is selected from the list, it
                      acts as a dimension filter.


    Drilling in reports
                      To provide drilling functions in Web Intelligence reports you can implement the
                      process described in “The drilling process” on page 78, or use the drill bar to
                      filter the query.




    80   ReportEngine Developer Guide
Drilling in Web Intelligence Reports
                                                                                  Drilling in reports   5
Drilling information
              You can access drilling information by examining the contents of the universe
              (the drill hierarchies and dimensions), or by examining the drill bar.
              Drill hierarchies defined in a universe
              Use Report.getNamedInterface(“DrillInfo”) get aDrillInfo
              instance.


              To get the DrillHierarchies used in the report, use
              DrillInfo.getDrillHierarchies. A hierarchy is used if one of its
              dimensions is included in the query for the report.
              To get the dimensions and details that are not included in a hierarchy but are
              used in the report, use DrillInfo.getFreeDimensions.
              The DrillBlock object gets the drill hierarchies and dimensions for just one
              block (table or graph) in the report.
              Drill bar
              DrillBar exposes drill and report filters, and specific drill objects added by
              the user. A drill object can be a dimension, or a detail.

Defining the drill operation
              A drill operation is defined in terms of the drill path. The drill path is represented
              in ReportEngine SDK by the DrillPath interface, and consists of a set of
              parameters such as the IDs of the objects (dimensions) from and to which the
              user is drilling. Defining the drill operation, therefore, involves setting the
              parameters of the drill path object.
              To define the drill operation:
              1.   Enter drill mode.
              2.   Define the query string parameters, if required.
              3.   Get the parameters of the drill request.
              4.   Set the drill path.

Entering and leaving drill mode
              You need to put Web Intelligence into a special mode so that it can perform the
              drilling functions. There are two modes: ReportMode.Viewing and
              ReportMode.Analysis.
              Calling DrillInfo.beginDrill puts a report in ReportMode.Analysis
              (drill) mode. Calling DrillInfo.endDrill stops the drill session and puts a
              report in ReportMode.Viewing mode.


                                                              ReportEngine Developer Guide 81
5   Drilling in Web Intelligence Reports
    Drilling in reports


    Defining the query string parameters
                      In Web Intelligence users drill with hyperlinks and a popup menu generated by
                      Web Intelligence using Javascript functions and style sheets (see “Generating
                      the HTML and viewing a drilled report” on page 80).
                      You can redefine the query string parameters with the DrillOption
                      interface, then use the new names to retrieve the details of the user’s drill
                      request and, hence, to set the DrillPath.
                      Note: You cannot change the name and path of the image used to indicate
                      the drill up hyperlinks. This is always ApplicationName/images/cdz/drillup.gif
                      Example: Defining the query string parameters
                      The following code fragment shows how to define the query string parameters
                      used to pass drill information to the Javascript functions that generate the
                      hyperlinks and popup menu, which provide the user with drilling functions.
                      //set up the query string parameters used for drilling
                      DrillOption option = info.getDrillOption();
                      option.setBlockHolder("Block");
                      option.setBlockSynchronized(true);
                      option.setCallBackScript("drillHandler.jsp?ReportIdx=0”);
                      option.setCallBackFrame("_self");
                      option.setDrillActionHolder("Action");
                      option.setToHolder("To");
                      option.setFromHolder("From");
                      option.setFilterHolder("Filter");
                      option.setHierarchyHolder("Hierarchy");
                      option.setStorageTokenHolder("Token");

                      Notice that you can add your own query string parameters to the call back
                      script definition. Depending on the architecture of your application, and how
                      you manage storage tokens (document state) you might need to include the
                      storage token in the call back script definition. If you do this, remember that
                      drilling methods such as beginDrill and executeDrill generate new
                      tokens for the document.

    Getting the parameters of the drill request
                      To get the parameters of the drill request use request.getParameter and
                      request.getParameterValues. For example:
                      String token = request.getParameter("Token");
                      String block = request.getParameter("Block");
                      String action = request.getParameter("Action");
                      String[] to = request.getParameterValues("To");
                      String[] from = request.getParameterValues("From");
                      String[] hierarchy =
                         request.getParameterValues("Hierarchy");
                      String[] filter = request.getParameterValues("Filter");




    82   ReportEngine Developer Guide
Drilling in Web Intelligence Reports
                                                                                    Drilling in reports   5
Setting the drill path
              The DrillPath defines the drill operation. To set the drill path:
              1.    Get the DrillPath object.
              2.    Set the drill action.
                    See “Setting the action: up, down, by, or slice” on page 83 below.
              3.    Set the block id.
              4.    Set the object id of the drill to element.
              5.    Set the object id and filter of the drill from element.
              Setting the action: up, down, by, or slice
              A user’s drill actions are classified by how they move through the drill
              hierarchies.

               Drill action Resulting report engine action
               Up               The report engine replaces the current object with its parent in
                                the drill hierarchy.
               Down             The report engine replaces the current object with its child in the
                                drill hierarchy.
               By               The report engine replaces the current object with an object that
                                is not adjacent to it in the drill hierarchy.
               Slice            The report engine adds or removes the filtered values.

                       hierarchy 1                           hierarchy 2
                                dimension 1                            dimension 5
                         down                                      up
                                        dimension 2                         dimension 6
                                                             by
                                              dimension 3                        dimension 7
                          down or by
                                                   dimension 4      slice

              Table 5-2 Different drill actions
              You set the drill action with DrillPath.setAction.
              The actions are enumerated by DrillActionType.
              Setting the from and to parameters
              To set the from and to parameters of the drill, you define the elements of the
              drill. The elements of the drill are the dimensions involved in the drill action and
              are represented by the DrillElements interface. There is a DrillElements
              object for the to and for the from dimensions. Individual from and to elements
              are represented by DrillFromElement and DrillToElement.




                                                                 ReportEngine Developer Guide 83
5   Drilling in Web Intelligence Reports
    Drilling in reports


                      For each drill operation:
                      1.   Get the drill from and to elements with DrillPath.getTo and
                           DrillPath.getFrom.
                      2.   Add drill elements to each collection.
                      3.   Set the object IDs of each drill element using the values you retrieve from
                           the query string.
                      4.   For each from element, set the filter, if any.
                      Note: The filter remains for drill-by actions between dimensions in the same
                      hierarchy. However for drill-up actions the filter is removed.
                      Note: For example, in the Time Period hierarchy, if you drill down to Quarters
                      from Year = 2003, all the quarters for 2003 are displayed, then if you drill by
                      Year, only Year= 2003 is displayed. However if you drill up from Quarters to
                      Year, all the values for Years are displayed.
                      Example: Setting the drill path
                      The following code fragment shows how to set the values of the drill path. The
                      parameters of the drill (action, from, to, block) are retrieved as described in
                      “Getting the parameters of the drill request” on page 82.
                      DrillPath drill = info.getDrillPath();
                      //set the ACTION
                      if (action.equals("down"))
                         drill.setAction(DrillActionType.DOWN);
                      else if (action.equals("up"))
                         drill.setAction(DrillActionType.UP);
                      else if (action.equals("slice"))
                         drill.setAction(DrillActionType.SLICE);
                      else if (action.equals("by"))
                         drill.setAction(DrillActionType.BY);
                      //set the BLOCK
                      drill.setBlockID(block);
                      //set the TO drill elements
                      if (to.length > 0) {
                         DrillElements toElements = drill.getTo();
                         for (int j = 0;j < to.length; j++) {
                             DrillToElement toElement =
                                    (DrillToElement) toElements.add();
                             toElement.setObjectID(to[j]);
                         }
                      }
                      //set the FROM drill elements
                      if (from.length > 0) {
                         DrillElements fromElements = drill.getFrom();
                         for (int k = 0; k < from.length; k++) {
                             DrillFromElement fromElement =
                                    (DrillFromElement) fromElements.add();
                             fromElement.setObjectID(from[k]);
                             if ((filter != null) && (filter.length > 0))
                                    fromElement.setFilter(filter[0]);



    84   ReportEngine Developer Guide
Drilling in Web Intelligence Reports
                                                                               Drilling in reports   5
                  }
              }

              This example assumes that there is only one value in the array filter —
              fromElement.setFilter(filter[0]). This is true for simple drilling,
              however, to handle more sophisticated drilling you need to use all the values
              in the array of filters. Also, in the part that sets the filter, you can add the
              condition
              ‘if !action.equals(“up“)’ since there is no filtering in a drill-up operation,
              however, if you set a filter for a drill-up operation, it is ignored.


Generating the HTML and viewing a drilled report
              To generate the HTML for the report execute the drill with
              DrillInfo.executeDrill, then view the generated HTML using
              HTMLView.getContent(see “Displaying the drilled report” on page 86. See
              also “Viewing an individual report in DHTML” on page 62).
              In drill mode (ReportMode.Analysis) when you call
              Report.getView(OutputFormatType.DHTML) Web Intelligence generates
              DHTML that uses scripts and style sheets to provide the drilling interface.

Copying the Java script files for drilling
              The Java script files used to create the drilling user interface are stored in
              /businessobjects/enterprise11/desktoplaunch/viewers/cdz/. Copy the
              following files from this directory to the same directory as your script that
              displays the DHTML view of the report.
              •   bomenuIE.js
              •   browserDetection.js
              •   drillcontext.js
              •   drillcontextDom.js
              •   /language/language/message.js
                  Where language is the language of the messages.
              These scripts use the styles defined in bomenu.css and the .gif files in the
              images folder. To get these files, copy the following to the directory containing
              the copied Java script files:




                                                           ReportEngine Developer Guide 85
5   Drilling in Web Intelligence Reports
    Drilling in reports


                      •   /businessobjects/enterprise11/desktoplaunch/viewers/cdz/style/
                          skin_name/bomenu.css
                           skin_name is one of: skin_default, skin_corporate, or skin_coloredline.
                           The fonts used in bomenu.css do not include some special characters. To
                           display characters such as the yen symbol (¥) use bomenu_fe.css.
                      •   /businessobjects/enterprise11/desktoplaunch/viewers/cdz/images/

    Referencing the Javascript files for drilling
                      The DHTML generated by Report.getView references these files and you need
                      to include this in your header with HTMLView.getString("head", false).
                      For an example of how to do this, see “Displaying the drilled report” on
                      page 86.

    Displaying the drilled report
                      To display the drilled report, call HTMLView.getContent.
                      Alternatively you can call HTMLView.getString() which retrieves both the
                      appropriate HTML header and the drilled report, however, it means you can't
                      add supplementary HTML to the page.
                      Example: Displaying the drilled report
                      The following code fragment illustrates how to display a report after executing
                      the drill.
                      <%
                      HTMLView htmlView = null;
                      htmlView = (HTMLView) rep.getView(OutputFormatType.DHTML);
                      String htmlHeader = htmlView.getStringPart("head", false);
                      %>
                      <html>
                         <!-- DRAW HEADER -->
                         <head>
                             <link rel="stylesheet"
                                    type="text/css" href="style/bomenu.css">
                             <%=htmlHeader%>
                         </head>
                             <!-- DRAW REPORT-->
                             <%=htmlView.getStringPart("body", true)%>
                      </html>




    86   ReportEngine Developer Guide
Drilling in Web Intelligence Reports
                                                                                  Drilling in reports   5
Manually handling out of scope drill requests
               Once you have set the DrillTo and DrillFrom elements you can detect
               if a drill dimension is not in scope with DrillDimension.isInScope. If the
               defined drill operation contains out of scope dimensions with
               DrillInfo.willGoOutOfScope.
               If the DrillDimension is outside the scope of analysis you can manually
               extend the scope of analysis with DrillInfo.extendScopeOfAnalysis.
               This method returns a DrillElements collection to which you can add the
               extra drill dimensions that the user wants to include in the analysis.
               You commit the changes you make to the scope of analysis by calling
               DrillInfo.executeDrill.
               If you want to add a query filter to the extended scope of analysis, use
               DrillInfo.addQueryConditions. This returns a DrillElements
               collection to which you can add the ID of the filter dimensions and the
               associated filter values. You commit this change with
               DrillInfo.executeDrill. See also, “Adding query conditions using the drill
               bar” on page 88.

Adding objects that have prompts
               If you extend the scope with an object that contains a prompt in its universe
               definition, you need to fill the prompts it raises before you execute the drill. See
               “Handling prompts” on page 64 to find out how to do this.

Filtering with a drill bar
               The DrillBar object exposes the drill filters and specific objects added by
               the user.
               By default, the drill bar is initialized with the report filter, but it can be
               customized by the user to add or remove drill objects. Drill objects can be
               dimensions, or details.
               In the example below, the DrillBar object contains three objects, the
               Country dimension filtered on the US value, the Resort dimension filtered on
               the Bahamas Beach value, and the unfiltered Service Line object.




               You access the drill bar using DrillInfo.getDrillBar, and you add and
               remove objects to and from the drill bar with DrillBar.add and
               Drillbar.remove.




                                                             ReportEngine Developer Guide 87
5   Drilling in Web Intelligence Reports
    Drilling in reports


                      Note: When you remove an object from the drill bar, it is automatically
                      removed from the report filter.

    Adding query conditions using the drill bar
                      You can use the filters in the drill bar to add query conditions when extending
                      the scope of analysis. For example, if the drill bar has the filter Country = US,
                      when the scope is extended you can use this object to form a query condition
                      before executing the SQL. This limits the amount of information returned into
                      the cube to results for Country = US, and is more rapid than retrieving the
                      results for all the values of Country.
                      The filters set in the drill bar can affect other result objects. For example, if you
                      set the filter Month = February, the results for Quarter are automatically limited
                      to Quarter = Q1; you cannot view the results for Month = February and Quarter
                      = Q3.
                      Note: Changing the query affects all the reports in the document. If you add a
                      condition to the query, information in other reports in the document might
                      change.
                      For more information see “Manually handling out of scope drill requests” on
                      page 87.

    Taking a snapshot of a drill
                      You can use DrillInfo.snapshot to put aside a drilled view and continue
                      drilling. This method adds a report containing the current view to the
                      document’s report list and report map.




    88   ReportEngine Developer Guide
ReportEngine Developer Guide


Building and Editing
Data Providers




                               chapter
6   Building and Editing Data Providers
    Overview



    Overview
                     A data provider holds information about a query. Using a data provider you can
                     get the SQL for a query, retrieve the data returned when the query is executed,
                     and explore the data source (universe) through which the data was retrieved.
                     This chapter explains how to use ReportEngine SDK to build data providers
                     and edit queries for Web Intelligence and Desktop Intelligence reports.


    Data providers
                     A data provider has two parts: a query and a data source.

    The query
                     The query part of a data provider defines the data to be retrieved. The query
                     is expressed in terms of the data source objects (universe objects, also known
                     as result objects) of interest and conditions which restrict the data retrieved.
                     The query can also have an associated scope of analysis which includes more
                     data in the retrieved microcube than the query requires. This helps when you
                     are providing drilling features (see “Scope of analysis” on page 97 and “The
                     drilling process” on page 78).
                     The query of a data provider is exposed in ReportEngine through the Query
                     and Scope objects. Conditions on queries are expressed as a syntax tree in
                     which conditions and operators (for example AND, and EQUAL TO) are nodes
                     in the tree. This syntax tree is created with the ConditionContainer set of
                     classes. See “Conditions” on page 98.

    The data source
                     The data source of a data provider gives you access to the universe used to
                     define the query. ReportEngine SDK exposes the following universe elements:
                     •    class
                     •    hierarchy
                     •    dimension
                     •    measure
                     •    detail
                     •    predefined condition




    90   ReportEngine Developer Guide
Building and Editing Data Providers
                                                                     Building a data provider   6
             Using the classes that expose these universe elements, you can present the
             contents of a universe to users as classes and objects for query editing, or as
             drill hierarchies in a drill bar.
             Use the following classes to explore a universe:
             •   DataSource (universe)
             •   DataSourceObjects (classes and hierarchies in the universe)
             •   DataSourceObject (elements of the universe)
                 Universe elements can be classes, conditions, dimensions, details,
                 measures, or hierarchies.
                 DataSourceObject is a specialization of the TreeNode class.
             You use DataSourceObject to create and edit the query, but after you
             execute the query the objects are stored in the document's dictionary as
             ReportExpression objects.


Building a data provider
             You can build a data provider by:
             •   Integrating the Web Intelligence Java Report Panel into your application.
             •   Building a data provider manually with ReportEngine SDK.



Integrating the Web Intelligence Java Report Panel into your application
             The Web Intelligence Java Report Panel is the standard method for users to
             create data providers and edit queries.




                                                         ReportEngine Developer Guide 91
6   Building and Editing Data Providers
    Building a data provider




                     Table 6-1 The Web Intelligence Java Report Panel
                     Note: This applet is different from previous releases of Web Intelligence.

    Launching the Web Intelligence Java Report Panel
                     You use the <applet> or <object> tag to declare the applet, and the <param>
                     tag to specify the applet’s parameters. All parameters are of the type
                     java.lang.String.




    92   ReportEngine Developer Guide
Building and Editing Data Providers
                                                 Building a data provider   6
Parameters            Value(s)                  Description
Applet parameters
code                  “com.businessobjects.w The path to the
                      p.tc.TCMain”           applet.
useslibrary           “Web Intelligence          The name of the
                      Report Panel”              applet.
useslibrarycodebase   “/webiApplet/              The path to the
                      ThinCadenza.jar”           archive containing the
                                                 applet
HelpRoot              -                          The path to the online
                                                 help.
Lang                  “en”; “jp”                 The language of the
                                                 user interface.
Server parameters
Server                -                          The name of the
                                                 server from which the
                                                 applet is downloaded.
Isapi                 “/servlet/                 The path to the
                      com.businessobjects.cd     servlet through which
                      zlet.                      the server and the
                      CadenzaServlet”            browser
                                                 communicate.
Port                  default is “8080”          The port used for the
                                                 application server
CdzSession            use the string returned    The session identifier
                      by ReportEngine.           for the open
                      getServerInstance          document.
Document parameters
Token                 use the string returned    The storage token for
                      by DocumentInstance.       the document.
                      getStorageToken when
                      editing an open
                      document
RepoType              “corporate”; “inbox”;      The type of the
                      “personal”.                repository in which
                                                 the document is
                                                 stored.
DocumentID            -                          The id of the
                                                 document.



                                    ReportEngine Developer Guide 93
6   Building and Editing Data Providers
    Building a data provider


                      Parameters                  Value(s)                   Description
                      DocumentName                 -                         The name of the
                                                                             document.
                      OpenFirstClassOfUniverse -                             If present, the applet
                                                                             automatically opens
                                                                             the first class of the
                                                                             universe.
                      Data source parameters
                      UniverseID                   “UnivCUID=universe        The id of the universe
                                                   cid value”                on which the query
                                                                             will be run.
                     You can use the implicit request object (javax.servlet.http.HttpServletRequest)
                     to get the values for some of these parameters. For example, you can use
                     request.getServerName and request.getServerPort to populate the Server
                     and Port parameters.
                     Note: Some parameters are optional depending on what you are doing with
                     the applet. For example, if you are creating a new document, you do not need
                     to provide a storage token.
                     Example: Launching the Java Report Panel
                     The following example shows functions that use BusinessObjects Enterprise
                     SDK to recover a universe object from a valid ID. This Universe can be used
                     to supply information necessary to start the Java Report Panel
                     <%!
                     IInfoObject getUniverse(IInfoStore iStore, String ID){
                         IInfoObjects universes = null;
                         IInfoObject universe = null;
                         try{
                            String sQuery = "SELECT SI_CUID, SI_NAME FROM”
                                   + “ CI_APPOBJECTS WHERE SI_ID = " + ID
                                   + " AND SI_KIND = '"+ CeKind.UNIVERSE +"'";
                            universes = (IInfoObjects) iStore.query(sQuery);
                            if(universes.size() > 0)
                                universe = (IInfoObject)universes.get(0);
                         }catch(Exception e){
                            universe = null;
                         }
                         return universe;
                     }
                     %>
                     // The following script retrieves all necessary
                     // parameters and then launches the Web Intelligence Java
                     // Report Panel.
                     <%
                     IInfoStore iStore = (IInfoStore)
                         session.getAttribute("InfoStore");



    94   ReportEngine Developer Guide
Building and Editing Data Providers
                                             Building a data provider   6
ReportEngine wiRepEngine = (ReportEngine)
   session.getAttribute("ReportEngine");
String ID = request.getParameter("uID");
universe = getUniverse(iStore, ID);
if (universe != null){
   String currPath = request.getServletPath();
   String contextPath = request.getContextPath();
   String serverName = request.getServerName();
   int serverPort = request.getServerPort();

   currPath = currPath.substring(
             0, currPath.lastIndexOf( '/' ) + 1 );
   currPath = contextPath + currPath;
   String instanceID = wiRepEngine.createServerInstance();
   String strWISession =
      instanceID.substring(0,instanceID.indexOf(","));
%>
<APPLET CODE="com.businessobjects.wp.tc.TCMain"
   CODEBASE="<%= contextPath %>/webiApplet/"
   ARCHIVE="ThinCadenza.jar" style="
          width: 100%; height: 100%;">
<PARAM NAME=CODE VALUE="com.businessobjects.wp.tc.TCMain" >
<PARAM NAME=CODEBASE VALUE="<%= contextPath %>/webiApplet/">
<PARAM NAME=ARCHIVE VALUE="ThinCadenza.jar" >
<PARAM NAME="type"
       VALUE="application/x-java-applet;version=1.4">
<PARAM NAME="Isapi"
       VALUE="<%= contextPath %>/CadenzaServlet"></PARAM>
<PARAM NAME="Server" VALUE="<%= serverName %>"></PARAM>
<PARAM NAME="Protocol" VALUE="http"></PARAM>
<PARAM NAME="Port" VALUE="<%= serverPort %>"></PARAM>
<PARAM NAME="Type" VALUE="signed"></PARAM>
<PARAM NAME="WebiSession"
       VALUE="<%= strWISession %>"></PARAM>
<PARAM NAME="CdzSession" VALUE="<%= instanceID %>"></PARAM>
<PARAM NAME="DocumentID" VALUE=""></PARAM>
<PARAM NAME="UniverseID"
       VALUE="UnivCUID=<%=universe.getCUID()%>"></PARAM>
<PARAM NAME="bRobot" VALUE="false"></PARAM>
<PARAM NAME="bTraceInLogFile" VALUE="false"></PARAM>
<PARAM NAME="HelpRoot"
       VALUE="<%= contextPath.substring(1) %>"></PARAM>
<PARAM NAME="SaveAs"
       VALUE="<%= contextPath %>save.jsp"></PARAM>
<PARAM NAME="Lang"
       VALUE="<%= request.getLocale().getLanguage() %>"
              ></param>
</APPLET>




                                 ReportEngine Developer Guide 95
6   Building and Editing Data Providers
    Building a data provider


    Building a data provider manually
                     When you create a new document instance, Web Intelligence automatically
                     creates an empty data provider for the document. The data provider has a data
                     source and an empty query object. Building a data provider consists in
                     populating the query object with the data source objects in which you are
                     interested.
                     To build a data provider:
                     1.   Get the collection of data providers for the document.
                     2.   Get the universe elements in which you are interested.
                     3.   Get the query for the data provider.
                     4.   Add result objects.
                     5.   Add condition objects (optional).
                     6.   Execute the query.
                     Example: Building a data provider
                     The following code fragment illustrates how to populate the query object of a
                     data provider.
                     //select a universe ==> sID
                     ...
                     //create a new document instance
                     DocumentInstance doc = reportEngine.newDocument(sID);
                     DataProviders dps = doc.getDataProviders();
                     // Retrieve the 1st data provider
                     DataProvider dp = dps.getItem(0);
                     // Retrieve the universe objects
                     DataSource ds = dp.getDataSource ();
                     DataSourceObject city =
                                  ds.getClasses().getChildByName("city");
                     DataSourceObject year =
                                  ds.getClasses().getChildByName ("year");
                     DataSourceObject sales =
                                  ds.getClasses().getChildByName ("sales");
                     Query q = dp.getQuery();
                     // Add result objects to the query
                     q.addResultObject (city);
                     q.addResultObject (year);
                     q.addResultObject (sales);
                     // Run the query: execute the query and fetch the data
                     dp.runQuery();


    Editing queries
                     A query is represented by the Query object and has the following parts:
                     •    a list of result objects




    96   ReportEngine Developer Guide
Building and Editing Data Providers
                                                                        Building a data provider   6
             •   a scope of analysis that defines the amount of data available in the cube
             •   conditions that restrict the amount of data retrieved from the data source
             To get the query for a data provider, use DataProvider.getQuery.

Result objects
             A result object is a class or an object in a universe. Including a result object in
             the query is the same as dragging and dropping an object into the Results area
             of the Query Panel of the Web Intelligence Java Report Panel. When you
             execute the query, the result object is added to the report dictionary (as a
             report expression, see “Block structure: axes and report expressions” on
             page 108) and is available for editing reports.
             To add a result object to the query, use Query.addResultObject.
             To remove a result object from the query, use Query.removeResultObject.

Scope of analysis
             The scope of analysis is a feature that enables you to include more information
             in a cube than the query requires. This is very helpful in drilling as it is avoids
             modifying the query for every drill operation. See “Drilling in reports” on
             page 80.
             The scope of analysis is defined in terms of the scope level and is represented
             by the Scope interface. The scope level specifies how many objects of a class
             hierarchy are retrieved when you run the query. The scope level can be
             LEVEL_1, LEVEL_2, LEVEL_3, or CUSTOM.
             A scope level of LEVEL_1 indicates that just the result object specified in the
             query is retrieved. A scope level of LEVEL_3 indicates that the first three
             objects in the class hierarchy, starting with the result objects specified in the
             query, will be included in the retrieved results.
             If you modify the elements in the scope of analysis, Web Intelligence changes
             the scope level accordingly. If you create a scope of analysis that does not
             match an existing hierarchy, for example, if you remove the Quarter object
             from the scope of analysis so that a drill on the Year goes to the Month object,
             the scope level is set to CUSTOM, however, if you remove the third level from
             a LEVEL_3 scope of analysis, Web Intelligence sets the scope level to
             LEVEL_2.
             To get the scope of analysis for a query, use Query.getScope.
             To modify a scope of analysis add and remove the objects you want in the
             scope of analysis with Scope.addScopeObject and
             Scope.removeScopeObject.




                                                           ReportEngine Developer Guide 97
6   Building and Editing Data Providers
    Building a data provider


    Conditions
                     A condition is a constraint on the data retrieved when you run a query, and is
                     sometimes called a query filter.
                     For example, if you add the result objects Year, Revenue, Store, and Company
                     Average, then define the condition ((Year between 1995 and 1999) AND
                     (Revenue < Company Average)), the query would return only data about the
                     stores that, between 1995 and 1999, achieved revenues below the company
                     average. For more information on conditions see Web Intelligence User’s
                     Guide.
                     Simple conditions
                     The simplest condition consists of a container, a data source object, and unary
                     operator. For example, in the condition (Revenue is not NULL), “Revenue” is
                     the object, and “is not NULL” is the operator.
                     In ReportEngine SDK, this condition is represented as follows.

                       FilterConditionContainer
                         ConditionObject
                         getDataSourceObject = Revenue
                          FilterCondition
                          getOperator = NOT_IS_NULL



                     The FilterCondition class holds information about operators and operands. For
                     some operators, such as BETWEEN, the FilterCondition contains more than
                     one operand.
                     Example: Creating a simple condition
                     The following JSP code fragment creates the condition (Revenue < 10000).
                     Query q; //query to which the condition is applied
                     //create a container for the condition
                     ConditionContainer c1 = q.createCondtion();
                     //create an object for the condition
                     ConditionObject co = c1.createConditionObject(revenue);
                     //create a FilterCondition object to contain information
                     //about the operator and the operand
                     FilterCondition fc =
                        co.createFilterCondition(Operator.LESS);
                     fc.createFilterConditionConstant("10000");


                     Complex conditions
                     By combining containers with operators and adding extra condition objects you
                     can build very complex conditions.




    98   ReportEngine Developer Guide
Building and Editing Data Providers
                                                                                                                                                                                                                                         Building a data provider   6
             Example: Structure of a complex condition
             The following is a representation in REBean of the condition:
                                  (Revenue < 1000000) OR ((Year = 2002) AND (Holiday)).

                        FilterConditionContainer(OR)
                         ConditionObject
                             getDataSourceObject = Revenue
                                    FilterCondition
                                    getOperator = LESS
                                    getOperand = 1000000

                             FilterConditionContainer(AND)
                              ConditionObject                                                                                                                                                                          ConditionObject
                                    getDataSourceObject = Year                                                                                                                                                         getDataSourceObject = Holiday
                                          FilterCondition
                                          getOperator = EQUAL
                                          getOperand = 2002

             In this example the data source object used for the last part of the condition (Holiday) is a predefined condition that is part of the universe, and it does not need a corresponding FilterCondition object.




Including a prompt in a condition
             To include a prompt in a condition use FilterCondition.createConditionPrompt.
             This method returns a ConditionPrompt object that you can use to define a
             prompt that is activated when the query is executed.
             As with normal prompts when you create a condition prompt you need to
             define the name of the prompt (that is, the question that is asked). You can
             also define properties such as its default value, and whether or not it is
             constrained to a list of values.
             You handle these prompts with the same workflows that are described in
             “Handling prompts” on page 64.
             Example: Including a prompt in a condition
             The following JSP code fragment creates the condition prompt “Year?”
             //get the query (q) to which the condition is applied
             //...
             //create a container for the condition
             ConditionContainer cc = q.createCondition();
             //create an object for the condition
             ConditionObject co = cc.createConditionObject(country);
             //create a FilterCondition object to contain the prompt
             FilterCondition fc =
                co.createFilterCondition(Operator.EQUAL);
             //define the prompt



                                                                                                                                                                                                                             ReportEngine Developer Guide 99
6   Building and Editing Data Providers
    Executing queries and retrieving the data


                     ConditionPrompt cp = fc.createConditionPrompt("Country?");
                     cp.setConstrained(false);
                     cp.setMonoValue(true);
                     cp.addDefault("Australia");



    Executing queries and retrieving the data
                     When a query is executed and data retrieve, contexts and prompts are raised
                     that need to be handled. It is possible to execute a query without retrieving
                     data, in which case no prompts or contexts need to be handled.

                      To execute the query and…               Use…
                      not retrieve the data                   DataProvider.executeQuery
                          The user does not need to set any
                          prompts or contexts.
                      retrieve the data                       DataProvider.runQuery
                          If there are prompts or contexts,
                          the user must set these using the
                          same procedure as for viewing a
                          document.

                     DataProvider.runQuery puts the data it retrieves into the results recordset of
                     the data provider.
                     Use DataProvider.getResults to retrieve the recordset. For an example of how
                     to access the values in the recordset see “Working with Recordsets” on
                     page 117.

    Getting the SQL for the query
                     Web Intelligence uses the properties of the Query object to create the SQL
                     statement it executes when you execute the query.
                     To get the SQL for a query, use Query.getSQL.




    100 ReportEngine Developer Guide
ReportEngine Java Developer Guide


Formatting Reports




                                    chapter
7
    Overview
                   Report Engine SDK contains classes and methods for controlling the format of
                   reports. Applications for formatting Web Intelligence reports (*.wid) create and
                   edit document structures, sections, cells, and page decoration.
                   This chapter discusses how to use REBean to format Web Intelligence reports.


    Creating and editing the document structure
                   You can access and change the structure of a Web Intelligence document. A
                   Web Intelligence document is made up of at least the following elements:
                   •   report
                   •   page header/footer
                   •   report body
                   A document can also contain:
                   •   sections
                   •   blocks
                   •   report cells
                   •   free cells
                   It is often useful to create a blank Web Intelligence document within which you
                   can manually build queries and report structures.
                   To create a blank document use DocumentInstance.newDocument.
                   Example: Creating a blank document
                   This example shows a JSP functions that use BusinessObjects Enterprise
                   SDK to recover the ID of the Universe parent folder. Using this ID an
                   IInfoObjects containing information about Universes stored in the Central
                   Management System is returned.

                   IInfoObjects getUniverses(IInfoStore iStore, int searchID) {
                      int ROOT_FOLDER_ID = 95;
                      IInfoObjects rootDirs = null;
                      IInfoObjects universes = null;

                       String rootQuery = "SELECT SI_ID, SI_NAME FROM”
                                 + “ CI_APPOBJECTS WHERE SI_PARENTID="
                                 + ROOT_FOLDER_ID ;
                       String unvQuery = "SELECT SI_ID, SI_NAME, SI_CUID,”
                                 + “ SI_OWNER, SI_PARENTID, SI_KIND"
                                 + " FROM CI_APPOBJECTS WHERE SI_ANCESTOR=";




    102 ReportEngine Java Developer Guide
7
   try{
//get the Universe Root directory
       rootDirs = iStore.query(rootQuery);
       if (rootDirs.size() > 0){
//Get the Universes
          IInfoObject rootDir =
              (IInfoObject)rootDirs.get(0);
          unvQuery += rootDir.getID();
          universes = iStore.query(unvQuery);
       }
   }catch (SDKException sdke){
       universes = null;
   } catch (Exception e){
       universes = null;
   }
   return universes;
}
The following code fragment creates a blank document using the first universe
in the collection of universes as a data source.
//Recover the universe list
IInfoStore iStore =
       (IInfoStore)session.getAttribute("InfoStore");
ReportEngines webiRepEngines =
       (ReportEngine)session.getAttribute("ReportEngines");
ReportEngine webiRepEngine = webiRepEngines.getService(
       ReportEngineType.WI_REPORT_ENGINE);
IInfoObjects universes = getUniverses(iStore, iID);
//Get the first universe
IInfoObject universe = (IInfoObject)universes.get(0);
//then create the blank document
DocumentInstance doc =
   webiRepEngine.newDocument(universe.getID());




                                    ReportEngine Java Developer Guide 103
7
    Representing document structure through containment
                   Document elements are structured according to their containment relationship.

                    This element…                              Can contain these elements…
                    report                                     page header/footer, report body
                    report body                                sections, blocks, and cells
                    page header/footer                         cells
                    section                                    sections, blocks, and cells
                   The containment relationship between the elements of a document is
                   represented in the object model as a tree using TreeNode,
                   ReportElementContainer, and ReportElement.

                     report                                            report
                      page header                                      page header
                                              free cell                                    free cell


                      report body                                      report body
                       free cell

                       section                                           section
                                    report cell

                         block                                             section


                         block                                                  block


                        free cell


                      page footer                                      page footer
                                              free cell                                    free cell



                   Table 7-1 Structures of a document with one report, one section, and two blocks, and
                   another with one report, two sections, and one block.
                   Notice that, to have two sections in a report, the relationship between the
                   sections is containment.




    104 ReportEngine Java Developer Guide
7
Example: Creating a document structure
The following code fragment creates the document structure shown in the
diagram. This code creates a new document and a report and adds information
to the header and footer parts. It then creates a section and a block and adds
universe objects (report expressions) to the block.
//create an empty document and a new report
DocumentInstance doc = engine.newDocument("1");
ReportContainer report = doc.createReport("My Report");

PageHeaderFooter header = report.getPageHeader();
Cell headerCell = header.createFreeCell("header cell");
PageHeaderFooter footer = report.getPageFooter();
Cell footerCell = footer.createFreeCell("footer cell");

BodyReport body = report.getBodyReport();
// create a section
SectionContainer sectionYear = body.createSection();
sectionYear.getAxis().addExpr(yearExpr); //[Year]
// create a block
ReportBlock block1 = sectionYear.createBlock ();
BlockAxis hAxis = block1.getAxis(TableAxis.HORIZONTAL);
hAxis.addExpr(quarterExpr); //[Quarter]
// create another block
ReportBlock block2 = body.createBlock ();
BlockAxis hAxis2 = block2.getAxis(TableAxis.HORIZONTAL);
hAxis2.addExpr(revenueExpr); //[Sales Revenue]

doc.applyFormat();




Table 7-2 Report structure defined by the code example above
Note: The header, footer, and report body elements are created by default.
Also, when you create a block, the default type is TableType.HTABLE.




                                       ReportEngine Java Developer Guide 105
7
    Positioning document elements
                   By default, elements are positioned using x-y co-ordinates referenced from the
                   top left corner of the containing element.

                               x


                          y         body report


                                    free cell



                   You can express x and y in millimeters or inches.

    Using attachments to avoid overlapping elements
                   Since the size of some elements, for example table blocks, is not known at the
                   time the report is formatted, sometimes elements overlap. To avoid this you
                   can use the attachment feature.
                   An attachment is a way to position a Cell or ReportBlock element relative to
                   other elements. An attachment consists of a vertical anchor, horizontal anchor
                   and a pair of x-y co-ordinates.
                   Vertical anchors can be either TOP, BOTTOM or NONE. Horizontal anchors
                   can be either RIGHT or LEFT or NONE. For example, in the diagram below the
                   attachment between block 1 and block 2 has a vertical anchor set to BOTTOM
                   and a horizontal anchor set to NONE, and the anchor between block 1 and cell
                   1 has a vertical anchor set to NONE and a horizontal anchor set to RIGHT.
                              xb1                             xc1


                    yb1
                                                                                   attachmentb1-c1
                                      block 1                       cell 1

                                                                                   attachmentb1-b2
                    yb2


                                      block 2



                   Table 7-3 Positioning elements relative to the parent container and siblings.




    106 ReportEngine Java Developer Guide
7
             Example: Creating an attachment
             The following Java code fragment creates and positions the elements shown
             in the diagram above. In this example, the x and y co-ordinates’ parameters
             are in millimeters and are cast to the required type (double) using the “d”
             operator.
             //units = UnitType.MILLIMETER
             // Create block 1 (b1) as child of the ReportBody container
             ReportBlock b1 = report.getReportBody().createBlock();
             // Set the block’s position relative to its container
             b1.setX(150d); // Xb1
             b1.setY(10d); // Yb1

             // Create block 2 (b2) and cell 1 (c1)
             ReportBlock b2 = report.getReportBody().createBlock();
             ReportBlock c1 = report.getReportBody().createFreeCell(" ");

             // Attach cell 1 to block 1 (RIGHT attachment): b1-c1
             c1.setAttachTo(b1, VAnchorType.NONE, HAnchorType.RIGHT);
             // Position cell 1 relative to block 1
             c1.setX(200d); // Xc1

             // Attach block 2 to block 1 (BOTTOM attachment): b1-b2
             b2.setAttachTo(b1, VAnchorType.BOTTOM, HAnchorType.NONE);
             // Position block 2 relative to block 1
             b2.setY(200d); // Yb2


Creating and editing sections
             A report can have zero or more sections, each one containing blocks, cells
             and/or other sections. A section has one axis with one report expression, and,
             by default, each report expression has a corresponding report cell.
             To check if a report cell is a section container use: ReportCell.isSection.
             When you add report expressions to the section’s axis, they are added to the
             right of the last one added.
             Example: Editing the sections of a report
             The following code fragment creates two sections, one for Year and another
             for Country.
             SectionContainer sc, sc2;
             ReportExpression reYear;
             ReportExpression reCountry;

             sc.getAxis().addExpression(reYear);
             sc2 = sc.createSection();
             sc2.getAxis().addExpression(reCountry);




                                                   ReportEngine Java Developer Guide 107
7
                   When you add an expression to the axis of a section, a cell for the expression
                   is automatically created. In the example above, report cells for =[Year] and
                   =[Country] are created.

    Creating and editing blocks
                   Block is a generic name for tables, cross tables, forms, and graphs.
                   Block structure: axes and report expressions
                   A block axis is an oriented collection of one or more report expressions.
                   A report expression is a report object or a variable. For example, [Customer].
                   Report expressions are stored in the document dictionary when a query is
                   executed, and are represented in REBean by the ReportExpression interface.
                   Sections and report blocks have axes. A section has one axis. A report block
                   has one, two, or three axes. The following table shows the axes for each type
                   of block.

                    Block type                               Axes
                    vertical table                           one horizontal axis
                    horizontal table                         one vertical axis
                    cross table                              horizontal, vertical, and content axes
                    graph                                    x, y, and z axes
                   For a vertical table the report expressions are displayed in columns.




                   Table 7-4 Structure of a vertical table
                   Note: The block type determines the operators applied to the expression in
                   the report. For example, in the above example the report expression [year] is
                   shown in the table as NameOf([year]) and =[year].
                   For a horizontal table the report expressions are displayed in rows.




    108 ReportEngine Java Developer Guide
7




Table 7-5 Structure of a horizontal table
For a cross table the report expressions are displayed in columns and rows
with a shared body.




Table 7-6 Structure of a cross table
In a graph the report expressions are displayed as a picture with two or three
dimensions.




                                            ReportEngine Java Developer Guide 109
7




                   Table 7-7 Structure of a graph
                   Example: Building a report: adding expressions to axes
                   The following code fragment builds a report structure by retrieving the report
                   expressions from the document dictionary.
                   // Retrieve the dictionary associated with the document
                   // populated by the last call to Document.runQuery
                   ReportDictionary dico = doc.getDictionary();

                   // Create a new report
                   ReportContainer report = doc.createReport("My Report");
                   BodyReport body = report.getBodyReport();

                   // Create a section as the body report child
                   SectionContainer section = body.createSection ();
                   ReportExpression ctryExpr =
                                dico.getChildByname("ParentCountryID");

                   // Add the country object on the section axis
                   section.getAxis().addExpr(ctryExpr);

                   // Create a block in the section container
                   ReportBlock block = section.createBlock ();

                   ReportExpression yearExpr =
                                dico.getChildByName("ParentYearID");
                   ReportExpression revExpr =
                                dico.getChildByName("ParentRevenueID");
                   // Add the Year and Revenue objects on the vertical axis of
                   // the horizontal table.
                   block.getAxis (TableAxis.HORIZONTAL).addExpr (yearExpr);
                   block.getAxis (TableAxis.HORIZONTAL).addExpr (revExpr);




    110 ReportEngine Java Developer Guide
7
               doc.applyFormat ();


Sorting report expressions
               You can sort report expressions into ascending or descending natural order.
               The natural order of an object is the one used in the database.
               Sorts are stored in a collection (Sorts) that defines the type and priority of the
               sort. By default the first sort in the collection has the highest priority.

Breaks
               You can add breaks to report expressions. You can add breaks to report
               expressions belonging to an axis, and you can show or hide the break’s header
               and footer using the BreakElement interface. By default the header and footer
               are hidden.
               Breaks are stored in a collection. The first element in the collection has the
               highest priority.

Calculations
               You can add a calculation to a report expression. For example, the predefined
               calculation Sum adds the values of the report expression.
               By default, the results of a calculation are placed in the footer of a table, and
               use the name of the calculation as a label for the result. For a percentage
               calculation, a Percentage column is also added.


Representing a block
               A block can be represented as a vertical or horizontal table, a cross table, a
               form, or a graph. The interface Representation defines how a block is
               represented.

Vertical and horizontal tables
               The header, footer and body of the table are exposed through the Table class
               as a CellMatrix collection, which contains TableCell objects. Vertical and
               horizontal tables use the SimpleTable specialization of Table.
               You can change the following properties of the header, footer and body of a
               table with the Table interface:
               •   visibility
               •   repetition
               •   decoration


                                                      ReportEngine Java Developer Guide 111
7
                   The settings on low level objects are inherited from their parents but, if
                   changed, override those of their parents.

    Cross tables
                   Cross tables use the CrossTable specialization of Table, and the cells in a
                   cross table are grouped into zones.

                    Top - Left                 Top - Body                  Top - Right
                    Body - Left                Body - Body                 Body - Right
                    Bottom - Left              Bottom - Body               Bottom - Right
                   The zones correspond to parts of a cross table in structure view.
                   Zones that can contain more than one cell, for example Body - Body, contain
                   a matrix of TableCell objects that are contained in the collection CellMatrix.
                   Note: If you add a break to the report expressions in a cross table, each
                   break has its own header and footer and each zone (except Body - Body)
                   contains a division for each break.

    Forms
                   Forms are represented by the Form interface. The cells in the form are
                   represented by a CellMatrix object, and you can set the decoration of labels
                   and values separately.

    Graphs
                   Graphs are represented by the Graph interface, and a set of interfaces that
                   represent parts of the graph: Legend, GraphTitle, GraphData,
                   GraphAxisValues, GraphAxisProperties, Graph3D, and Wall.
                   Developer Suite supports the following graphs.




    112 ReportEngine Java Developer Guide
7
Graph category       Graph type
Bar                  Vertical Grouped
                     Horizontal Grouped
                     Vertical Line and Bar
                     Horizontal Line and Bar
                     Vertical Stacked
                     Horizontal Stacked
                     Vertical Percent
                     Horizontal Percent
                     3D
Line                 Vertical Mixed
                     Horizontal Mixed
                     Vertical Stacked
                     Horizontal Stacked
                     Vertical Percent
                     Horizontal Percent
                     3D
                     3D Surface
Area                 Vertical Absolute
                     Horizontal Absolute
                     Vertical Stacked
                     Horizontal Stacked
                     Vertical Percent
                     Horizontal Percent
                     3D Area
                     3D Surface
Pie                  Pie
                     Doughnut
                     3D Pie
                     3D Doughnut
Radar & Scatter      Stacked Area Radar
                     Polar
                     Scatter
                     Radar Line




                  ReportEngine Java Developer Guide 113
7
    Creating and editing cells
                   A cell is a report element that contains information such as the title of the
                   report, or the heading of a section. There are two types of cell: free cell, and
                   report cell.
                   Free cells contain a string and are exposed with the class FreeCell. Report
                   cells contain a formula of a section axis and are exposed with the class
                   ReportCell.
                   You can add a cell to all the elements contained in a report element. For more
                   information on containment rules see “Representing document structure
                   through containment” on page 104.

    Creating and editing the page decoration
                   Page decoration refers to the display aspects of the contents of a cell. For
                   example, the font, color, and size of the text in the cell.
                   You can control the decoration of most cells in a report using the Decoration
                   interface. The Decoration interface provides a gateway for other interfaces
                   such as Alignment, Attributes and Font.

    Alignment
                   Using the Alignment interface you can set the horizontal and vertical alignment
                   of the cell contents. You can also set the wrapping properties of text in the cell.

    Attributes
                   The Attributes interface represents the “non-font” aspects of the cell’s
                   presentation. Using this interface you can set properties such as the
                   background and foreground image, the color of the foreground and
                   background, and the properties of the cell border (which is represented by the
                   interface Border).

    Font
                   The Font interface allows you to determine the color, style, size and font name
                   of the text in the cell.




    114 ReportEngine Java Developer Guide
7
Page layout
             You can control the page layout of a report using the PageLayout, Visibility and
             Repetition classes. The classes give you control over how blocks behave
             around page breaks, repeating blocks on every page, displaying calculations
             and breaks, and hiding and showing the elements of a report.

Paper size
             You can set the page size for the document to the following paper sizes:
             Custom, A4 to A0, and Letter, and orient the page in landscape, or portrait
             views.
             All the margins are adjustable and you can set the units to millimeters, or
             inches.




                                                   ReportEngine Java Developer Guide 115
7




    116 ReportEngine Java Developer Guide
ReportEngine Developer Guide


Working with Recordsets




                               chapter
8   Working with Recordsets
    Overview



    Overview
                    ReportEngine SDK often uses the recordset data structure for storing
                    information such as the results in a data provider.
                    This chapter explains how to use the recordset classes of the ReportEngine
                    SDK.


    Anatomy of a recordset
                    In ReportEngine SDK recordsets provide a generic way of representing the
                    data about, or contained in, a group of objects.


                                           a         b          c       10.0

                              field        d         e          f       20.0           fields

                     current record        g         h          i       30.0
                                            j        k          l       40.0           recordset
                                           m         n         o        50.0
                                           p         q          r       60.0
                                           s         t         u        70.0


                    Each recordset is divided into rows and columns. Each row can be considered
                    a record (or a set of fields) and you can access only one record at a time.

    Recordsets
                    In ReportEngine SDK the Recordset interface represents recordsets.

    Field names
                    Recordset.getColumnName(n) gives the name of the nth field in the current
                    record.
                    The names of the fields in most recordsets are fixed. You can find the names
                    listed under the method descriptions in the ReportEngine SDK API Reference.
                    The exception to this is DataProvider.getResult which returns a recordset
                    in which the names of the fields are the names of the results (columns) of the
                    query.




    118 ReportEngine Developer Guide
Working with Recordsets
                                                                       Anatomy of a recordset   8
Moving around the recordset
              Recordsets can contain only one record (row) at a time. To load it use the
              move methods of Recordset:
              •   first, last, next, previous, and setRow
              The Recordset class has a feature for setting the direction. You can set the
              direction to FORWARD(default) or REVERSE. When the direction is set to forward
              calling Recordset.next moves to the next row in the collection and when it
              is set to reverse calling Recordset.previousmoves to the previous row in
              the collection. Recordset.first IRecordset.Firstand Recordset.last
              do not depend on the direction and always move to row 0 and row
              (Recordset.getColumnCount - 1) respectively.
              It is good practice to set the direction and call Recordset.first
              IRecordset.Firstor Recordset.last before you start processing a
              recordset so that you know which row the Recordset object contains.
              You can use Recordset.first IRecordset.Firstand
              Recordset.isFirst IRecordset.IsFirstto control loops that move
              through recordsets.

Accessing the value of a field
              In ReportEngine SDK you can access the values of a field directly.
              To access the fields of a record, use Recordset.getCellObject and
              provide the index of the column in which you are interested.
              Example: Accessing the values in a recordset
              The following code fragment prints the types of the columns and the contents
              of the results of a query contained in a data provider.
              Recordset rs = dp.getResult(0);
                           // 0: assume query has one flow
              rs.first();

              // Print the column types. They can be Integer, String,
              // or Date.
              for (int i = 0; i < rs.getColumnCount(); i++) {
                 Class c = rs.getColumnType(i);
                 StringBuffer sbt = new StringBuffer();
                 if ( c.equals(Integer.class) )
                     sbt.append("Integer");
                 if ( c.equals(String.class) )
                     sbt.append("String");
                 if ( c.equals(Date.class) )
                     sbt.append("Date");
                 sbt.append(";");
                 System.out.println(sbt.toString());
              }




                                                            ReportEngine Developer Guide 119
8   Working with Recordsets
    Anatomy of a recordset


                    // Print the recordset contents: column names and data
                    while (!rs.isLast()) {
                       // column names
                       StringBuffer sbn = new StringBuffer();
                       for (int j = 0; j < rs.getColumnCount(); j++) {
                           sbn.append( rs.getColumnName(j).toString() );
                           sbn.append(";");
                       }
                       System.out.println(sbn.toString());

                        // data
                        for (int k= 0; k< rs.getColumnCount(); k++) {
                           sbd.append( rs.getCellObject(k).toString() );
                           sbd.append(";");
                        }
                        System.out.println(sbd.toString());

                        rs.next();
                    }


                    This code fragment assumes that rs.getDirection equals FORWARD, and that
                    the data provider (dp) has been populated. For more information on populating
                    data providers see “Executing queries and retrieving the data” on page 100.




    120 ReportEngine Developer Guide
ReportEngine Developer Guide



Business Objects
Information Resources




                               appendix
A   Business Objects Information Resources
    Documentation and information services



    Documentation and information services
                     Business Objects offers a full documentation set covering its products and
                     their deployment. Additional support and services are also available to help
                     maximize the return on your business intelligence investment. The following
                     sections detail where to get Business Objects documentation and how to use
                     the resources at Business Objects to meet your needs for technical support,
                     education, and consulting.


    Documentation
                     You can find answers to your questions on how to install, configure, deploy,
                     and use Business Objects products from the documentation.


    What’s in the documentation set?
                     View or download the Business Objects Documentation Roadmap, available
                     with the product documentation at http://www.businessobjects.com/support/.
                     The Documentation Roadmap references all Business Objects guides and
                     lets you see at a glance what information is available, from where, and in
                     what format.


    Where is the documentation?
                     You can access electronic documentation at any time from the product
                     interface, the web, or from your product CD.

    Documentation from the products
                     Online help and guides in Adobe PDF format are available from the product
                     Help menus. Where only online help is provided, the online help file contains
                     the entire contents of the PDF version of the guide.

    Documentation on the web
                     The full electronic documentation set is available to customers on the web
                     from support website at: http://www.businessobjects.com/support/.

    Documentation on the product CD
                     Look in the docs directory of your product CD for versions of guides in Adobe
                     PDF format.



    122ReportEngine Developer Guide
Business Objects Information Resources
                                                    Customer support, consulting and training   A
Send us your feedback
            Do you have a suggestion on how we can improve our documentation? Is
            there something you particularly like or have found useful? Drop us a line,
            and we will do our best to ensure that your suggestion is included in the next
            release of our documentation: documentation@businessobjects.com.
            Note: If your issue concerns a Business Objects product and not the
            documentation, please contact our Customer Support experts. For
            information about Customer Support visit: http://www.businessobjects.com/
            support.


Customer support, consulting and training
            A global network of Business Objects technology experts provides customer
            support, education, and consulting to ensure maximum business intelligence
            benefit to your business.


How can we support you?
            Business Objects offers customer support plans to best suit the size and
            requirements of your deployment. We operate customer support centers in
            the following countries:
            •   USA
            •   Australia
            •   Canada
            •   United Kingdom
            •   Japan

Online Customer Support
            The Business Objects Customer Support website contains information about
            Customer Support programs and services. It also has links to a wide range of
            technical information including knowledgebase articles, downloads, and
            support forums.
            http://www.businessobjects.com/support/




                                                        ReportEngine Developer Guide123
A   Business Objects Information Resources
    Useful addresses at a glance



    Looking for the best deployment solution for your
    company?
                     Business Objects consultants can accompany you from the initial analysis
                     stage to the delivery of your deployment project. Expertise is available in
                     relational and multidimensional databases, in connectivities, database design
                     tools, customized embedding technology, and more.
                     For more information, contact your local sales office, or contact us at:
                     http://www.businessobjects.com/services/consulting/


    Looking for training options?
                     From traditional classroom learning to targeted e-learning seminars, we can
                     offer a training package to suit your learning needs and preferred learning
                     style. Find more information on the Business Objects Education website:
                     http://www.businessobjects.com/services/training


    Useful addresses at a glance

                      Address                                   Content
                      Business Objects product                  Information about the full range of
                      information                               Business Objects products.
                      http://www.businessobjects.com
                      Product documentation                     Business Objects product
                      http://www.businessobjects.com/           documentation, including the
                      support                                   Business Objects Documentation
                                                                Roadmap.
                      Business Objects Documentation            Send us feedback or questions
                      mailbox                                   about documentation.
                      documentation@businessobjects.com
                      Online Customer Support                   Information on Customer Support
                      http://www.businessobjects.com/           programs, as well as links to
                      support/                                  technical articles, downloads, and
                                                                online forums.




    124ReportEngine Developer Guide
Business Objects Information Resources
                                            Useful addresses at a glance   A
Address                            Content
Business Objects Consulting        Information on how Business
Services                           Objects can help maximize your
http://www.businessobjects.com/    business intelligence investment.
services/consulting/
Business Objects Education         Information on Business Objects
Services                           training options and modules.
http://www.businessobjects.com/
services/training




                                    ReportEngine Developer Guide125
A   Business Objects Information Resources
    Useful addresses at a glance




    126ReportEngine Developer Guide
ReportEngine Developer Guide


Logging with ReportEngine
SDK Overview




                               appendix
B   Logging with ReportEngine SDK Overview
    Logging Systems


                    The are a number of ways to trace a ReportEngine SDK application including
                    a Java package optimized for ReportEngine SDK.
                    This appendix discusses how to use the various logging systems available.


    Logging Systems
                    ReportEngine SDK provides logging systems.


    Logging in REBean
                    In a Java programming environment you can use the following logging systems.
                    •    Jakarta log4j
                         The Jakarta log4j system is part of the Jakarta project.
                         See http://Jakarta.apache.org/log4j.
                    •    java.util.logging
                         The java package java.util.logging is the logging system provided with
                         JDK
                         1.4.1. See http://java.sun.com/j2se/1.4.1/docs/guide/util/logging/
                         index.html.
                    •    log4j.logger.com.businessobjects.rebean.ReportEngines
                         The <BOProductName>Web Intelligence SDK package
                         log4j.logger.com.businessobjects.rebean.ReportEngines allows you to
                         integrate trace messages from your own application with those generated
                         by the Business Objects servers and <BOProductName>Web
                         Intelligence SDK.

    Trace Levels
                    The following table shows the trace levels available through these trace systems.


                     Trace Level               Provides messages on
                     DEBUG                    •    helper classes
                                              •    calls from REBean to the report engine server
                                              •    JHSAL activity
                     INFO                     •    entry of each JSP
                                              •    calls to the methods exposed by REBean




    128   ReportEngine Developer Guide
Logging with ReportEngine SDK Overview
                                               Activating logging by editing the configuration files   B
           Trace Level                 Provides messages on
           WARN                        •    potentially harmful situations
           ERROR                       •    non-fatal exceptions
           FATAL                       •    exceptions that stop the application executing




Activating logging by editing the
configuration files
           To activate logging you edit the webi.properties file. When you change this
           file you need to restart Tomcat for your changes to take effect.


Using the default settings
           To activate the logging system using the default settings:
           1.   Add the following line to the webi.properties configuration file:
                Trace=1
           2.   Start, or restart Tomcat.
                This activates logging, by default the log4j logging system is selected,
                and the
                trace level is set to INFO. If there is no log4j.properties file,
                log4j.properties.todo is generated.


Setting the trace level
           To activate the logging system, set the trace level and use the default logging
           system:
           •    Add the following line to the webi.properties configuration file
                Trace=1, LEVEL
                Where LEVEL can be one of: DEBUG, INFO, WARN, ERROR, or FATAL
           This automatically selects the log4j logging system and sets the trace level to
           LEVEL. If there is no log4.properties file, log4.properties.todo is
           generated.



                                                         ReportEngine Developer Guide          129
B   Logging with ReportEngine SDK Overview
    Activating logging by editing the configuration files



    Selecting the logging system
                        To activate the logging system, and set the trace level and logging system:
                        •    Add the following lines to the webi.properties configuration file:
                                  Trace=1, LEVEL
                                  Adapter=log4j.logger.com.businessobjects.rebean.ReportEngines.s
                                  ystem
                             Where:
                                  LEVEL can be one of: DEBUG, INFO, WARN, ERROR, or FATAL
                                  system is one of: Log4jLogger (log4j), or StandardLogger
                                  (debugdiag)
                        This activates logging, selects the system logging system, and sets the trace
                        level to LEVEL. If there is no configuration file for the logging system a .todo
                        fileis generated.


    Activating logging while Tomcat is running
                        To activate logging while Tomcat is running, put the following code in a file
                        called traces.jsp and put the file in the same folder at the InfoView files.
                        Then, to activate logging, open traces.jsp in a web browser and select the
                        options (logging system, and trace level) you want.
                        The following is an example of the traces.jsp file.
                        <%@ taglib uri="/WEB-INF/wilog.tld" prefix="log" %>
                        <jsp:useBean id="systems" class="java.util.Hashtable"
                        scope="application" />
                        <%
                            if (systems.isEmpty()) {
                                 systems.put("fake",
                            "log4j.logger.com.businessobjects.rebean.ReportEngines.FakeLogger
                            ");
                                 systems.put("debugdiag",
                        "log4j.logger.com.businessobjects.rebean.ReportEngines.StandardLogger
                            ");
                                 systems.put("log4j",
                            "log4j.logger.com.businessobjects.rebean.ReportEngines.Log4jLogge
                            r");
                            }
                        %>
                        <html>
                        <head><title><BOProductName>Web Intelligence Logging
                            System</title></head>
                        <body>
                        <%
                            String uri = request.getRequestURI();
                            String sys = request.getParameter("sys");



    130   ReportEngine Developer Guide
Logging with ReportEngine SDK Overview
                         Activating logging by editing the configuration files   B
   String level = request.getParameter("level");
   String prop = request.getParameter("prop");
   String adapter = request.getParameter("adapter");
   if (sys == null)
   {
      out.println("<form method="POST"
      action="" + uri + "">");
      out.println("<h4>Change the
          <BOProductName>Web Intelligence Logging System</
   h4>");
      out.println("<input name="sys" value="log4j"
          type="RADIO" CHECKED/>Enable Log4J, ");
          out.println(" properties <input value="Choose"
          name="prop" type="FILE" size="25"/> ");
      out.println("<br><input name="sys"
          value="debugdiag"
          type="RADIO"/>Enable Debugdiag ");
          out.println("<br><input name="sys"
          value="fake"
          type="RADIO"/>Disable Any ");
      out.println("<br><br>Level <input name="level"
          value="debug" type="RADIO"/>DEBUG ");
          out.println("<input name="level" value="info"
          type="RADIO" CHECKED/>INFO ");
      out.println("<input name="level" value="warn"
          type="RADIO"/>WARN ");
      out.println("<input name="level" value="error"
          type="RADIO"/>ERROR ");
      out.println("<input name="level" value="fatal"
          type="RADIO"/>FATAL ");
      out.println("<br><br><input type="SUBMIT"
          SELECTED value="GO" /><br><br>");
   }
   else
   {
%>
<log:reinit adapter="<%=(String)systems.get(sys) %>"
level="<%=level %>" lib="" prop="<%=prop %>"/>
<%
       out.println("<h5><a href=""+ uri +"">
          Back</a></h5>");
}
%>
</body>
</html>




                                   ReportEngine Developer Guide          131
B   Logging with ReportEngine SDK Overview
    Configuring the Jakarta log4j logging system



    Configuring the Jakarta log4j logging system
                      The Jakarta log4j logging system uses a configuration file called
                      log4j.properties. This file must be present in the classes directory of the
                      web application, for example, webappswijspWEB-INFclasses. If the
                      configuration file is not present log4j.properties.todo is created in the bin
                      folder of the application server, however you should move this file to the
                      classes directory for your web application (and remove the “todo” from the file
                      name) so you can have one configuration file for each application.
                      This logging system is delivered with the BusinessObjects platform. It is
                      installed in $INSTALLDIRclasses. See also http://jakarta.apache.org/log4j/
                      docs/index.html for further explanation of the configuration options for this
                      tool.


    Setting the trace level
                      You set the trace level in log4j.properties. The possible levels are DEBUG,
                      INFO, WARN, ERROR, and FATAL.
                      The trace level setting in log4j.properties takes precedence over the trace
                      level setting in webi.properties.


    Setting the trace mechanism
                      You set the trace output mechanism in log4j.properties. Possible output
                      mechanisms are: file, console (stdout), or a socket.


    Setting the trace output
                      You can set the output format in log4j.properties. The following table shows
                      the formatting tokens you can use.


                       This token       Adds this to the trace
                       %d                date
                       %t                thread
                       %p                trace level
                       %c                the name of the logger.
                       %r                time since the trace system was initialized




    132   ReportEngine Developer Guide
Logging with ReportEngine SDK Overview
                                                   Configuring the Jakarta log4j logging system   B
             This token      Adds this to the trace
             %x              thread content, for example, the session ID
             %m              the message
             See


Specifying the trace level for individual classes
             You can specify the trace level for a package or a class.
             For example, if the root trace level is DEBUG, but you do not want to see the
             trace for the REBean package, add the line
             log4j.logger.com.businessobjects.rebean.wi=WARN to
             log4j.properties.
             Similarly, you can exclude the trace for the ReportEngine interface with
             log4j.logger.com.businessobjects.rebean.wi.ReportEngine=WARN
             log4j.properties

Example log4j.properties
             The following lists the contents of log4j.properties. In this example, the
             root trace level is set to DEBUG, and traces from the Report interface are
             excluded.
             log4j.rootCategory=DEBUG, A1
             # Console output
             log4j.appender.A1=org.apache.log4j.ConsoleAppender
             # File output
             #log4j.appender.A1=org.apache.log4j.FileAppender
             #log4j.appender.A1.File=infoview.log
             # Socket output
             #log4j.appender.A1=org.apache.log4j.net.SocketAppender
             #log4j.appender.A1.RemoteHost=bergame
             #log4j.appender.A1.Port=8887
             # Format
             log4j.appender.A1.layout=org.apache.log4j.PatternLayout
             log4j.appender.A1.layout.ConversionPattern=
             %-4r %-5p %c{10} (%x) - %mn
             ## to filter REBean logging, uncomment
             #log4j.logger.com.businessobjects.rebean.wi=WARN
             #log4j.logger.com.businessobjects.rebean.wi.AxisType=WARN
             #log4j.logger.com.businessobjects.rebean.wi.BarType=WARN
             #log4j.logger.com.businessobjects.rebean.wi.HTMLView=WARN
             log4j.logger.com.businessobjects.rebean.wi.Report=WARN
             ## to filter REPORT ENGINE SERVLET, uncomment
             #log4j.logger.com.businessobjects.cdzlet=WARN
             ## to filter INFOVIEW JSP logging, uncomment
             #log4j.logger.scripts=WARN
             #log4j.logger.viewers=WARN



                                                       ReportEngine Developer Guide       133
B   Logging with ReportEngine SDK Overview
    Configuring the Jakarta log4j logging system




    134   ReportEngine Developer Guide
ReportEngine Developer Guide


Configuring ReportEngine
using webi.properties




                               appendix
C   Configuring ReportEngine using webi.properties
    Configuring ReportEngine SDK web applications



    Configuring ReportEngine SDK web
    applications
                     You can configure individual ReportEngine SDK or viewer applications such
                     as InfoView to improve their efficiency on application server on which they
                     have been deployed. The purpose of this chapter is to tell you how to improve
                     BusinessObjects Enterprise application efficiency.


    What is webi.properties?
                     Each ReportEngine web application can have a webi.properties file. For
                     BusinessObjects Enterprise XI R2 applications this file is optional. The
                     webi.properties file is located in the WEB-INFclasses subdirectory of the
                     <BOProductName>Web Intelligence application. For example, if you have
                     deployed InfoView on a Tomcat application server the webi.properties file
                     would be found in the following directory.
                     <TOMCAT_HOME>webappsbusinessobjectsenterprise115desktopl
                     aunchWEB-INFclasseswebi.properties


    How to update webi.properties
                     The webi.properties file is a plain text file containing variables used to tune
                     the individual <BOProductName>Web Intelligence web application. The
                     variables defined in the webi.properties file are taken in to account when your
                     <BOProductName>Web Intelligence server starts up. To change variable
                     settings in webi.properties, Business Objects recommends that you do the
                     following:
                     1.   Navigate to the classes subdirectory in your <BOProductName>Web
                          Intelligence web application,
                     2.   that is to say <MyWebIntelligenceApp>/WEB-INF/classes.
                     3.   Make a copy of the webi.properties file. This copy is to stay in the
                          <MyWebIntelligenceApp>/WEB-INF/classes subdirectory as a backup.
                     4.   Copy webi.properties to a temporary directory.
                     5.   Edit webi.properties using your favorite text editor, set the value of the
                          variables as required.
                     6.   Replace <MyWebIntelligenceApp>/WEB-INF/classes/webi.properties
                          with your updated version.
                     7.   Restart Business Objects XI R2.




    136   ReportEngine Developer Guide
Configuring ReportEngine using webi.properties
                                                  Configuring ReportEngine SDK web applications    C
                A comprehensive list of variables to update can be found in the next section.


Configuration Options
                The following variables can be used to tune web applications:

Variable Name                       Description                       Default Value
TEMP_DIR                             The directory where temporary same as the Java
                                     files generated by            temporary directory
                                     <BOProductName>Web
                                     Intelligence are stored.
XML_TRANSFORMER                      The parser used for XML          org.apache.xalan.proce
                                     translation.                     ssor.TransformerFactor
                                                                      yImpl
CHUNK_SIZE                           The size of binary or character In bytes: 60000
                                     object sent between the client In kilobytes: 60k
                                     browser and the
                                     <BOProductName>Web
                                     Intelligence server.
FAILOVER_SIZE                        The size of binary or character 10
                                     object sent between the client
                                     browser and the
                                     <BOProductName>Web
                                     Intelligence server.
MAX_HEAP_SIZE                        Prevent the web application    750m
                                     from consuming all the heap of
                                     the Java Virtual Machine.
Trace                                Set the application to trace     Commented out.
                                     internal                         Uncomment and set to
                                     <BOProductName>Web               1 to activate.
                                     Intelligence calls.
STORAGE_TOKEN_STACK_SIZE             Sets the limit of undo actions 10
                                     possible for DocumentInstance
                                     objects.
                                     Set to 0 for no limit for file
                                     persistence and token are
                                     storage until memory reaches
                                     FAILOVER_SIZE.
                Note: For application servers running with the Java Virtual Machine 1.4 and
                above, runtime.maxMemory is used to set the MAX_MEMORY variable
                internally. This ensures that your <BOProductName>Web Intelligence
                application does not consume the Java Virtual Machine heap.



                                                          ReportEngine Developer Guide      137
C   Configuring ReportEngine using webi.properties
    Configuring ReportEngine SDK web applications


                     In order to optimize resources on the Web Intelligence server, the
                     STORAGE_TOKEN_STACK_SIZE parameter is used to limit the size of the
                     size of stack by limiting document serialization. For the end user, this means
                     the number of undo actions that can be done.
                     The default value of STORAGE_TOKEN_STACK_SIZE is 10, the same as
                     the FAILOVER_SIZE variable.
                     •    If STORAGE_TOKEN_STACK_SIZE =0 their is no limit for file
                          persistence and token are stored into memory until reaching
                          FAILOVER_SIZE. If failover happens, the maximum number of
                          DocumentInstance objects in the storage manager will fail over to a
                          backup application server.
                     •    If STORAGE_TOKEN_STACK_SIZE <= FAILOVER_SIZE their is no file
                          persistence.
                     •    If STORAGE_TOKEN_STACK_SIZE > FAILOVER_SIZE up to
                          (STORAGE_TOKEN_STACK_SIZE minus FAILOVER_SIZE) instances
                          are stored in file system.
                     The memory footprint for a document state that is higher than the value of
                     STORAGE_TOKEN_STACK_SIZE in the stack is deleted. If a client tries to
                     use an out of stack token to access a document state the ReportEngine will
                     throw an exception. You can retrieve the stack size programmatically and
                     validate storage tokens using:
                     int ReportEngine.getStorageTokenStackSize()
                     boolean ReportEngine.IsStorageTokenValide(String
                        storageToken)




    138   ReportEngine Developer Guide
Index
A                                                training services 124, 125
accessing                                    Business Objects Enterprise sessions
     user profiles 25                            creating 46
actions                                          storage tokens 38
     drilling 83
Adobe Acrobat 34                             C
      see also PDF                           calculations 111
alignment 114                                categories 38–46
anchors                                            category details 45
     vertical and horizontal 106                   category moving 45
applets                                            creating 44
     Java Report Panel 92                          deleting 44
area graph 112                                     getting details 45
attachments 106                                    renaming 44
authentication                                     user rights, and 39
     passwords 19                            categorizing documents 38
axis (block) 108                             cells
                                                   creating 114
B                                            CESDK
background 114                                     creating a ISessionMgr object 18
bar graph 112                                      referencing 17
batched lists of values 72                   CESDK object
blocks                                             creating 20
     cells 114                               chunking
     creating 108                                  lists of values 72
     cross tables 112                        classes
     forms 112                                     referencing 17
     graphs 112                              closing
     repeating 115                                 ReportEngine object 32
     representing 111                              ReportEngine SDK sessions 21
borders 114                                  colors 114
breaks 111                                   conditions 98
browsers                                           prompts 99
     storage tokens 38                             structure 99
building data providers 89                   consultants, Business Objects 124
Business Objects                             contexts
     consulting services 124, 125                  opening documents 46
     support services 123                    creating




                                    Developing with Web Intelligence Report Engine SDK 139
blocks 108
    categories 44


    cells 114                                   see also reports
    document structure 102                      building data providers 89
    ISessionMgr object 18                       categories 38
    sections 107                                changing names 48
cross tables 112                                creating 102
custom 57                                       dictionaries 91
customer support 123                            displaying
                                                      document lists 47
D                                               drillable 79
                                                drilling 77
data providers 89–100
                                                format 80
     building 91
                                                formatting reports 101
     data sources 90
                                                opening 13, 46
     executing queries 100
                                                prompts 64
data sources 90
                                                properties 56
decoration
                                                refreshing 13, 64, 73
     pages 114
                                                      document lists 47
deleting
                                                report maps 74
     categories 44
                                                saving 48
Developer Suite
                                                sending 50
     migration 11
                                                structure 102
dimensions
                                                types 34
     drilling 80, 83
                                                Web Intelligence and Desktop Intelligence
     scope of analysis, and 87
                                                           format 30
displaying
                                          drill bars 81, 87
     document lists 47
                                          drill hierarchies 80
     report maps 74
                                          drill mode 79, 80
document structure 102
                                                entering and leaving 81
     attachments 106
                                          drill options 82
     blocks 108
                                          drill path 79, 79, 81
     positioning elements 106
                                                setting 79, 81, 83
     report expressions 107
                                          drilling 77–88
     sections 107
                                                actions 83
documentation
                                                dimensions 80
     feedback on 123
                                                drill bars 81
     on product CD 122
                                                drill hierarchies 81
     on the web 122
                                                drill mode 79, 85
     roadmap 122
                                                drill path 79, 81, 83
documents 48
                                                filtering 87



                                 Developing with Web Intelligence Report Engine SDK 140
generating HTML 80, 85
    hierarchies 80, 83


    hyperlinks 79, 81, 82                               saving 48
    images 85                                      formatting
    Java script files 85                                layout 115
    overview 78                                         page
    query string parameters 79, 79, 79, 81, 82               decoration 114
    reports 80–88                                       paper size 115
    scope of analysis 80, 87, 97                        reports 101
    setting parameters 83                          forms 112
    slice 83                                       free cells 114
    snapshots 88
    transparent drill out of cube 80               G
                                                   getHTMLView 36
E                                                       drilling 80, 85
editing                                            getting started 11, 16
     blocks 108                                    graphs 112
     cells 114
     data providers 89                             H
     document structure 102
                                                   handling
     queries 96
                                                        context prompts 74
     sections 107
                                                        exceptions 29
education. See training
                                                        out of scope drill requests 87
Enterprise Mode authentication 20
                                                        prompts 64
errors 29
                                                   hello world example 16
exceptions 29
                                                   hierarchies
executing queries 100
                                                        drilling 81, 83
                                                   hyperlinks
F                                                       generating for drilling 79, 80, 81, 82, 85
feedback, on documentation 123
fields                                             I
      recordsets 118
                                                   images
filtering
                                                        drilling 85
      drill bars 81, 87
                                                   importing code in JSP 24
      drill-by and drill-up actions 84
                                                   include directive
      queries 98
                                                        in JSP 24
      query conditions 88
                                                   information resources 122
fonts 114
                                                   InfoView
foreground 114
                                                        example workflows 13
formats



                                          Developing with Web Intelligence Report Engine SDK 141
user profiles 24
Introduction 9


J                                                 N
Java Report Panel 91                              navigating
     launching 92                                     reports 74
Java Report Panel seeJava Report Panel            nested prompts 72
Java script files                                 NT Challenge Mode authentication 20
     drilling 85
java.util.Properties 26, 56                       O
JSP
                                                  objects
     importing code 24
                                                       query results 97
     reading a user profile 26
                                                  Online Customer Support 123
                                                  opening
L                                                      documents 13, 46
landscape layout 115                              out of scope drills 80, 87, 97
layout 115
line graph 112                                    P
listing
                                                  packages
      documents 47
                                                       java.util.Properties 56
lists of values 68–74
                                                  page
      batched 72
                                                       layout 115
      chunking 72
                                                  page decoration 114
      constrained prompts, and 69
                                                  paper size 115
      displaying 68
                                                  passwords 19
      multicolumn 70
                                                       storage token 36
      prompts in (nested) 72
                                                  PDF
      refreshing 73
                                                       displaying reports 60
log in and log out 16
                                                       output format 63
logins 19
                                                  .pdf see PDF
LOV see lists of values
                                                  pie chart 113
                                                  portrait layout 115
M                                                 prompts 64–74
managing                                               conditions 99
     documents 34                                      constrained 69
Microsoft Excel                                        context 64, 74
     displaying reports 60                             drilling 87
     output format 63                                  entering values 70, 71
migration 11, 48                                       lists of values 68
multivalued prompts 69                                 multicolumn lists of values 70




                                         Developing with Web Intelligence Report Engine SDK 142
multivalued 69
    nested 72


    storage tokens 36                             report maps 74
properties 57                                         snapshots, and 88
    documents 56                                  Report Panel see Java Report Panel
                                                  ReportEngine object
Q                                                     closing 32
                                                  ReportEngine SDK
queries 90
                                                      creating a ISessionMgr object 18
    editing 96
                                                      exceptions 29
    executing 100
                                                      features 34
query conditions 88, 98
                                                      hello world 16
query strings
                                                      login 19
    drilling 79, 79, 79, 81, 81, 82
                                                      migration 11
                                                      packages 10
R                                                     referencing classes 17
radar & scatter graph 113                         ReportEngine sessions
REBean                                                closing 21
     creating a ReportEngine object 30            reports
     exceptions 29                                    drilling 77, 80, 85
     features 10                                      filters 87
     formatting reports 101                           formatting 101–115
recordsets 117–120                                    report maps 74
     changing records 119                             viewing all the reports in a document 61
     fields 118                                   repository
referencing                                           opening documents 46
     CESDK 17                                         sending documents 51
     ReportEngine SDK classes 17                  RESDK
refreshing                                            building data providers 89
     document lists 47                                document properties 56
     documents 13, 64, 73                         resolving universe contexts 74
     lists of values 73                           resources 122
renaming categories 44                            result objects 97
RENET                                             running queries 100
     exceptions 29
     features 10
                                                  S
report expressions 107, 108
                                                  save to corporate see publishing
     adding to axes 110
                                                  saving documents 48
     breaks 111
                                                  scope of analysis 78, 80, 97
     calculations 111
                                                      handling manually 87
     sorting 111



                                         Developing with Web Intelligence Report Engine SDK 143
scripts
     drilling 85


sections                                              transparent drill out of cube 80
     creating 107                                     traversing
sending documents 50–53                                    categories 41
session ID                                                 report maps 74
     cookies, and 20                                  triggers
sessions                                                   generating storage tokens 36
     closing 21
     creating 20, 46                                  U
setting
                                                      universes 90
     drill actions 83
                                                          resolving contexts 74
     drill parameters 83
                                                      user names 19
     user profiles 27
                                                      user profiles 24, 47
settings in user profiles 24
                                                          accessing 25
slice drill action 83
                                                          adding to 28
snapshots 88
                                                          setting 27
SQL
                                                      user rights 47
     executing 100
                                                          categories, for 39
storage tokens
                                                          transparent drill out of cube 80
     advantages 38
                                                      user sessions see Business Objects Enterprise
     browser navigation 38
                                                                    sessions
     generation triggers 36
     life cycle 35
     opening documents 46                             V
     viewing reports 61                               values
support                                                   prompts 68
     customer 123                                     viewing
     locations 123                                        binary view 61
     technical 123                                        reports 59–75
     web site 123
                                                      W
T                                                     web
tables                                                    customer support 123
     cross tables 112                                     getting documentation via 122
     vertical and horizontal 111                          useful addresses 124
technical support 123                                 web sites
temporary files                                           support 123
     storage tokens 35                                    training 124
training, on Business Objects products 124




                                             Developing with Web Intelligence Report Engine SDK 144
Index




Developing with Web Intelligence Report Engine SDK 145
Index




146 Developing with Web Intelligence Report Engine SDK

More Related Content

PDF
Citrix admin
PDF
PANOS 4.1 Administrators Guide
PDF
Hp man ppm9.20_whats_new_pdf
PDF
Ppm7.5 cmd tokval
PDF
Deployment guide series ibm tivoli access manager for e business v6.0 sg247207
PDF
Ppm7.5 demand cg
PDF
Xi3 ds administrators_guide_en
PDF
Citrix admin
PANOS 4.1 Administrators Guide
Hp man ppm9.20_whats_new_pdf
Ppm7.5 cmd tokval
Deployment guide series ibm tivoli access manager for e business v6.0 sg247207
Ppm7.5 demand cg
Xi3 ds administrators_guide_en

What's hot (17)

PDF
Solmanfocusedbuild
PDF
Share point configuration guidance for 21 cfr part 11 compliance
PDF
Tivoli data warehouse version 1.3 planning and implementation sg246343
PDF
Sg247692 Websphere Accounting Chargeback For Tuam Guide
PDF
Tivoli data warehouse 1.2 and business objects redp9116
PDF
Amdin iws7 817-2179-10
PDF
Cloud Infrastructure Architecture Case Study
 
PDF
Supplemental pack ddk
PDF
R Exts
PDF
Supply chain management
PDF
SAP_HANA_Modeling_Guide_for_SAP_HANA_Studio_en
PDF
B4X Custom Views v1.9
PDF
Tape automation with ibm e server xseries servers redp0415
PDF
Ibm tivoli intelligent think dynamic orchestrator pre proof of-concept cookbo...
PDF
Tivoli business systems manager v2.1 end to-end business impact management sg...
Solmanfocusedbuild
Share point configuration guidance for 21 cfr part 11 compliance
Tivoli data warehouse version 1.3 planning and implementation sg246343
Sg247692 Websphere Accounting Chargeback For Tuam Guide
Tivoli data warehouse 1.2 and business objects redp9116
Amdin iws7 817-2179-10
Cloud Infrastructure Architecture Case Study
 
Supplemental pack ddk
R Exts
Supply chain management
SAP_HANA_Modeling_Guide_for_SAP_HANA_Studio_en
B4X Custom Views v1.9
Tape automation with ibm e server xseries servers redp0415
Ibm tivoli intelligent think dynamic orchestrator pre proof of-concept cookbo...
Tivoli business systems manager v2.1 end to-end business impact management sg...
Ad

Similar to Resdk java custo_webi_dg (20)

PDF
Deployment guide series ibm tivoli compliance insight manager sg247531
PDF
Deployment guide series ibm tivoli compliance insight manager sg247531
PDF
Solution deployment guide for ibm tivoli composite application manager for we...
PDF
Certification guide series ibm tivoli usage and accounting manager v7.1 imple...
PDF
It asset management processes using tivoli asset manager for it sg247601
PDF
It asset management processes using tivoli asset manager for it sg247601
PDF
It asset management processes using tivoli asset manager for it sg247601
PDF
Mysql To Db2 Conversion Guide Ibm Redbooks
PDF
Deployment guide series ibm tivoli usage and accounting manager v7.1 sg247569
PDF
irmpg_3.7_python_202301.pdf
PDF
Ibm web sphere datapower b2b appliance xb60 revealed
PDF
ABAP_RESTful_Programming_Model_EN[1].pdf
PDF
Performance tuning for content manager sg246949
PDF
Certification guide series ibm tivoli provisioning manager express for softwa...
PDF
Deployment guide series ibm tivoli access manager for e business v6.0 sg247207
PDF
Business objects51en
PDF
MFG/PRO QAD Reporting Framework Document Guide
PDF
Mongo db security-guide
PDF
Mongo db security guide
PDF
Pc 811 troubleshooting_guide
Deployment guide series ibm tivoli compliance insight manager sg247531
Deployment guide series ibm tivoli compliance insight manager sg247531
Solution deployment guide for ibm tivoli composite application manager for we...
Certification guide series ibm tivoli usage and accounting manager v7.1 imple...
It asset management processes using tivoli asset manager for it sg247601
It asset management processes using tivoli asset manager for it sg247601
It asset management processes using tivoli asset manager for it sg247601
Mysql To Db2 Conversion Guide Ibm Redbooks
Deployment guide series ibm tivoli usage and accounting manager v7.1 sg247569
irmpg_3.7_python_202301.pdf
Ibm web sphere datapower b2b appliance xb60 revealed
ABAP_RESTful_Programming_Model_EN[1].pdf
Performance tuning for content manager sg246949
Certification guide series ibm tivoli provisioning manager express for softwa...
Deployment guide series ibm tivoli access manager for e business v6.0 sg247207
Business objects51en
MFG/PRO QAD Reporting Framework Document Guide
Mongo db security-guide
Mongo db security guide
Pc 811 troubleshooting_guide
Ad

Recently uploaded (20)

PDF
CMI College 2025- English presentation of the project
PPTX
ILO Code 174 .pptx
PDF
3 Best IPTV Reseller Programs Providers (2025)
PPTX
Health_System_in_India_Oasrganization_BSc_Nursing.pptx
PDF
KarolG CarRace Sequence...why a 40 character minimum for a title?
PPTX
continuous_steps_relay.pptx. Another activity
PPTX
Picture Perception - a constructive narrative
PDF
Fortnite: Eminem Battles Robot Slim Shady
PPTX
G.A.M.E. O.N.! (General — Art — Mythology — Entertainment — Obscure Naata) [2...
PDF
Can You Imagine? Read along and let’s see!
PPTX
Difference Between Saving slides And Investment Slides.pptx
PPTX
Goal - its setting ,tracking and relevance
PDF
mnbnyuynhncf ytdnbvdfghdfhghdhdfhdghdghdghghgfhfh
PPTX
701301-Happy Birthday Slideshow Template.pptx
PDF
Watch Eddington (2025) – A Town Torn in Two
PPTX
eNTREP OHS 5jhjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjs.pptx
PPTX
Introduction to NGO’s098765789709876.pptx
PDF
Best IPTV Service Providers in the UK (2025) – Honest Reviews & Top Picks
PDF
CityofHorror_v1.1.pdf manual en español i
PDF
D009 - Lahoo Ke Pyaase. its a hindi comics
CMI College 2025- English presentation of the project
ILO Code 174 .pptx
3 Best IPTV Reseller Programs Providers (2025)
Health_System_in_India_Oasrganization_BSc_Nursing.pptx
KarolG CarRace Sequence...why a 40 character minimum for a title?
continuous_steps_relay.pptx. Another activity
Picture Perception - a constructive narrative
Fortnite: Eminem Battles Robot Slim Shady
G.A.M.E. O.N.! (General — Art — Mythology — Entertainment — Obscure Naata) [2...
Can You Imagine? Read along and let’s see!
Difference Between Saving slides And Investment Slides.pptx
Goal - its setting ,tracking and relevance
mnbnyuynhncf ytdnbvdfghdfhghdhdfhdghdghdghghgfhfh
701301-Happy Birthday Slideshow Template.pptx
Watch Eddington (2025) – A Town Torn in Two
eNTREP OHS 5jhjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjs.pptx
Introduction to NGO’s098765789709876.pptx
Best IPTV Service Providers in the UK (2025) – Honest Reviews & Top Picks
CityofHorror_v1.1.pdf manual en español i
D009 - Lahoo Ke Pyaase. its a hindi comics

Resdk java custo_webi_dg

  • 1. Report Engine Java Developer Guide BusinessObjects Enterprise XI R2 Windows and UNIX
  • 2. Copyright If you find any problems with this documentation, please report them to Business Objects S.A. in writing at [email protected]. Copyright © Business Objects S.A. 2004. All rights reserved. Trademarks Business Objects, the Business Objects logo, Crystal Reports, and Crystal Enterprise are trademarks or registered trademarks of Business Objects SA or its affiliated companies in the United States and other countries. All other names mentioned herein may be trademarks of their respective owners. Patents Business Objects owns the following U.S. patents, which may cover products that are offered and sold by Business Objects: 5,555,403, 6,247,008 B1, 6,578,027 B2, 6,490,593 and 6,289,352. Third-party Business Objects products in this release may contain redistributions of software licensed contributors from third-party contributors. Some of these individual components may also be available under alternative licenses. A partial listing of third-party contributors that have requested or permitted acknowledgments, as well as required notices, can be found at: http://www.businessobjects.com/thirdparty
  • 3. Contents Chapter 1 Introduction 7 Chapter 2 Introduction to ReportEngine SDK 9 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Packages for customizing BusinessObjects Enterprise XI R2 . . . . . . . . . . 10 Migrating to BusinessObjects XI R2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 A typical ReportEngine SDK application . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Installing ReportEngine SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Chapter 3 Application Essentials 15 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 “Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 BusinessObjects Enterprise sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Implementing “Hello World” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 User preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Reporting essentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Chapter 4 Document Management 33 Document types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Document state: storage tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Organizing documents in categories and folders . . . . . . . . . . . . . . . . . . . . 38 Working with documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Document properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Chapter 5 Viewing Reports 59 Viewing reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Handling prompts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Displaying a report map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Developing with Web Intelligence Report Engine SDK 3
  • 4. Chapter 6 Drilling in Web Intelligence Reports 77 Introduction to drilling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Drilling in reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 Chapter 7 Building and Editing Data Providers 89 Data providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 Building a data provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 Executing queries and retrieving the data . . . . . . . . . . . . . . . . . . . . . . . . 100 Chapter 8 Formatting Reports 101 Creating and editing the document structure . . . . . . . . . . . . . . . . . . . . . . 102 Creating and editing cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Page layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Appendix A Working with Recordsets 117 Anatomy of a recordset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 Appendix B Business Objects Information Resources 121 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Customer support, consulting and training . . . . . . . . . . . . . . . . . . . . . . . . 123 Useful addresses at a glance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Appendix C Logging with ReportEngine SDK Overview 127 Logging Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Activating logging by editing the configuration files . . . . . . . . . . . . . . . . . 129 Appendix D Configuring ReportEngine using webi.properties 135 Developing with Web Intelligence Report Engine SDK 4
  • 5. Examples Referencing BusinessObjects Enterprise SDK 17 Instantiating the ISessionMgr class 18 HTML form for gathering a user’s login information 19 Establishing a session 20 Printing a user’s preferences 26 Setting a user’s report panel preference to Java 27 Adding a new preference to a user’s profile 29 Referencing the ReportEngine SDK 30 Instantiating a ReportEngine an IReportEngine object 31 Instantiating a ReportEngine objects depending on file type 31 Storage token life cycle 36 how to check that a user has the right to create categories 40 Traversing the category tree recursively 41 Retrieve a user’s Inbox and Favorites folder IDs 43 Creating a new folder or category 44 Moving and renaming categories or folders 45 Retrieve the properties for a category 45 Displaying a document list 47 Save a document 48 Scheduling a document 49 Retrieve the list of groups to which a user belongs 51 Sending a document to folders and categories 52 Send a document to the inbox of groups of users 54 Getting the name of a document 56 Adding a property to a document 57 Viewing all the reports in a Web Intelligence document 61 Viewing a report in a Web Intelligence document 62 Viewing a report in Microsoft Excel format 63 Handling a single, simple prompt 64 Developing with Web Intelligence Report Engine SDK 5
  • 6. Examples Dynamically creating input names 66 Handling many, simple prompts 66 Displaying a simple list of values 68 Handling multivalued prompts 70 Handling multicolumn lists of values 70 Order of filling a hierarchy of nested prompts 72 Handling nested prompts 72 Refreshing a list of values containing nested prompts 73 Traversing the report map for a Web Intelligence document 74 Defining the query string parameters 82 Setting the drill path 84 Displaying the drilled report 86 Launching the Java Report Panel 94 Building a data provider 96 Creating a simple condition 98 Structure of a complex condition 99 Including a prompt in a condition 99 Creating a blank document 102 Creating a document structure 105 Creating an attachment 107 Editing the sections of a report 107 Building a report: adding expressions to axes 110 Accessing the values in a recordset 119 6 Developing with Web Intelligence Report Engine SDK
  • 8. 1 Introduction About this guide About this guide This guide describes the processes and procedures for creating web applications using BusinessObjects Enterprise SDK and the ReportEngine SDK package. Who should read this guide To use the BusinessObjects Enterprise SDK and ReportEngine SDKs you need a working knowledge of the concepts of distributed computing systems, HTTP server technology, and JSP development. You also need a basic knowledge of the products in the BusinessObjects product line. Familiarity with BusinessObjects Enterprise is assumed. Business Objects information resources For more information and assistance, see “Business Objects Information Resources” on page 121. This appendix describes the Business Objects documentation, customer support, training, and consulting services, with links to online resources. 8 ReportEngine Developer Guide
  • 9. ReportEngine Developer Guide Introduction to ReportEngine SDK chapter
  • 10. 1 Introduction to ReportEngine SDK Overview Overview ReportEngine SDK consists of a number of Java packages. Typically, every application that uses these packages must implement the same kinds of workflows. This chapter briefly introduces ReportEngine SDK and the workflows a typical application needs to implement. Packages for customizing BusinessObjects Enterprise XI R2 There are two packages for customizing BusinessObjects Enterprise: • BusinessObjects Enterprise SDK The "platform package," provides platform functions of the Business Objects servers, and document scheduling. • ReportEngine SDK This package plugs into Business Objects Enterprise SDK. It provides the functions of the Web Intelligence and Desktop Intelligence Report Engines. BusinessObjects Enterprise SDK ReportEngine SDK Crystal Enterprise Documents Web Intelligence documents View View Refresh Refresh Analyze Analyze Create† Format† Platform functions Manage sessions and users Desktop Intelligence documents View Manage documents and categories Refresh List universes and folders Schedule documents Analyze† Metadata (universe) Explore† †Web Intelligence Documents for REBean Only BusinessObjects Enterprise SDK is called the platform package because it exposes the platform functions of the Business Objects servers. ReportEngine SDK exposes the functions of the Desktop Intelligence and Web Intelligence Report Engines. 10 ReportEngine Developer Guide
  • 11. Introduction to ReportEngine SDK Migrating to BusinessObjects XI R2 1 Migrating to BusinessObjects XI R2 If you already have a business intelligence solution based on previous versions of ReportEngine SDK you might need to migrate your solution. Migration affects the following areas: • referencing components of the BusinessObjects Enterprise platform • controlling user sessions • listing and navigating through folders and categories • managing and viewing documents • handling security commands • using the various dictionaries • deploying your application For more information on migration issues see the Migrating Business Objects Customized Applications to BusinessObjects XI R2 guide. A typical ReportEngine SDK application Not all applications that use ReportEngine SDK have the same features, but all typically provide features for listing and viewing documents contained in the BusinessObjects Enterprise Central Management System (CMS). A more sophisticated application could also include features such as document creation and report formatting. Application essentials Every application that uses ReportEngine SDK needs to perform common tasks such as importing the appropriate packages, and creating and managing the user’s BusinessObjects Enterprise session (login). Every application should also take user profiles into account and ensure that errors are handled properly. See “User rights for categories and folders” on page 39 and “User preferences” on page 24. Document management Document management features include the ability to list the documents that the current user can view, and, depending on the user’s rights, allowing the user to browse and manage categories and folders used to organize the documents. Document management can also include features such as saving, and scheduling documents. ReportEngine Developer Guide 11
  • 12. 1 Introduction to ReportEngine SDK A typical ReportEngine SDK application Viewing reports An application that provides for viewing documents can display them using the default DHTML format. It is easy to extend this to handle documents that contain prompts, and to provide drilling functions. These extended functions have to be handled when a document is refreshed. How you provide viewing features depends on the type of document opened. The report-viewing part of the application should include routines for viewing reports in the following document types: • Web Intelligence (*.wid) • Crystal Reports documents • Desktop Intelligence (*.rep) • other document types, for example Adobe® Acrobat®, Microsoft® Excel or XML format. See “Viewing reports” on page 60 for a full listing of available formats. Creating documents: building and editing data providers To give users the ability to create documents and generate their own reports, you need to provide them with tools to build and edit data providers. A data provider encapsulates information about an information source and the query that defines the information retrieved. Creating a document essentially means creating a data provider. You can use the same classes to provide different features for editing a query, such as adding conditions and changing the scope of analysis. Formatting documents Formatting documents involves creating and positioning the elements of a report (blocks, sections, and cells) in the appropriate report structure. Using ReportEngine SDK you can build reports from scratch. ReportEngine SDK includes classes for controlling report page decoration (fonts, colors, headers, and footers) and layout. 12 ReportEngine Developer Guide
  • 13. Introduction to ReportEngine SDK A typical ReportEngine SDK application 1 Open document workflow The following diagram shows the workflow for opening a document. Client Report Engine pages SDK open a document check for prompts fill prompts until there are none left unfilled fill document toolbar get the report map fill report map get the report in the requested format fill rendering area Refresh document workflow The following diagram shows the workflow for refreshing a document. Client Report Engine pages SDK <open document workflow> update document toolbar refresh the report refresh check for prompts fill prompts until there are none left unfilled set the position fill document toolbar get the report map fill report map fill rendering get the report in the requested format area ReportEngine Developer Guide 13
  • 14. 1 Introduction to ReportEngine SDK Installing ReportEngine SDK Installing ReportEngine SDK Installing Business Objects components ReportEngine SDK components are added to the development machine when BusinessObjects Enterprise XI R2 is installed on the system. To develop a custom ReportEngine SDK application it is necessary to connect to a running BusinessObjects Enterprise server, however, the development environment does not have to be on the same machine as the BusinessObjects Enterprise Server. Install ReportEngine SDK components on a development machine by: 1. Run BusinessObjects Enterprise XI R2 installer. 2. Click Next on the BusinessObjects Enterprise XI R2 Installation Wizard panel. 3. Select the I accept the License Agreement button in the License Agreement panel. 4. Click Next. 5. Select the Perform Server Installation 6. Click Next. 7. Enter your corporate information and keycode. 8. Click Next. 9. Specify the destination folder in the Destination folder text box. 10. Click Next. 11. Select the Custom button 12. Click Next. 13. Deselect all BusinessObjects Enterprise Features. 14. Enable the SDK products feature. To install J2EE components only, deselect the SDK products feature and install the Java features sub-component. 15. Click Next. 16. Click Next. This installs all components necessary to develop custom Business Objects applications; Java libraries are installed and registered correctly. 14 ReportEngine Developer Guide
  • 16. 2 Application Essentials Overview Overview Before providing viewing, reporting, and editing functions ReportEngine SDK applications need to perform basic tasks, such as referencing the appropriate package and creating a BusinessObjects Enterprise session for the user. This chapter covers the essential concepts and tasks that all applications that customize BusinessObjects Enterprise must use. “Hello World” The simplest application you can write with BusinessObjects Enterprise SDK is one that creates a BusinessObjects Enterprise session, that is, provides log in and log out functions. This is the basis for building much more sophisticated applications that provide, for example, functions to list, view and create documents, and attach them to hierarchical categories. get name and open a password Name = “janderson” session from user Pass = “*******” close session display “Hello World” and a logout link Table 2-1 Application for logging in and out of BusinessObjects Enterprise This application gathers login details from the user, and sends the details to another page which uses BusinessObjects Enterprise SDK to try to open a BusinessObjects Enterprise session. If the session is successfully created, the application displays a “Hello World” message and the option to log out. When 16 ReportEngine Developer Guide
  • 17. Application Essentials “Hello World” 2 the user clicks the logout link, the application closes the user’s BusinessObjects Enterprise session with BusinessObjects Enterprise SDK and displays the first page again. Each page that uses BusinessObjects Enterprise SDK must: • reference BusinessObjects Enterprise SDK • create or reference an IEnterpriseSession object • create or reference an IInfoStore object See “Implementing “Hello World”” on page 21 for code that implements this application. Referencing BusinessObjects Enterprise SDK Referencing BusinessObjects Enterprise SDK gives your web application access to the BusinessObjects Enterprise platform functions exposed by the SDK. Note: You must use BusinessObjects Enterprise SDK prior to using ReportEngine SDK. To develop a Java application Business Objects recomments that you add all libraries found in the <BusinessObjectsHome>common3.5javalib into the WEB-INFlib directory of your JSP project. Referencing BusinessObjects Enterprise SDK To reference BusinessObjects Enterprise SDK, import the BusinessObjects Enterprise packages. Example: Referencing BusinessObjects Enterprise SDK To import BusinessObjects Enterprise SDK packages, add the following line to pages that use the packages. <% page import="com.crystaldecisions.sdk.framework.*, com.crystaldecisions.sdk.occa.infostore.*, com.crystaldecisions.sdk.occa.pluginmgr.*, com.crystaldecisions.sdk.plugin.*, com.crystaldecisions.sdk.plugin.desktop.server.*, com.crystaldecisions.sdk.occa.infostore.*, com.crystaldecisions.sdk.plugin.destination.smtp.*, com.crystaldecisions.sdk.plugin.destination.managed.*, com.crystaldecisions.sdk.exception.SDKException, com.crystaldecisions.sdk.occa.security.*, com.crystaldecisions.sdk.plugin.desktop.user.*, com.crystaldecisions.sdk.properties.*, com.businessobjects.sdk.plugin.desktop.webintelligence.CeWeb IntelligenceRightID"%> ReportEngine Developer Guide 17
  • 18. 2 Application Essentials BusinessObjects Enterprise sessions You need to include this line in every page that uses BusinessObjects Enterprise SDK. Creating an new user session In BusinessObjects Enterprise SDK the ISessionMgr lets a user to log in to the BusinessObjects Enterprise server and create a session. Session information is stored in the IEnterpriseSession object returned by this method. Every session has a corresponding IEnterpriseSession object which is used to access ReportEngine SDK. Creating an ISessionMgr object To create a user session for an application that uses BusinessObjects Enterprise SDK, you must first instantiate a new ISessionMgr object. Example: Instantiating the ISessionMgr class ISessionMgr mySessionMgr = CrystalEnterprise.getSessionMgr(); BusinessObjects Enterprise sessions Every user of InfoView requires a BusinessObjects Enterprise session before entering and using the system. The BusinessObjects Enterprise session represents the user’s current interaction with BusinessObjects Enterprise. A user’s BusinessObjects Enterprise session provides access to the user’s details, and objects that are subject to the rights of the user, for example, the list of universes that the current user can use to create documents. You must create a BusinessObjects Enterprise session for the user: it is the key part of the log in and authentication process. To create a session for a user: 1. Get the user’s login information: • name • password • the Central Management System (CMS) the user wishes to log into • authentication type (Enterprise, LDAP, winAD) 2. Establish a valid BusinessObjects Enterprise session for the user. 18 ReportEngine Developer Guide
  • 19. Application Essentials BusinessObjects Enterprise sessions 2 Getting login information The simplest way to get a user’s login information is to use an HTML form into which the user enters a name and a password. When the user submits the form, the values for the fields are passed via the query string to a page that processes the values. Example: HTML form for gathering a user’s login information <FORM name="LoginForm" action="Login.jsp" method="POST"> <TABLE><TR> <TD>Name:</TD> <TD><input name="Name"></TD> </TR> <TR> <TD>Password:</TD> <TD><input type="password" name="pass"></TD> </TR> <TR> <TD>Central Management System:</TD> <TD><input name="CMS"></TD> </TR> <TR> <TD>Authentication:</TD> <TD> <select name='auth'> <option value='secEnterprise'>Enterprise</option> <option value='secLDAP'>LDAP</option> <option value='secLDAP'>WinAD</option> </select> </TD> </TR> <TR> <TD><input id=submit1 name=submit1 type=submit value="Login"></TD> </TR></TABLE> </FORM> When the user enters login information and clicks the Login button, the values for the fields are passed to Login.jsp in the query string parameters Name and Pass. Since the method attribute of the form is set to POST, these values will not be visible in the URL. Authentication The way you monitor passwords depends on how BusinessObjects Enterprise passwords have been set up by the BusinessObjects Enterprise system administrator. There are two settings available to the system administrator which you can use as the basis for the login procedure in your own application: ReportEngine Developer Guide 19
  • 20. 2 Application Essentials BusinessObjects Enterprise sessions • Enterprise Mode This mode requires from the user to submit a user name and password which are unique to BusinessObjects Enterprise (and may be different from their network name/password combination). • LDAP Mode This mode requires the user to submit a user name and password which are stored on a corporate LDAP server. • WinAD Mode This mode requires the user to submit a user name and password which are stored on a Windows Authentication Server. For more information on authentication in Windows, see the BusinessObjects Enterprise XI R2 Administrator’s Guide. Establishing a valid BusinessObjects Enterprise user’s session To establish a valid BusinessObjects Enterprise user’s session: 1. Try to create an IEnterpriseSession object for the user. 2. If the IEnterpriseSession object is valid, store this object in the user’s session attributes. 3. Create an IInfoStore object and store in the user’s session attributes. These steps are usually done together and are normally followed by redirecting the user to an appropriate page: a welcome page or back to the login page, depending on the validity of the session. Example: Establishing a session The following code fragment illustrates how to establish a BusinessObjects Enterprise session. ISessionMgr mySessionMgr = CrystalEnterprise.getSessionMgr(); IEnterpriseSession eSession; try { eSession = mySessionMgr.logon(name, password, CMS, auth); if (eSession != null){ session.setAttribute("EnterpriseSession", enterpriseSession); IInfoStore iStore = (IInfoStore) enterpriseSession.getService("InfoStore"); session.setAttribute("InfoStore", iStore); } catch (SDKException sdkEx){ ; } 20 ReportEngine Developer Guide
  • 21. Application Essentials Implementing “Hello World” 2 Retrieving a BusinessObjects Enterprise session Once you have established a valid BusinessObjects Enterprise session for the user, you can retrieve it from the user’s session attributes. Closing a BusinessObjects Enterprise session To close a session, that is, log a user out of BusinessObjects Enterprise, use IEnterpriseSession.logoff. Closing a session is important: • It frees the resources held by the user’s BusinessObjects Enterprise session. • It forces other users to start their own sessions rather than just taking over an existing session. Note: See “logout.jsp” on page 24 for an example of how to close a BusinessObjects Enterprise session. BusinessObjects Enterprise session time-out The time-out of a Business Objects Enterprise SDK Session is the life time of the IEnterpriseSession object; the session is destroyed when the object is destroyed. Business Objects recommends that you store the users IEnterpriseSession object in the application server session objects, in this way the user session have the exact same time out as the Application server session. Implementing “Hello World” Following is an implementation of the Hello World application discussed on page 16. To run this application you need to have installed BusinessObjects Enterprise and established a Business Objects Central Management System. For more information, see the Installation and Configuration Guide for Windows or UNIX. ReportEngine Developer Guide 21
  • 22. 2 Application Essentials Implementing “Hello World” index.jsp login.jsp Name = “janderson” Pass = “********” logout.jsp home.html In this implementation index.jsp displays a form which collects the user’s login information which is passed to login.jsp. Login.jsp attempts to create a session and IInfoObject for the user. If the operation is successful, login.jsp redirects to home.html which displays the “Hello World” message and a link to logout.jsp. When the user clicks the logout link, logout.jsp closes the session and displays index.jsp again. index.jsp <html> <body> <h1>Create a BusinessObjects Enterprise Session</h1> <form name="LoginForm" action="login.jsp" method="POST"> <table><tr> <td>Name: </td> <td><input name="Name"></td> </tr> <tr> <td>Password: </td> <td><input type="password" name="Pass"></td> </tr> <TR> <TD>Crystal Management System:</TD> <TD><input name="CMS"></TD> </TR> <TR> <TD>Authentication:</TD> <TD> <select name='auth'> <option value='secEnterprise'>Enterprise</ option> <option value='secLDAP'>LDAP</option> </select> </TD> 22 ReportEngine Developer Guide
  • 23. Application Essentials Implementing “Hello World” 2 </TR> <tr> <td><input id=s1 name=s1 type=submit value="Login"></ td> </tr></table> </form> </body> </html> login.jsp This page is opened when the user clicks Login in the form LoginForm described on page 19. The user name and password used for the login are passed from the HTML form in the query string parameters Name and Pass. <%@ page import="com.crystaldecisions.sdk.framework.CrystalEnterp rise" %> <%@ page import="com.crystaldecisions.sdk.framework.IEnterpriseSe ssion" %> <%@ page import="com.crystaldecisions.sdk.framework.ISessionMgr" %> <%@ page import="com.crystaldecisions.sdk.exception.SDKException" %> <% String CMS = request.getParameter("cms"); String userID = request.getParameter("user"); String password = request.getParameter("password"); String auth = request.getParameter("auth"); if ( CMS == null) CMS = ""; if ( userID == null) userID = ""; if ( password == null) password = ""; if ( auth == null) auth = ""; IEnterpriseSession enterpriseSession; try { ISessionMgr mySessionMgr = CrystalEnterprise.getSessionMgr(); enterpriseSession = mySessionMgr.logon(userID, password, CMS,auth); if (enterpriseSession != null) {//Create and store useful objects for the session. session.setAttribute("EnterpriseSession", enterpriseSession); IInfoStore iStore = (IInfoStore) enterpriseSession.getService("InfoStore"); session.setAttribute("InfoStore", iStore); response.sendRedirect("home.html"); } else response.sendRedirect("index.jsp"); ReportEngine Developer Guide 23
  • 24. 2 Application Essentials User preferences } catch( SDKException mySDKExept) { response.sendRedirect("index.jsp"); } %> home.html <html> <body> <h1>Create a Web Intelligence Session: Home Page</h1> <p>Hello World!</p> <a href="logout.jsp">Log out</a> </body> </html> logout.jsp <%@ page import="com.crystaldecisions.sdk.framework.IEnterpriseSe ssion" %> <% IEnterpriseSession enterpriseSession; enterpriseSession =(IEnterpriseSession) session.getAttribute("EnterpriseSession"); session.removeAttribute("EnterpriseSession"); if(enterpriseSession != null) { enterpriseSession.logoff(); enterpriseSession = null; } %> User preferences Users can set their InfoView and ReportEngine viewing options using the Preferences page in InfoView or BusinessObjects Enterprise SDK. When designing a ReportEngine SDK application you should take this into account. For example, if the user wants to use the Java version of the Report Panel for creating and editing documents, then you need to design your application so that it can display the Java Report Panel rather than the DHTML Report Panel. 24 ReportEngine Developer Guide
  • 25. Application Essentials User preferences 2 Accessing InfoView user preferences With BusinessObjects Enterprise SDK you can get, set and add new preferences in a user’s profile. Standard preferences and possible settings are: BusinessObjects Enterprise user preference variables, values and meaning. Variable Name Possible Meaning Values webi_view P View documents in PDF format. I View Documents in Interactive format. H View Documents in DHTML format. (default) webi_panel java Create documents using the Java Report Panel. (default) html Create documents using the HTML Report Panel. DOCUMENT_WIStartNewDrill duplicate Start the drill action in a duplicate report. existing Start the Drill action in the current report. (default) DOCUMENT_WIPromptDrillOutScope N Prompt if drill requires additional data. (default) Y Do not prompt if Drill requires additional data. DOCUMENT_WISyncDrillBlocks N Synchronize Drill on report blocks. (default) Y Do not Synchronize Drill on report blocks. ReportEngine Developer Guide 25
  • 26. 2 Application Essentials User preferences Variable Name Possible Meaning Values DOCUMENT_WIDrillBar N Show the Drill bar. Y Hide the Drill bar. (default) Note: other applications may have their own user settings which are stored in the user profile. For more information see “Adding custom options to a user’s profile” on page 28. Getting a user’s InfoView preferences To read the value of a user’s option: 1. Get the current user’s IUser object using an IInfoStore query. 2. Get the "desktopsettings" profile string. 3. Convert the profile string to a Map for easy manipulation and printing. Example: Printing a user’s preferences The following code functions show how to retrieve a user’s BusinessObjects Enterprise preferences and print them to an HTML response stream. <%! //Return a string containing a user’s Web Intelligence Preferences String getWebiPrefs(IInfoStore iStore, int uId){ String prefs = ""; String sQuery = "SELECT SI_ID, SI_NAME, SI_DATA FROM” + “ CI_SYSTEMOBJECTS WHERE SI_ID = '" + uId + "'"; IInfoObjects users = null; try{ users = iStore.query(sQuery); if (users.size() > 0){ IUser user = (IUser)users.iterator().next(); prefs = user.getProfileString("desktopsettings"); } }catch(SDKException sEx){ return ““; } return prefs; } //Convert a String of preferences to a Map Map webiPrefsToMap(String prefs){ StringTokenizer st = new StringTokenizer (prefs, "&"); Map webiPrefs = null; while (st.hasMoreTokens()) { String s2 = st.nextToken(); StringTokenizer st2 = new StringTokenizer (s2, "="); if (st2.countTokens() == 2) 26 ReportEngine Developer Guide
  • 27. Application Essentials User preferences 2 webiPrefs.put(st2.nextToken(), st2.nextToken()); } return webiPrefs; } %> The following code fragment shows how to use the functions declared above to print a user’s BusinessObjects Enterprise preferences to an HTML stream. <% int userID = myIEnterpriseSession.getUserInfo().getUserID(); PrintWriter myWriter = response.getWriter(); String prefs = getWebiPrefs(myIInfoStore, userID); Map prefsMap = webiPrefsToMap(prefs); if (prefsMap != null){ Iterator itr = prefsMap.entrySet().iterator(); while(itr.hasNext()) { Map.Entry current = (Map.Entry)itr.next(); myWriter.print ( current.getKey() + "=" + current.getValue() + "<br>"); } } %> Setting an option in a user profile To set an option: 1. Get a user’s preferences. 2. Update a standard option in the Map continuing the user preferences. 3. Convert the Map to a String. 4. Update the user profile with IInfoStore.commit. Example: Setting a user’s report panel preference to Java The following code functions enables a user’s profile to be updated to use the Java Report Panel. <%! //Update the user’s Web Intelligence preferences. void setWebiPrefs(IInfoStore iStore, String prefs, int uId) { String sQuery = "SELECT SI_ID, SI_NAME, SI_DATA FROM CI_SYSTEMOBJECTS WHERE SI_ID = '" + uId + "'"; IInfoObjects users = null; try{ users = iStore.query(sQuery); if (users.size() > 0){ ReportEngine Developer Guide 27
  • 28. 2 Application Essentials User preferences IUser user = (IUser)users.iterator().next(); user.setProfileString("desktopsettings", prefs); iStore.commit(users); } }catch(SDKException sEx){ ; } } //Convert a preferences Map to a string String webiPrefsToSting(Map wPrefs){ StringBuffer sbWebiPrefs = new StringBuffer(); Iterator itr = wPrefs.entrySet().iterator(); while(itr.hasNext()) { Map.Entry current = (Map.Entry)itr.next(); if(sbWebiPrefs.length() != 0) sbWebiPrefs.append("&"); sbWebiPrefs.append(current.getKey()); sbWebiPrefs.append("="); sbWebiPrefs.append(current.getValue()); } return sbWebiPrefs.toString(); } %> The following code fragment shows how to use the functions declared above to update a user’s Web Intelligence preferences. <% //Update a user’s Web Intelligence preferences int userID = myIEnterpriseSession.getUserInfo().getUserID(); String prefs = getWebiPrefs(myIInfoStore, userID); Map prefsMap = webiPrefsToMap(prefs); prefsMap.put( "webi_panel", "java"); setWebiPrefs(iStore, webiPrefsToSting(prefsMap), userID); %> Note: The functions getWebiPrefs and webiPrefsToMap are declared in the example “Printing a user’s preferences” on page 26 Adding custom options to a user’s profile To add custom options to a user’s profile: 1. Get a user’s preferences. 2. Set the custom option with Map.put. When you set an option that does not exist in the user profile, Map.put creates a new option and sets it to the value you specify. 3. Convert the Map to a String. 28 ReportEngine Developer Guide
  • 29. Application Essentials Exception handling 2 4. Update the user profile with IInfoStore.commit. Example: Adding a new preference to a user’s profile The following code fragment sets a custom preference. <% //Add a custom Web Intelligence preference using functions defined in the previous examples int userID = myIEnterpriseSession.getUserInfo().getUserID(); String prefs = getWebiPrefs(myIInfoStore, userID); Map prefsMap = webiPrefsToMap(prefs); prefsMap.put( "MyPreference", "tea"); setWebiPrefs(iStore, webiPrefsToSting(prefsMap), userID); %> Note: The functions getWebiPrefs and webiPrefsToMap are declared in the example “Printing a user’s preferences” on page 26. Exception handling BusinessObjects Enterprise SDK generates exceptions of the type REException. Depending on the cause of the exception, ReportEngine SDK generates exceptions of the following type: • CommunicationException • ConfigurationException • CustomSortException • DSObjectSynchroException • FilterConditionException • NotImplementedException Exceptions and their descriptions are listed in the online reference documentation. Note: All exception classes (above) are subclasses of the REException class, Business Objects recommends using the REException.getCode when testing code. Note: You can return localized error messages message by calling REException.getLocalizedMessage. ReportEngine Developer Guide 29
  • 30. 2 Application Essentials Reporting essentials Reporting essentials All applications that view, edit or format Web Intelligence and Desktop Intelligence documents need to: • reference ReportEngine SDK • retrieve the ReportEngines service • retrieve the ReportEngine instance This links the ReportEngine and platform packages. • close the ReportEngines object Note: You use Report Engine SDK to: • View, refresh, fill prompt, drill, edit query and format Web Intelligence documents. • View refresh, fill prompt Desktop Intelligence documents. Referencing ReportEngine SDK Referencing the ReportEngine packages gives your web application access to the ReportEngine SDK functions. ReportEngine SDK allows users to work with both Web Intelligence and Desktop Intelligence documents. Use the ReportEngines factory object to retrieve the ReportEngine instance necessary to open the document type required. If the web application uses J2EE it must reference REBean. Example: Referencing the ReportEngine SDK To import the REBean package, add the following line to JSP pages that use REBean. <%@ page import= "com.businessobjects.rebean.wi.*" %> You need to include this line in every JSP page that uses REBean classes. Creating a ReportEngine object To create a ReportEngine object for an application that uses ReportEngine SDK, retrieve the ReportEngines object from the user’s IEnterpriseSession. Using the ReportEngines object you can retrieve a ReportEngine instance to open either Web Intelligence or Desktop Intelligence documents. 30 ReportEngine Developer Guide
  • 31. Application Essentials Reporting essentials 2 Once instantiated, manipulation of a ReportEngine instance is essentially the same, regardless of whether the current user has opened a Web Intelligence or Desktop Intelligence document. This eliminates the need for repeated conditional statements to check the document type and allows simpler, more streamlined code to be written. Example: Instantiating a ReportEngine an IReportEngine object To instantiate the ReportEngine object, add the following lines to one page of the web application that uses the reporting features of the ReportEngine SDK. ISessionMgr mySessionMgr = CrystalEnterprise.getSessionMgr(); enterpriseSession = mySessionMgr.logon(userID, password, CMS,auth); if (enterpriseSession != null) { ILogonTokenMgr iLManager = enterpriseSession.getLogonTokenMgr() ; ReportEngines repEngines = (ReportEngines) enterpriseSession.getService("ReportEngines"); ReportEngine widocRepEngine = (ReportEngine)repEngines.getService( ReportEngines.ReportEngineType.WI_REPORT_ENGINE); session.setAttribute("widReportEngine", widocRepEngine); } Use the “kind” attribute of a document IInfoObject to see if a Web Intelligence or Desktop Intelligence ReportEngine needs to be opened. Example: Instantiating a ReportEngine objects depending on file type String strQuery = "Select SI_KIND from CI_INFOOBJECTS” + “where SI_ID=" + strDocId; IInfoObjects iDocObjects = iStore.Query(strQuery); IInfoObject iDocObject = null; try { iDocObject = (InfoObject) iDocObjects[0]; } catch { ... } String strKind = iDocObject.Kind; ReportEngine reportEngine = null; if(strKind.Equals("Webi")) { reportEngine = reportEngines.getService( ReportEngineType.WI_ReportEngine); } else { reportEngine = reportEngines.getService( ReportEngine Developer Guide 31
  • 32. 2 Application Essentials Reporting essentials ReportEngineType.FC_ReportEngine); } Closing a ReportEngines object Just as you need to close a BusinessObjects Enterprise session, you should also close a ReportEngines when you have finished with it. To close a report engine object use ReportEngines.close(). This method deallocates the memory assigned to the object and should be called before you call IEnterpriseSession.logoff(). 32 ReportEngine Developer Guide
  • 34. 3 Document Management Overview Overview Two key parts of a typical ReportEngine SDK application are listing the documents that the user can view, and depending on the user’s rights, allowing the user to browse and manage categories and folders used to organize the documents. This chapter explains how to open, list, and work with documents. Document types With BusinessObjects Enterprise SDK you can work with: • Web Intelligence documents • Desktop Intelligence documents • Crystal Reports documents • third-party documents, for example Microsoft Excel (.xls), and Adobe Acrobat (.pdf) files Using ReportEngine SDK you can do everything Web Intelligence users can do with Web Intelligence documents: • view as DHTML • view as PDF • view as Excel • view as XML • refresh • create • categorize • delete • drill • save • schedule • send 34 ReportEngine Developer Guide
  • 35. Document Management Document state: storage tokens 3 Document state: storage tokens Storage tokens represent a state of a document at a particular stage, each time a document is edited, for example refreshed, the document state changes. Storage tokens are used to: • Retrieve the document state from page to page. • Simulate an undo action in a customized application. Storage token life cycle ReportEngine SDK generates a storage token: • when you open a document • when the microcube contents are modified or formatted When you open a document, ReportEngine SDK creates a DocumentInstance object that has a storage token. ReportEngine SDK also creates a temporary state that contain information about the document’s current state. Temporary files Executing file doc object open doc StorageToken = r0 r0 view1 A storage token is self descriptive with regards to the type of ReportEngine required to open the associated document. This means that you do not need to check the document type before opening. For information on how to control storage token, see “Configuring ReportEngine using webi.properties” on page 135. As the document changes state through the execution of JSP files, the storage token changes too, and more temporary states, representing the document’s states, are created. ReportEngine Developer Guide 35
  • 36. 3 Document Management Document state: storage tokens You can retrieve the maximum storage stack size, that is to say, the maximum number of storage tokens that can be created as a document changes state programmatically and validate that a storage token is valid by calling ReportEngine.getStorageTokenStackSize() or ReportEngine.IsStorageTokenValid. ReportEngine SDK generates a new storage token and corresponding set of temporary files at the following triggers: User interface Triggers SDK Triggers refreshing the document calling DocumentInstance.getView drilling modifying the DrillPath object creating and editing a document calling DataProvider.getResult applying new formats calling DataProvider.runQuery IDataProvider.RunQuery running a query opening a document Note: Setting a password and filling in a prompt does not cause a new token to be generated directly. However, a new storage token is generated when you commit the change using DocumentInstance.getView. Example: Storage token life cycle The following diagram shows how storage tokens change according to triggers in the user interface and the object model. It also shows how the storage tokens are passed between web pages and refer file states stored in memory that can be used to reconstruct the DocumentInstance object using the call ReportEngine.getDocumentFromStoratagetoken. In the diagram below, this call name is shortened to “get doc”. Using the storage token as an identifier for a document state, you can restore the document to any of its saved states. 36 ReportEngine Developer Guide
  • 37. Document Management Document state: storage tokens 3 e. Temporary files Executing files docInstance object 1 open docInstance StorageToken = r0 r0 GIF run query StorageToken = r0-s0 r0-s0 view1 r0-s0 2 get doc(r0-s0) GIF GIF drill StorageToken = r0-s1 r0-s1 view2 r0-s1 3 get doc(r0-s1) GIF drill StorageToken = r0-s2 r0-s2 GIF commit change StorageToken = r0-s3 view3 r0-s3 ReportEngine Developer Guide 37
  • 38. 3 Document Management Organizing documents in categories and folders Table 3-1 Storage token life cycle Advantages of storage tokens Performance Using a storage token is to refer to document states is fast and optimized for memory usage. Lifetime A storage token in the file system lasts as long as the ReportEngines object used to create ReportEngine instances. Business Objects recommended that you store a ReportEngines object in the session object once it is created and retrieve it again as required for document storage tokens to be valid throughout an application. Browser navigation back and forward After progressing through several document states, users can go back and forwards in their browser to a previous document state and continue working from that state. Undo mechanism You can build an undo mechanism by passing the storage token from the previous action perform on the document to the next web page. Organizing documents in categories and folders In InfoView, categories and folders are used to classify documents in the central management system. Documents organized in the hierarchical category and folder structures are easier for users to find; A user can save a document to selected categories and folders. A document can be assigned to one or more public or personal categories. 38 ReportEngine Developer Guide
  • 39. Document Management Organizing documents in categories and folders 3 Table 3-2 Categorized documents. Using the BusinessObjects Enterprise query mechanism you can navigate a category or folder hierarchy and retrieve IInfoObjects containing the individual categories and folders. These in turn enable you to: • create, rename and delete categories and folders • get the details of a categories and folders User rights for categories and folders A System administrator, using BusinessObjects Enterprise Central Management Console, can set how much control a user or group has over categories and folders. User rights settings are updated in the Advanced Rights page of the InfoView section for BusinessObjects Enterprise Applications of the Central Management Console. The following table lists an InfoView user’s possible rights. Folder and category-related settings in a Web Intelligence user’s rights InfoView Advanced Right Variable Name User can change preferences CeInfoViewRightID.PREFERENCE User can move and copy CeInfoViewRightID.ORGANIZE objects, create shortcuts and add object to the favorites folder. Can use InfoView simple CeInfoViewRightID.SIMPLESEARCH search Can use InfoView advanced CeInfoViewRightID.ADVANCEDSEARCH search ReportEngine Developer Guide 39
  • 40. 3 Document Management Organizing documents in categories and folders InfoView Advanced Right Variable Name Can use InfoView filter feature CeInfoViewRightID.FILTER User has a favorites folder CeInfoViewRightID.FAVORITES User can view inbox contents CeInfoViewRightID.VIEWINBOX User can create categories CeInfoViewRightID.CREATECATEGORIES User can assign categories to CeInfoViewRightID.ASSIGNCATEGORIES users or groups User can send documents to CeInfoViewRightID.SENDDOCUMENTS users and groups User can create dashboards CeInfoViewRightID.CREATEDASHBOARDS User can create folders CeInfoViewRightID.CREATEFOLDERS A list of a user’s rights over an object in the IInfoStore can be recovered by retrieving the user’s ISecurityInfo object for a certain BusinessObjects Enterprise application. Example: how to check that a user has the right to create categories This code fragment shows how to validate a user has the right to create categories. <% IInfoStore iStore = (IInfoStore)session.getAttribute("InfoStore"); IInfoObject infoView = null; String query = "SELECT STATIC FROM CI_APPOBJECTS,” + “ CI_SYSTEMOBJECTS WHERE” + “ (SI_PARENTID = 99 AND SI_KIND='" + CeKind.INFOVIEW + "')"; try{ IInfoObjects appObjects = iStore.query( query); if (appObjects.size() > 0) infoView = (IInfoObject )appObjects.get(0); if (infoView != null){ ISecurityInfo secInfo = infoView.getSecurityInfo(); if (secInfo.checkCustomRight( CeInfoViewRightID.CREATECATEGORIES, infoView.getKind())) { ... } } 40 ReportEngine Developer Guide
  • 41. Document Management Organizing documents in categories and folders 3 }catch (Exception exc){ ... } %> Note: Before trying to manage categories, check that the user who started the session has the appropriate rights. Note: A list of a rights for other BusinessObjects Enterprise applications can be found by changing the CeKind being searched for. For example, to search for a user’s Web Intelligence rights the query string would include CeKind.WEBINTELLIGENCE in the place of CeKind.INFOVIEW. Navigating categories and folders Categories and folders in a Central Management System are represented as a tree. Personal and Public are root nodes for categories. Home is the root node for folders. To access the category or folder trees, query the repository to retrieve the ID of the parent node for categories or folders. Use this ID to navigate the child nodes. Example: Traversing the category tree recursively The following example shows functions that use BusinessObjects Enterprise SDK to recover the ID of the parent folder for a user’s personal categories. Using this ID a bulleted list containing the hierarchical structure of the user’s personal categories is generated. <%! //Return the ID of a specific folder public int getFolderParentId(IInfoStore iStore, int userID, String kind){ int FolderID = 0; IInfoObjects folders = null; String query = "SELECT SI_PARENTID FROM CI_INFOOBJECTS” + “ WHERE SI_KIND='" + kind + "'" + “ AND SI_OWNERID=" + userID; try{ folders = iStore.query(query); if(folders.size() > 0) FolderID= ((IInfoObject)folders.get(0)).getParentID(); }catch (SDKException sdke){ return FolderID;} return FolderID; } //Return a selectable list of categories or folders String getCategoryList(IInfoStore iStore, int id, String kind ){ String results = ""; IInfoObject category; if (id == -1) id = 0; String sQuery = "SELECT SI_ID, SI_NAME, SI_PARENTID FROM” ReportEngine Developer Guide 41
  • 42. 3 Document Management Organizing documents in categories and folders + “ CI_INFOOBJECTS WHERE SI_PARENTID=" + id + " AND SI_KIND= '"+ kind + "'" ; try{ IInfoObjects categories = iStore.query(sQuery); if (!categories.isEmpty()){ results += "<ul>"; for(int i = 0; i < categories.size(); i++){ category = (IInfoObject)categories.get(i); String name = category.getTitle(); int catID = category.getID() ; results += "<li><input type="radio" name="" + kind + "" value="" + catID + "" >" + name + "</li>n"; results += getCategoryList(iStore, category.getID(), kind); } results += "</ul>"; } }catch (SDKException sdke){ results = null; } return results; } %> The following code fragment shows how to use the functions declared above to print personal categories for a user. <% IEnterpriseSession enterpriseSession =(IEnterpriseSession) session.getAttribute("EnterpriseSession"); IInfoStore iStore= (IInfoStore)session.getAttribute("InfoStore"); int userID = enterpriseSession.getUserInfo().getUserID(); int persoCatsfolderID = getFolderParentId( iStore,userID,(String)CeKind.PERSONALCAT); String catButtons = getCategoryList( iStore, (String)CeKind.PERSONALCAT)); %> Note: For an example of how to list documents in a folder, see “Displaying a document list” on page 47. Retrieving Inbox and favorites folder IDs Each BusinessObjects Enterprise user has unique personal directories. The Inbox and Favorites directories contain documents sent to a specific user or saved for personal rather than corporate use. To list the contents of these folders you need to retrieve the ID for each user’s personal directories. Once the root directory ID is retrieved, you can list and navigate the contents in the same way corporate folders are navigated. 42 ReportEngine Developer Guide
  • 43. Document Management Organizing documents in categories and folders 3 Example: Retrieve a user’s Inbox and Favorites folder IDs The following example shows functions that use BusinessObjects Enterprise SDK to recover the ID of the parent folder for a user’s Inbox and Favorites folders. <%! //Retrieve the ID for any type of personal folder public int getFolderId(IInfoStore iStore, int userID, String kind){ int FolderID = 0; IInfoObjects folders = null; String query = "SELECT SI_ID" + " FROM CI_INFOOBJECTS" + " WHERE SI_KIND='" + kind + "'" + " AND SI_OWNERID=" + userID; try{ folders = iStore.query(query); if(folders.size() > 0) FolderID = ((IInfoObject)folders.get(0)).getID(); }catch(SDKException sdke){ FolderID = -1; } return FolderID; } //Retrieve the ID of a user’s Inbox int getInboxFolderId(IInfoStore iStore, int userID){ return getFolderId(iStore,userID,(String)CeKind.INBOX); } //Retrieve the ID of a user’s favorites folder int getFavoritesPFolderID(IInfoStore iStore, int userID){ return getFolderId(iStore,userID,(String)CeKind.FAVORITESF); } %> //The following example shows how to retrieve a list of documents in the current user’s Inbox. See “Displaying a document list” on page 47 for the definition of getList. <% IEnterpriseSession enterpriseSession; IInfoObjects docList = null; enterpriseSession = (IEnterpriseSession) session.getAttribute("EnterpriseSession"); IInfoStore iStore = (IInfoStore) session.getAttribute("InfoStore"); int userID = enterpriseSession.getUserInfo().getUserID(); int inboxID = getInboxFolderId(iStore, userID); docList = getList(iStore, inboxID, (String)CeKind.WEBI ); %> ReportEngine Developer Guide 43
  • 44. 3 Document Management Organizing documents in categories and folders Note: See “Displaying a document list” on page 47 for the definition of getList. Creating categories and folders You can add categories and folders by: • getting the ID of the folder or category in which you wish to create a node • getting the correct plug-in to create a node • committing the new object to the Central Management System Example: Creating a new folder or category The following example shows functions that use BusinessObjects Enterprise SDK to create a new folder or category. <%! int addFolderOrCategory(IInfoStore iStore, int parentFolderID,String name, String description, String type){ int objectID = 0; IPluginInfo plugin; try{ IPluginMgr pluginMgr = iStore.getPluginMgr(); plugin = pluginMgr.getPluginInfo(type); IInfoObjects newInfoObjects = iStore.newInfoObjectCollection(); newInfoObjects.add(plugin); IInfoObject infoObject = (IInfoObject) newInfoObjects.get(0); infoObject.setTitle (name); infoObject.setDescription (description); objectID = infoObject.getID(); infoObject.properties().setProperty( CePropertyID.SI_PARENTID, parentFolderID); iStore.commit (newInfoObjects); }catch (SDKException e) { throw new Error("Failed to add the object."); } return objectID; } %> The following code fragment shows how to use the functions declared above to create a new personal category and a new folder. <%//How to use this function //Create a new personal category addFolderOrCategory(iStore, categoryParentID, "Category Name", "Keywords",CeKind.PERSONALCAT); //Create a new personal folder addFolderOrCategory(iStore, categoryParentID, "Folder Name", "Keywords", CeKind.FOLDERS);%> 44 ReportEngine Developer Guide
  • 45. Document Management Organizing documents in categories and folders 3 Moving and renaming categories and folders You can move categories and folders from one parent to another using the IInfoObject.setParentID method. You can rename categories and folders using the IInfoObject.setTitle method. After the category or folder has been renamed or moved, IInfoStore.commit must be called with the changed IInfoObject passed as a parameter. Example: Moving and renaming categories or folders The following function changes the name of a folder or category and moves it in the folder or category hierarchy respectively. <%! String changeNameMove(IInfoStore iStore, int ID, String newName, int newParentID){ String query; IInfoObjects result; String res = ""; query = "Select SI_NAME, SI_ID From CI_INFOOBJECTS “ + “ Where SI_ID=" + ID; try{ result = iStore.query(query); if ( result.size() > 0 ){ IInfoObject currResult; currResult = (IInfoObject)result.get(0); currResult.setTitle(newName); currResult.setParentID(newParentID); iStore.commit(result); } } catch(SDKException e){ ; } return res; } Getting the properties of a category Each IInfoObject in the BusinessObjects Enterprise IInfoStore contains a collection of all properties assigned to that object, known as a “properties bag.” To retrieve IInfoObject details, request SI_NAME, SI_DESCRIPTION, SI_KEYWORD in the query string used to recuperate the IInfoObject representing a category or folder. Example: Retrieve the properties for a category The following method returns the properties of a category, folder, or document as an IInfoObject: <%! IInfoObject getProps(IInfoStore iStore, int ID){ ReportEngine Developer Guide 45
  • 46. 3 Document Management Working with documents String query; IInfoObjects result = null; IInfoObject properties = null; String res = ""; query = "SELECT SI_FILES, SI_DESCRIPTION,” + ” SI_KEYWORD, SI_KIND"; query += " FROM CI_INFOOBJECTS WHERE SI_ID=" + ID; try{ result = iStore.query(query); if (result.size() > 0){ properties = (IInfoObject)result.get(0); } } catch(SDKException e){ return null; } return properties; } %> The following code fragment shows how to use the functions declared above to print the description and keywords of an IInfoObject object to an HTTP stream. <% int ID = Integer.parseInt(request.getParameter("ID")); PrintWriter myWriter = response.getWriter(); IInfoStore iStore = (IInfoStore) session.getAttribute("InfoStore"); IInfoObject fProperties = getProps(iStore, ID); myWriter.print( fProperties.getDescription() + "<br>n"); myWriter.print( fProperties.getKeyword() + "<br>n"); //Another way to retrieve the keyword IInfoObject Property myWriter.print( fProperties.properties().getProperty( CePropertyID.SI_KEYWORD).getValue().toString()); %> Working with documents Working with documents involves opening and listing the documents, then providing facilities for saving, sending, scheduling, and organizing documents. Opening documents After establishing a session for a user (see “Establishing a valid BusinessObjects Enterprise user’s session” on page 20) you can open a document on behalf of the user. In general, to open a document you: 46 ReportEngine Developer Guide
  • 47. Document Management Working with documents 3 1. Establish a BusinessObjects Enterprise session for the user. 2. Get an identifier for the document. The identifier can be a storage token (see “Document state: storage tokens” on page 35), or more simply the document’s ID. 3. Retrieve the ReportEngineinstance relating to the type of document to be opened. 4. Open the document using the ReportEngine.openDocument method for Web Intelligence or Desktop Intelligence documents. See “Instantiating a ReportEngine objects depending on file type” on page 31 for an example of how this is done. Taking into account user rights and profiles Because your Web Intelligence application acts on behalf of a user, what your application can do with the document is subject to the user’s rights. They are set in the BusinessObjects Enterprise Central Management Console. You should take these rights into account in your application. You should also take into account the settings in the user’s profile. See “User preferences” on page 24. Displaying document lists To display a list of documents you: 1. Use the IInfoStore.query method to return the list of IInfoObjectss representing the root directory of the user’s folders and documents. 2. Loop through the IInfoObject list and print the values of the fields of each row. 3. Allow navigation through the folders. Note: IInfoObject is the base BusinessObjects Enterprise type. An IInfoObject can be used to store any type of object in the central management system. Refreshing a document list A document list is refreshed every time IInfoStore.query is called. The results come directly from the BusinessObjects Enterprise Central Management System (CMS) with no intermediary cache. Example: Displaying a document list The following code fragment is a helper function called getList. This function is passed an IInfoObject object as a parameter, which is then used to return a list of IInfoObject objects of a required type, in this case Folders or Web Intelligence documents. ReportEngine Developer Guide 47
  • 48. 3 Document Management Working with documents This function is placed either at the head of the listfolders.jsp script or in a file containing helper functions included in listfolders.jsp. <%! IInfoObjects getList(IInfoStore iStore, int searchID, String kind){ IInfoObjects list = null; String query = "SELECT SI_ID, SI_NAME, SI_PARENTID,” + “ SI_KIND, SI_INSTANCE, SI_DESCRIPTION FROM” + “ CI_INFOOBJECTS WHERE SI_PARENTID=" + searchID + " AND SI_KIND = '" + kind + "'"; try{ list = iStore.query(query); } catch (SDKException sdke){ list = null; } return list; } %> The function getInfoList is called from listfolders.jsp. The following code fragment shows returns a list of Web Intelligence documents in the document root folder. <% int iID= 0; //ID of the root folder IInfoObjects webiDocs = null; String searchID=request.getParameter("sID"); if (searchID!=null) iID=Integer.parseInt(searchID); IInfoStore iStore = (IInfoStore)session.getAttribute("InfoStore"); webiDocs=getList(iStore,iID,(String)CeKind.WEBI); ... %> Saving documents To save a document use DocumentInstance.save and DocumentInstance.saveAs. Example: Save a document The following example shows how to open a document to be worked on, then open and save the original version of the document. <% DocumentInstance doc = myReportEngine.openDocument(docID); String docToken doc.getStorageToken(); //User perform actions on document doc... //Open the first version of the document and save. DocumentInstance docToSave = 48 ReportEngine Developer Guide
  • 49. Document Management Working with documents 3 theReportEngines.getDocumentFromStorageToken(docToken); docToSave.save(); %> Note: Go to “Sending documents to users, groups and categories” on page 50 to see how to use the saveAs method. Scheduling documents Scheduling refreshes a document automatically at a specified time or times. When a scheduled document refreshes successfully, an instance is created. An instance is a version of the document containing data available at the time it is refreshed. Instances created later contain more recent data. By scheduling and viewing instances, a user can have the latest information available for viewing, printing, and distributing. For example, you can schedule a document to run every night so data viewed first thing in the morning is sure to be up to date. To schedule a document you need to: 1. Query the IInfoStore to get the IInfoObject representing the specific document. 2. Get the document’s ISchedulingInfo object. 3. Set the type and frequency of the scheduling. 4. Use the IInfoStore to schedule the document. Note: The schedule action refreshes data in a document. This means that Prompt, Context, and Drill actions have to be handled automatically at run time using information gathered from the user when the schedule action is created. Example: Scheduling a document The following function shows how to schedule a document to run once immediately or recurrently on a specific interval of days. The document instance created is stored in the list of document instances attached to a document. <%! boolean scheduleDocument(IInfoStore iStore, int documentID, int days){ IInfoObjects documentList; ISchedulingInfo schedulingInfo; IInfoObject document; String res = ""; boolean success = true; ReportEngine Developer Guide 49
  • 50. 3 Document Management Working with documents try { String schedQuery = "Select SI_schedulingInfo From” + “ CI_INFOOBJECTS Where SI_ID=" + documentID; documentList = iStore.query( schedQuery); if ( documentList.size() > 0 ){ document= (IInfoObject) documentList.get(0); schedulingInfo = document.getSchedulingInfo(); if (days == -1){ schedulingInfo.setType(CeScheduleType.ONCE); schedulingInfo.setRightNow(true); } else { schedulingInfo.setIntervalDays(days); schedulingInfo.setType( CeScheduleType.DAILY ); } iStore.schedule(documentList); } } catch( SDKException e ) { success = false ; } return success; } %> The following code fragment shows how to call the scheduleDocument function to schedule a document to be run once immediately. <% String docId = request.getParameter("docID"); IInfoStore iStore = (IInfoStore)session.getAttribute("InfoStore"); scheduleDocument(iStore, Integer.parseInt(docId), -1); %> Sending documents to users, groups and categories The list of BusinessObjects Enterprise users to whom a document can be sent depends on the groups to which the current user belongs, and the current user’s permissions. 50 ReportEngine Developer Guide
  • 51. Document Management Working with documents 3 Action To these groups and/or Depending on the current users … user’s settings for these permissions… Save to Groups groups and categories to DocumentInstance.saveAs and Categories which the current user has access Send to Inbox, groups to which the IInfoStore.schedule FTP, email, current user belongs, groups. and/or the other users in those groups Example: Retrieve the list of groups to which a user belongs The following JSP function shows how to retrieve the list of groups the current user belongs to. <%! IInfoObjects getUserGroups(IInfoStore iStore) { IInfoObjects groups = null; String query = "SELECT SI_ID, SI_NAME" + " FROM CI_SYSTEMOBJECTS" + " WHERE SI_KIND='" + CeKind.USERGROUP + "'" ; try{ groups = iStore.query(query); } catch (SDKException sdke){ groups = null; } return groups; } %> BusinessObjects Enterprise uses object security, which means that security is set for each object in the system and not for each user. Thus, for a particular object, certain users and certain groups have the rights to different actions, depending on the object’s settings. Access to folders and categories can be restricted to specific groups and individual users. Saving a document to a specific folder and category is a way of publishing a document to a group of users. These permissions are controlled by the system administrator using BusinessObjects Enterprise Central Management Console. Procedure for sending a document to folders and categories BusinessObjects Enterprise documents are organized by folder and category. ReportEngine Developer Guide 51
  • 52. 3 Document Management Working with documents To send a document to folders use DocumentInstance.saveAs. Typically, however, to send a document, you need to gather the appropriate information from the current user before sending. To do this you need two web pages: In the first page: 1. Display the name of the document to be sent. 2. Retrieve the IDs of: • corporate folders and categories • the root directory of the current user's personal categories 3. Get and display the list of folders and categories to which the current user can send documents. 4. Pass this information to the second page. Then, in the second page: 1. Get the details entered by the user. 2. Call DocumentInstance.saveAs. Example: Sending a document to folders and categories The following code fragments are used to save a document in specific folders and categories. saveDocAs.jsp is called by a page that passes the name and ID of the document in the query string. In saveDocAs.jsp the user selects the folders and categories the document is to be saved in. When the user clicks “Save Document” in the form, saveDocAs.jsp is executed and the document is sent according to the user’s selections. Note: The function getCatOrFoldersRadioButtons and webiPrefsToMap is declared in the example “Traversing the category tree recursively” on page 41. <%! //Return the ID of a specific folder public int getFolderParentId(IInfoStore iStore, int userID, String kind){ int FolderID = 0; IInfoObjects folders = null; String query = "SELECT SI_PARENTID FROM “ + “ CI_INFOOBJECTS WHERE SI_Kind='" + kind + "'" + AND SI_OWNERID=" + userID; try{ folders = iStore.query(query); if(folders.size() > 0) FolderID=((IInfoObject)folders.get(0)).getParentID(); }catch (SDKException sdke){ return FolderID;} return FolderID; } %> 52 ReportEngine Developer Guide
  • 53. Document Management Working with documents 3 The following code fragment shows how to use the functions declared above to create a form used to select the folders and categories in which a document will be saved. In saveDoc.jsp <% //get the parameters from the request object String docId = request.getParameter("docID"); String docName = request.getParameter("docName"); String docParentFolderID = request.getParameter("corpFolder"); String corpCategID = request.getParameter("corpCategory"); String persoCatedID = request.getParameter("persoCategory"); List ccIDlist = new ArrayList(); List pcIDlist = new ArrayList(); //Validate the parameters if (corpCategID != null) ccIDlist.add(Integer.decode(corpCategID)); if (persoCatedID != null) pcIDlist.add(Integer.decode(persoCatedID)); if (docId != null && docParentFolderID != null){ //Open and save the document DocumentInstance docToSave = webiRepEngine.openDocument(Integer.parseInt(docId)); if( docToSave != null) docToSave.saveAs( docName, Integer.parseInt(docParentFolderID), ccIDlist,pcIDlist); } %> Note: corpCategories and persoCategories are strings containing the ID’s of the corportate and personal category chosen by the active user to store the document in. Sending a document to the Inbox of users or groups If the current user has the appropriate permissions, you can schedule a document to be send to the inboxes of users or groups of users to which the current user belongs. Procedure for sending a document to inboxes To schedule a document, you need to gather the appropriate information from the current user before sending. To do this you need to: 1. Query the IInfoStore to get the IInfoObject representing the document to be sent. 2. Get the document’s ISchedulingInfo object. 3. Retrieve the Inbox plugin used to send a document to users. 4. Set the destination and send options for the Inbox plugin. ReportEngine Developer Guide 53
  • 54. 3 Document Management Working with documents 5. Create a Set containing the IDs of users or groups to which the current user can send the document. 6. Allow the user to choose the users/groups to send the document to. 7. Add the set of IDs created in the previous step to the Inbox plugin options. 8. Set the type and frequency of the scheduling. 9. Schedule the document. Note: In the InfoView user interface, this action is called “Send to BusinessObjects Inbox.” You get the list of groups to which the current user can publish documents by querying the IInfoStore. The returned IInfoObjects object contains the ID’s of all groups the current user has the right to send to. Example: Send a document to the inbox of groups of users <%! //This function retrieves the Inbox destination plugin IDestinationPlugin getInboxDestPlugin(IInfoStore iStore){ int PLUGIN_ROOT = 29; IDestinationPlugin inboxPlugin = null; String[] pluginsToLoad = new String[] {CeKind.DISKUNMANAGED, CeKind.SMTP, CeKind.FTP, Kind.MANAGED_DEST}; String pluginString = ""; for (int i = pluginsToLoad.length - 1; i >= 0; i--){ pluginString += "'" + pluginsToLoad[i] + "'"; if (i != 0) pluginString += ", "; } String pluginQuery = "SELECT * FROM CI_SYSTEMOBJECTS” + “ WHERE SI_PARENTID=” + PLUGIN_ROOT + “ AND SI_NAME in " + "(" + pluginString + ")"; try{ IInfoObjects destPlugins = iStore.query(pluginQuery); for (int i = 0; i < destPlugins.size(); i++){ IInfoObject plugin = (IInfoObject)destPlugins.get(i); if ( CeKind.MANAGED_DEST.equals(plugin.getTitle()) ) inboxPlugin = (IDestinationPlugin)(plugin); } } catch (SDKException e){ inboxPlugin = null; } return inboxPlugin; } //This function retrieves the IDs of the groups the current //user can schedule to Set getUserGroupIDs(IInfoStore iStore){ IInfoObjects groups = null; 54 ReportEngine Developer Guide
  • 55. Document Management Working with documents 3 Set IDs = new Set(); String query = "SELECT SI_ID, SI_KIND, SI_NAME" + " FROM CI_SYSTEMOBJECTS" + " WHERE SI_Kind='" + CeKind.USERGROUP + "'"; try{ groups = iStore.query(query); int size = groups.size(); for (int i = 0; i < size; i++) { IInfoObject obj = (IInfoObject)groups.get(i); if (CeKind.USERGROUP.equals(obj.getKind())) { IDs.add(new Integer(obj.getID())); } } } catch (SDKException sdke){ IDs = null; } return IDs; } %> The following code fragment shows how to send the copy of a document to the inbox of all users in the groups the current user is allowed to post to once a week. <% String docId = request.getParameter("docID"); IInfoStore iStore = (IInfoStore)session.getAttribute("InfoStore"); IDestinationPlugin inboxPlugin = null; IManagedOptions destOptions = null; ISchedulingInfo schedulingInfo = null; IInfoObjects documentList = null; IInfoObject document = null; try { String docQuery = "Select SI_schedulingInfo FROM” + “ CI_INFOOBJECTS Where SI_ID=" + docId; documentList = iStore.query(docQuery); if ( documentList.size() > 0 ) { document= (IInfoObject)documentList.get(0); schedulingInfo = document.getSchedulingInfo(); inboxPlugin = getInboxDestPlugin(iStore); IDestination destination = schedulingInfo.getDestination(); if (inboxPlugin != null){ destOptions =(IManagedOptions) inboxPlugin.getScheduleOptions(); destOptions.setDestinationOption( IManagedOptions.CeDestinationOption.ceInbox); destOptions.setSendOption( IManagedOptions.CeManagedSendOption.ceCopy); Set IDs = getUserGroupIDs(iStore); Set destinationIDs = destOptions.getDestinations(); destinationIDs.clear(); destinationIDs.addAll(IDs); ReportEngine Developer Guide 55
  • 56. 3 Document Management Document properties destination.setFromPlugin(inboxPlugin); schedulingInfo.setIntervalDays(7); schedulingInfo.setType(CeScheduleType.DAILY); iStore.schedule(documentList); } } } catch( SDKException e ) { throw e; } %> Document properties Some important characteristics of Web Intelligence and Desktop Intelligence documents are stored as part of the document. You can access these properties using the DocumentInstance object. ForReportEngine SDK the process for accessing a property of a Web Intelligence document is: 1. Get the collection of properties. 2. Set/Read the property. 3. Commit the change, if any, to the collection of properties. Working with properties Using ReportEngine SDK, you can access a document’s properties with DocumentInstance.getProperties and DocumentInstance.setProperties. These methods make use of the java.util.Properties class. There are predefined properties defined in PropertiesType. You can also add you own properties to the document. To avoid confusion in the central management system, PropertiesType.NAME is read only. Example: Getting the name of a document The following code fragment illustrates how to get the NAME property of a Web Intelligence document. DocumentInstance doc = myReportEngine.openDocument(docID); java.util.Properties props = doc.getProperties (); String dName = props.getProperty (PropertiesType.NAME); 56 ReportEngine Developer Guide
  • 57. Document Management Document properties 3 Adding your own properties to the document Use Properties.setProperty to add your own properties to the document. Example: Adding a property to a document The following code fragment illustrates how to add the RefreshCount property to a Web Intelligence document. DocumentInstance doc = myReportEngine.openDocument(docID); java.util.Properties props = doc.getProperties (); props.setProperty ("RefreshCount", "12"); doc.setProperties (props); If you create a new Properties collection and add properties to that collection, when you call DocumentInstance.setProperties the values in the new object are added to the standard property collection. Permanent properties such as NAME and AUTHOR are not erased in the merge. Values for the properties that you have set in the new collection take precedence over those in the one attached to the DocumentInstance. ReportEngine Developer Guide 57
  • 58. 3 Document Management Document properties 58 ReportEngine Developer Guide
  • 60. 4 Viewing Reports Overview Overview Web Intelligence Report Engine SDK contains classes and methods for viewing documents. Applications for viewing Web Intelligence and Desktop Intelligence documents handle prompts, and provide report and section navigation using the ReportMap. This chapter discusses how to use Report Engine SDKto view Web Intelligence and Desktop Intelligence reports. See also and “Formatting Reports” on page 101. Viewing reports You can view complete documents, that is to say, including all reports or individual reports or report pages in a variety of different formats. The following tables show the different formats available Desktop Intelligence Documents BINARY EXCEL EXCEL PDF CSV XML DHTML HTML CONTENT DataCentric DOCUMENT Y Y Y REPORT Y Y Y Y Y REPORT_PAGE Y Y Y DATA_PROVIDERS Y DATA_PROVIDER Y Y Web Intelligence Documents BINARY EXCEL EXCEL PDF CSV XML DHTML HTML CONTENT DataCentric DOCUMENT Y Y Y Y REPORT Y Y Y Y Y Y REPORT_PAGE Y Y DATA_PROVIDERS Y DATA_PROVIDER Y Y To view an entire document, call DocumentInstance.getView, to view an individual report, call Report.getView. If you want to view all the reports in a document in DHTML format, you need to get views of each report in DHTML 60 ReportEngine Developer Guide
  • 61. Viewing Reports Viewing reports 4 and display those separately. See “Viewing an individual report in DHTML” on page 62. More information can be found in the API doc for the SupportedViews interface. Note: Calling DocumentInstance.getView and Report.getView generates a new storage token. For more information on storage tokens see “Document state: storage tokens” on page 35. Viewing all the reports in a document To view all the reports in a document: 1. Open the document. 2. Get a binary view of the document. You can get a binary view of a document in PDF or Microsoft Excel format. When ReportEngine SDK converts the document into PDF it places reports on separate pages and creates a bookmark for each report. In Microsoft Excel format the reports of a Web Intelligence document appear on separate sheets. 3. Output the binary view of the document via the implicit response object. You need to prepare the response object to receive the appropriate content type. For Adobe Acrobat format set the content type to “application/pdf”. For Microsoft Excel format, set the content type to “application/vnd.ms-excel”. Example: Viewing all the reports in a Web Intelligence document The following code fragment displays all the reports in a document in Adobe Acrobat format. In this example, the name of the document is stored in docName and the ID is stored in docID. Typically these would be passed to the script in the query string. <% // get the document String strDocID = request.getParameter("DocID"); int intDocID = Integer.parseInt(strDocID) String strQuery = "Select SI_KIND from CI_INFOOBJECTS " + "where SI_ID=" + strDocID; IInfoObjects iDocuments = iStore.query(strQuery); IInfoObject iDocument = (IInfoObject) iDocObjects.get(0); String strKind = iDocObject.getKind(); // Instantiate appropriate ReportEngine according to // document type ReportEngine repEng = null; if (strKind.equals("Webi")) repEng = reportEngines.getService( ReportEngineType.WI_REPORT_ENGINE); else repEng = reportEngines.getService( ReportEngineType.FC_REPORT_ENGINE); ReportEngine Developer Guide 61
  • 62. 4 Viewing Reports Viewing reports // Open the document using its repository ID DocumentInstance doc = repEng.openDocument(intDocID); BinaryView docBinaryView = (BinaryView) doc.getView(OutputFormatType.PDF); //Parameterize the response response.setContentType("application/pdf"); response.setHeader("Content-Type", "application/pdf"); response.setDateHeader("expires", 0); //output the binary stream via the response object docBinaryView.getContent(response.getOutputStream()); %> Note: This example starts Adobe Acrobat Reader® and displays the document using this application. Depending on the user’s browser configuration, the document will appear in either in the browser or in a separate application window. Viewing an individual report in DHTML HTML is the standard format for viewing reports. The standard viewing format is DHTML. To view an individual report in DHTML format: 1. Get a document instance. 2. Set the report. 3. Get a view of the report in DHTML format. 4. Display the report. Example: Viewing a report in a Web Intelligence document The following code fragment displays a selected report in a Web Intelligence document in DHTML format. <% // Get query string parameters and initialize variables String sToken = request.getParameter("token"); String sRepID = request.getParameter("reportID"); DocumentInstance doc = null; Report rep = null; //the report to be viewed int iRepID = 0; //index of the selected report // Get the document doc = reportEngine.getDocumentFromStorageToken(sToken); // Set the report if ((sRepID != null)&&(!(sRepID.equals("")))) iRepID = Integer.parseInt(sRepID); else iRepID = 0;//set to the first report in the document rep = doc.getReports().getItem(iRepID); 62 ReportEngine Developer Guide
  • 63. Viewing Reports Viewing reports 4 //get a view of the report in DHTML format HTMLView docHtmlView = null; docHtmlView = (HTMLView)rep.getView(OutputFormatType.DHTML); // Set user agent (IE, Netscape…) String strUserAgent = request.getHeader("User-Agent"); docHtmlView.setUserAgent(strUserAgent); // Full Report HTML to the output stream docHtmlView.getContent(out, “”, “”); %> <%=docHTMLView%> Note: In this example, reportEngine is an initialized ReportEngine object. Viewing an individual report in another format You can view reports in Adobe Acrobat or Microsoft Excel format. The procedure is the same as for DHTML format (described above) except that, as for viewing all the reports in a document, you must get the content of the report as a binary stream which you can output via the response object. To view a report in a non-DHTML format: 1. Get a binary view of the report. 2. Output the binary view of the document via the implicit response object. You need to prepare the response object to receive the appropriate content type. For Adobe Acrobat format set the content type to “application/pdf”. For Microsoft Excel format, set the content type to “application/vnd.ms-excel”. Example: Viewing a report in Microsoft Excel format The following code fragment displays all the reports in a Web Intelligence document in Microsoft Excel format. //get the report to view (Report rep) ... //get the report contents as a binary stream in Excel format BinaryView docBinaryView = (BinaryView)rep.getView(OutputFormatType.XLS); //output the binary stream via the response object response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-Type", "application/vnd.ms-excel"); response.setDateHeader("expires", 0); //output the binary stream via the response object byte[] abyBinaryContent = docBinaryView.getContent(); //output the binary stream via the response object outputStream.write(abyBinaryContent); ReportEngine Developer Guide 63
  • 64. 4 Viewing Reports Handling prompts Handling prompts Prompts are a way to get supplementary information into a query before executing. In Report Engine SDK, how you handle prompts depends on the type of document you are working with. This section discusses how to handle prompts in Web Intelligence and Desktop Intelligence documents. Prompts are usually raised when a document is refreshed using DocumentInstance.refresh if scheduled. The refresh operation executes the query and, therefore, needs to collect the supplementary information that resolves filters and contexts. Note: Prompts that resolve universe contexts must be filled before standard prompts. See “Handling context prompts” on page 74. Documents with a single simple prompt One of the simplest and most common prompts is one that resolves a query filter. For example, “Enter the year: “ to which a user responds “2003” and the data retrieved by the query is restricted to the year 2003. Example: Handling a single, simple prompt The following code fragment illustrates how to handle a single, simple prompt. (“Simple prompt” means standard, text-entry prompts only.) The code in this example is from a JSP called refresh.jsp. When the user chooses to refresh a document, refresh.jsp is executed, then, when the prompt have been filled, view.jsp is executed. DocumentInstance doc = reportEngines.getServiceFromStorageToken(Token); if (doRefresh) doc.refresh(); //refresh first time only Prompts prompts = doc.getPrompts(); //try to enter values and set prompts String[] values = request.getParameterValues("PromptInput"); if ((values != null)&&(!(values[0].equals("")))){ prompts.getItem(0).enterValues(values); doc.setPrompts(); //also sets getMustFillPrompts to false } //get user input if (doc.getMustFillPrompts()) { //build a form to get user input for the prompt %> <formname="PromptsForm" action="refresh.jsp?Token=<%=doc.getStorageToken()%>" method="post"> <input name="PromptInput" type="text"/> 64 ReportEngine Developer Guide
  • 65. Viewing Reports Handling prompts 4 <input name="Submit" type="submit" value="OK" /> </form> <% } Response.sendRedirect("view.jsp? Token="+doc.getStorageToken()); Response.sendRedirect Note: This example does not show how to set how to set the Boolean variable doRefresh. One way to set this variable is to include an extra parameter in the query string for refresh.jsp; when DoRefresh is ”F”, doRefresh is false. The workflow for refresh.jsp for a document with one, simple prompt is therefore: 1. Get the DocumentInstance object for the document. 2. Get the Prompts collection for the document. 3. Try to enter values and set the Prompts for the document. The first time refresh.jsp is executed, this step will not work as the user has not yet entered a value for the Prompt. 4. Either: • if the Prompt is not filled, display a form to get a value from the user This is the case the first time the file is executed. The form’s action parameter is set to refresh.jsp so that this file is executed when the user clicks the submit (OK) button. • otherwise, execute view.jsp to display the document’s reports Using the storage token to retrieve a DocumentInstance When handling any kind of prompt, if you use the storage token to retrieve the document, you must be careful to use the correct token. The storage token changes after calls to DocumentInstance.refresh, and DocumentInstance.setPrompts. For more information on storage tokens see “Document state: storage tokens” on page 35. Documents with many simple prompts To handle many simple prompt objects you can extend the workflow for a single simple prompt (page 64) with a form into which the user can enter values for all the prompts, and a script that handles these values. ReportEngine Developer Guide 65
  • 66. 4 Viewing Reports Handling prompts One problem this extension raises is that you need to dynamically set the names of the inputs in the form that carry the values of each prompt. To do this you can construct a name using a string constant, for example “PV”, and the position of the prompt in the prompts collection. Example: Dynamically creating input names The following code fragment illustrates how to dynamically create names for the inputs of a form. <form name="PromptsForm" action="refresh.jsp" method="post"> <table><% for (int i = 0; i < prompts.getCount(); i++) { %><tr> <td>Enter a value for prompt number <%=i%>:</td> <td><input name=<%="PV"+i%> type="text"/></td> </tr><% } %><tr><td> <input name="Submit" type="submit" value="OK" /> </tr></td> </table> </form> Note: See the following example for an illustration of how to retrieve the values in these inputs from the query string. Example: Handling many, simple prompts The following code fragment illustrates how to handle many, simple prompts in a Web Intelligence or Desktop Intelligence document. (“Simple prompt” means standard, text-entry prompts only. The code in this example is from a page called refresh.jsp. When the user chooses to refresh a document, refresh.jsp is executed, then, when the prompt have been filled, view.jsp is executed. <% //get the document and its prompts DocumentInstance doc = reportEngine.getServiceFromStorageToken(token); if (doRefresh) doc.refresh(); //refresh first time only Prompts prompts = doc.getPrompts(); //try to get and enter values from the query string // valuesSelected is true when the user completes the form if (valuesSelected) { for (int j = 0; j < prompts.getCount(); j++) { //use (recreate) the parameter names created in the form String[] values = request.getParameterValues(("PV" + j)); if ((values != null)&&(values.length != 0)) prompts.getItem(j).enterValues(values); } 66 ReportEngine Developer Guide
  • 67. Viewing Reports Handling prompts 4 doc.setPrompts(); //also sets getMustFillPrompts to false } //get user input if (doc.getMustFillPrompts()) { //build a form to get user input for the prompt %> <form name="PromptsForm" action="refresh.jsp" method="post"> <table> <% //add a row to the table for each prompt // the names of inputs are created dynamically for (int i = 0; i < prompts.getCount(); i++) { %> <tr> <td><%=prompts.getItem(i).getName()%></td> <td><input name=<%="PV"+i%> type="text"/></td> </tr> <% } //and add a row to the table for the submit button // DoRefresh and ValuesSelected help keep track of // where we are in the workflow %><tr><td> <input name="Token" type="hidden" value="<%=doc.getStorageToken()%>" /> <input name="DoRefresh" type="hidden" value="false" /> <input name="ValuesSelected" type="hidden" value="true" /> <input name="Submit" type="submit" value="OK"> </tr></td> </table> </form> <% } else //all prompts are filled and can now display the report response.sendRedirect("view.jsp? Token="+doc.getStorageToken()); %> Note: A flag is now needed to determine if there are prompt values in the query string. This example uses a hidden input in the form, ValuesSelected, which is converted to a boolean when it is retrieved, however, you could also use the first prompt parameter PV0 for this purpose. ReportEngine Developer Guide 67
  • 68. 4 Viewing Reports Handling prompts Prompts with simple lists of values A List Of Values (Lov) is a set of values associated with a universe object. These values are the corresponding values found for the object in the database. The universe designer can edit this set as part of creating the object in the universe. For example, the Quarter object could have the following list of values {Q1, Q2, Q3, Q4}, and the Customer object could have a list of values like this: {Adams, Arkwright, Baker, Bean, ..., Zane}. These values are defined when the designer creates the object, but can be refreshed, to accommodate changes in the database, automatically or manually. For information on refreshing lists of values, see “Chunking long lists of values” on page 72. list of values for the Quarter object in the eFashion universe Table 4-1 Viewing the list of values for the Quarter object in Universe Designer. Handling prompts that contain Lov objects involves extending the workflow for many, simple prompts (page 65). To do this you detect if the prompt object has an associated Lov by calling Prompt.hasLOVIPrompt., if there is a list of values for the prompt, get the values in the list with Lov.getAllValues, then display them in the user input form, with Lov.getValues, as options of an HTML select tag. Note: Prompt.getLOV automatically refreshes the report, this can cause problems with nested prompts which need to be handled. See “Handling nested prompts” on page 72. The select tag for the list uses the same dynamic input naming described in “Dynamically creating input names” on page 66. Example: Displaying a simple list of values The following code fragment illustrates how to get the values of a Lov object and display them in a form. //get user input if (doc.getMustFillPrompts()) { //build a form to get user input for the prompt %><form name="PromptsForm" action="refresh.jsp" method="post"> 68 ReportEngine Developer Guide
  • 69. Viewing Reports Handling prompts 4 <table><% for (int i = 0; i < prompts.getCount(); i++) { Prompt prompt = prompts.getItem(i); if (prompt.hasLOV()) { Values lovValues = prompt.getLOV().getAllValues(); %> <tr> <td><%=prompt.getName()%></td> <td> <select name=<%="PV"+i%> size=1> <% for (int k=0; k < lovValues.getCount(); k++){ %> <option value="<%=lovValues.getValue(k)%>"> <%=lovValues.getValue(k)%> </option><% }%> </select> </td> </tr><% } } %><tr><td> <input name="Submit" type="submit" value="OK"> </tr></td> </table> </form> <%}%> Note: The example “Handling multivalued prompts” on page 70 shows how to modify the select tag to handle multivalued prompts. Constrained prompts A prompt is constrained if the answer must come from the prompt’s list of values (Lov). In Web Intelligence, users create constrained prompts by selecting Select Only From List when creating a prompt filter for a query. You can detect if a prompt is constrained with Prompt.isConstrained. Multivalued prompts Until now we have considered only prompts that can have one value, however, some prompts can require several values before being filled. For example, the prompt, Store name in list, can have one or many responses before it is filled, whereas the prompt, Year equals, can have only one response. ReportEngine Developer Guide 69
  • 70. 4 Viewing Reports Handling prompts Note: For prompts that use the Between operator, such as, Sales revenue is between X and Y, the user must specify both X and Y before the prompt can be considered complete. However, Web Intelligence forms these kinds of prompts as two separate prompts, you do not need to treat them as a multivalued prompt. To detect how many values the prompt requires use PromptType.getType. A prompt can either be PromptType.Mono or PromptType.Multi. Example: Handling multivalued prompts The following code fragment illustrates how to modify the <select> tag of the previous example (page 68) to handle multivalued prompts. <td><% if (prompt.getType() == PromptType.Mono) {%> <select name=<%="PV"+i%> size=1><% } //multivalued LOV needs a different select statement else {%> <select name=<%="PV"+i%> multiple size=5><% } //add values in LOV to the select list for (int k = 0; k < lovValues.getCount(); k++) { %> <option value="<%=lovValues.getValue(k)%>"> <%=lovValues.getValue(k)%> </option><% }%> </select> </td> Prompts with multicolumn lists of values A universe designer can create a list of values that has many columns. You detect a list of values with more than one column using Values.isMultiColumns. A multicolumn list of values is represented inReportEngine SDK as rows in a table with the RowValues interface. To display the values in the list you use Values.getRowValue to get a row in the table, and then RowValue.getHeader and RowValue.getItem display the values in the list. Note: Prompt.enterValues uses only the first value in each row to identify the row. When the user selects a row, make sure you pass just the value in the first column (index = 0) of the row to Prompt.enterValues. The example below illustrates this. Example: Handling multicolumn lists of values The following code fragment illustrates how to display multicolumn lists of values in the select block of the example on page 68. 70 ReportEngine Developer Guide
  • 71. Viewing Reports Handling prompts 4 if (prompt.hasLOV()) { //display the list of values Values lovValues = prompt.getLOV().getAllValues(); %><tr> <td><%=prompt.getName()%></td> <td><% if (lovValues.isMultiColumns()) { //MULTICOLUMN VALUES (1/2) display the column names String colNames = ""; for (int m = 0; m < lovValues.getRowValue(0).getCount(); m ++) colNames = colNames + " | " + lovValues.getRowValue(0).getHeader(m); %><%=colNames%><br><% } //assume multivalue LOV %><select name=<%="PromptValue"+i%> multiple size=5> <% //get value and text for the option tag for (int k = 0; k < lovValues.getCount(); k++) { String value = lovValues.getValue(k); String valueText = value; if (lovValues.isMultiColumns()) { //MULTICOLUMN VALUES (2/2) option is a row RowValue row = lovValues.getRowValue(k); value = row.getItem(0); valueText = ""; for (int n = 0;n < row.getCount(); n++) { //build a string to display the <option> tag if (n == 0) valueText = row.getItem(n); else valueText = valueText + " | " + row.getItem(n); } } %><option value="<%=value%>"> <%=valueText%> </option><% }%> </select> </td> </tr> } Note: value and valueText are different in multicolumn lists of values. The variable value contains just the first value in the row, which is passed to Prompt.enterValues to fill the prompt, whereas valueText displays all the values in the row. ReportEngine Developer Guide 71
  • 72. 4 Viewing Reports Handling prompts Chunking long lists of values Some objects, for example Customer name, can have a very long list of values. The Lov interface has methods that you can use to divide long lists of values into “chunks” that are easier to display, and easier for the user to browse: • Lov.getCurrentBatchIndex • Lov.getValues • Lov.getCurrentBatchName • Lov.setBatchSize Handling nested prompts Sometimes a list of values contains its own prompts. A prompt in a list of values is called a nested prompt. Nested prompts can be raised when a document containing prompts is refreshed and the prompts have lists of values that contain their own prompts. If a list of values contains prompts, those prompts must be filled before you can fill the prompts in the next level up. Example: Order of filling a hierarchy of nested prompts Consider the following set of prompts: Select a town from the list: (prompt in query) Select a state from the list: (prompt on list of towns) Select a country from the list: (prompt on list of states) Each prompt qualifies the one above it in the hierarchy; the country must be defined before a state can be defined and, similarly, a state must be defined before a town can be defined. You use Lov.mustFillNestedPrompts to detect if a list of values contains its own prompts, then Lov.getNestedPrompts, Prompt.enterValues IPrompt.EnterValues and Lov.setNestedPrompts to enter values for and set the nested prompts. Example: Handling nested prompts The following code fragment illustrates the recommended method for handling nested prompts. In this example, prompts and nested prompts are handled by the recursive function fillPrompts. //get the document and its prompts DocumentInstance doc = re.getDocumentFromStorageToken(token); if (doRefresh) doc.refresh(); //refresh first time only Prompts prompts = doc.getPrompts(); //if there are prompts, fill them if (doc.getMustFillPrompts()) { 72 ReportEngine Developer Guide
  • 73. Viewing Reports Handling prompts 4 this.fillPrompts (prompts, null); doc.setPrompts(); } else //all prompts are filled and can now display the report response.sendRedirect("view.jsp? Token="+doc.getStorageToken()); //FUNCTION - fill prompts and handle nested prompts public void fillPrompts (Prompts pmts, Lov parentLOV) { //pmts is the set of prompts or nested prompts to be filled //parentLOV is a LOV for which there are unfilled nested prompts for (int i = 0; i < pmts.getCount(); i++) { Lov lov = pmts.getItem(i).getLOV(); if (lov.mustFillNestedPrompts()) { Prompts nestedPrompts = lov.getNestedPrompts(); fillPrompts (nestedPrompts , lov); } //get user input for pmts //enter values for pmts } if (parentLOV != null) parentLOV.setNestedPrompts(); } Note: You can use the methods described in “Prompts with simple lists of values” on page 68 to get the user input and enter the values for nested prompts. Refreshing a list of values If the document contains lists of values with prompts, the prompts on the lists of values must be filled every time the document is refreshed, however, to make sure that the lists are up to date, you can use Lov.refresh to provide a “Refresh List” button so that the user can update the list manually. Note: This process is independent of the document refresh mechanism. After calling Lov.refresh, the next time you call Lov.getValues or Lov.getAllValues, the list of values will be refreshed. Refreshing a list of values containing nested prompts If you provide a manual refresh option, you can handle any nested prompts contained in the list of values with the fillPrompts function described in the example “Handling nested prompts” on page 72. Example: Refreshing a list of values containing nested prompts The following code fragment shows how to use the fillPrompts function described in the example “Handling nested prompts” on page 72 to handle nested prompts raised when the list of values is refreshed manually. ReportEngine Developer Guide 73
  • 74. 4 Viewing Reports Displaying a report map //get and display the LOV //if the user clicks "Refresh List" lov.refresh(); Prompts nestedPmts = lov.getNestedPrompts(); this.fillPrompts (nestedPmts, lov); Handling context prompts Universe designers define context prompts in universes to ensure users retrieve the appropriate data when there is more than one way to get the results of a query. For more information about defining contexts see Designer’s Guide. The classes and methods, and hence the process, for filling a context prompt is similar to that for filling many, simple prompts (page 65). The contexts in a document are represented by the Contexts collection, and you can detect if a document has contexts to fill with DocumentInstance.getMustFillContexts. To fill a context prompt: If contexts must be filled, 1. Get contexts. 2. Display the possible values for each context and get the user’s response. 3. Enter the values for the context provided by the user. 4. Set the contexts. 5. View the report. “Viewing reports” on page 60 explains how to view reports. Displaying a report map A ReportMap is a representation of the reports and report sections in a Web Intelligence or Desktop Intelligence document. There are two modes for calculating the contents of a report map: incremental and non-incremental. In incremental mode only the requested information is calculated, and in non-incremental mode the whole report map is calculated in one step. To get the report map for a document, call DocumentInstance.getReportMap. Example: Traversing the report map for a Web Intelligence document The following code fragment traverses the following report structure and gets a section as DHTML. 74 ReportEngine Developer Guide
  • 75. Viewing Reports Displaying a report map 4 Section1 Report1 Section2 Section1 map.getStructure() Report2 Section2 Report3 Section1 ReportMapNodes Section2 = ReportMapNode // Get the ReportMap from the document instance ReportMap map = doc.getReportMap(); //point to the root node of the structure ReportMapNodes root = map.getStructure(); // Get the number of reports in the document // There are three in this case: Report1, Report2, and Report3 int count = root.getChildCount(); // Get the first report ReportMapNode report1 = root.getChildAt(0); // Get the name of the report (Report1) String reportName = report1.getName(); // Get the report path (0) String reportPath = report1.getPath(); // Check if the report contains sections (true in this case) boolean leaf = report1.isLeaf(); // Get the number of sections in the report // There are two in this case: Section1, Section2 int section_count = report1.getChildCount(); // Get the first section ReportMapNode section1 = (ReportMapNode)report1.getChildAt(0); // Get the section name (Section1) String sectionName = section1.getName(); // Get the section path (0/0) String sectionPath = section1.getPath(); // Get the DHTML page associated with this section Report report = doc.setPath(sectionPath); HTMLView view = report.getView(OutputFormatType.DHTML); ReportEngine Developer Guide 75
  • 76. 4 Viewing Reports Displaying a report map 76 ReportEngine Developer Guide
  • 77. ReportEngine Developer Guide Drilling in Web Intelligence Reports chapter
  • 78. 5 Drilling in Web Intelligence Reports Overview Overview Drilling is one of the key features of Web Intelligence documents, helping users analyze document data. This chapter discusses how to provide drilling facilities for Web Intelligence documents. Note: you cannot drill in a Desktop Intelligence document. Introduction to drilling Drilling is a way for a user to control the amount of detail in a report. Universe designers create hierarchies of dimensions when they create universes, for example Country, State, City, Zip Code, Street. When users view reports, they can adjust the amount of detail in the reports by entering drill mode and drilling up or down according to the dimension hierarchies (often called “drill hierarchies). Note: Depending on their user rights, some users might not have access to the drilling functions. Users set the scope of analysis to control how much data Web Intelligence includes in the DataProvider(cube) it creates when a query is executed. When a user executes a query, Web Intelligence retrieves data for the dimensions in the query, but also for the dimensions that the user has included in the scope of analysis. This means that when a user drills through a dimension hierarchy the information for the new report is in the DataProvider, and it is not necessary to execute a new query to display the drilled report. See also “Drilling out of scope: the scope of analysis” on page 80. Note: The user executing the query might not be the user that set the scope of analysis. You use ReportEngine SDK to drill in Web Intelligence reports. The drilling process To provide users with a drill function, implement the following process: 1. User requests a drill operation by clicking on a drill link in a report. The request contains information about the drill operation. For example, the name of the script that will handle the request, from which dimension the drill starts, and to which dimension it goes. 78 ReportEngine Developer Guide
  • 79. Drilling in Web Intelligence Reports Introduction to drilling 5 2. The script defines the drill operation by initializing the document’s drilling objects with the information passed in the drill request. 3. The script instructs Web Intelligence to generate the HTML for the drilled report. Web Intelligence uses the information in the document’s drilling classes to generate the drilled view. 4. The script displays the drilled view generated by Web Intelligence. 5. Repeat steps 2 to 4 for each request for a drill operation. 1 st ue eq ll r Drill Option dri 2 Define drill dri ll re q ue s t 3 Generate DHTML Drill Path 5 View report 4 Table 5-1 The process you need to implement to provide a drilling function Defining the drill operation You can only define drill operations for drillable documents. A document is considered drillable if the dimensions used to form the query are part of a dimension hierarchy. Defining the drill operation involves: • getting the parameters of the drill request • defining the query string parameters • entering and leaving drill mode • setting the drill path ReportEngine Developer Guide 79
  • 80. 5 Drilling in Web Intelligence Reports Drilling in reports The details of how you define the drill operation depend on the type of report. For information on defining the drill operation for Web Intelligence reports see page 81. Generating the HTML and viewing a drilled report This step in the drilling process involves generating the HTML for the report using the drill operation you have defined. Once you have done this you can view the report as HTML using the normal workflows. Drilling out of scope: the scope of analysis An out of scope drill is one that goes up or down to a dimension that is not in the DataProvider. To fulfill this request the query must be reformed and rerun to retrieve the requested data. You can handle out of scope drills manually or transparently. How you manually handle out of scope drills depends on the type of report, however the mechanism for transparently handling out of scope drills does not depend on the report type. For information on manually handling out of scope drills for Web Intelligence reports see page 87. Transparent Drill Outside of Cube The Web Intelligence facility for automatically handling out of scope drill requests is called Transparent Drill Outside of Cube. When this is functioning, the scope of analysis of the Query is automatically reset to incorporate the data for the requested dimension. Supervisors can control a user’s access to this facility using Supervisor. Drill hierarchies Hierarchies contain dimensions and are defined by universe designers. You can see drill hierarchies in the Report Panel. A dimension contains a list of values. When a value is selected from the list, it acts as a dimension filter. Drilling in reports To provide drilling functions in Web Intelligence reports you can implement the process described in “The drilling process” on page 78, or use the drill bar to filter the query. 80 ReportEngine Developer Guide
  • 81. Drilling in Web Intelligence Reports Drilling in reports 5 Drilling information You can access drilling information by examining the contents of the universe (the drill hierarchies and dimensions), or by examining the drill bar. Drill hierarchies defined in a universe Use Report.getNamedInterface(“DrillInfo”) get aDrillInfo instance. To get the DrillHierarchies used in the report, use DrillInfo.getDrillHierarchies. A hierarchy is used if one of its dimensions is included in the query for the report. To get the dimensions and details that are not included in a hierarchy but are used in the report, use DrillInfo.getFreeDimensions. The DrillBlock object gets the drill hierarchies and dimensions for just one block (table or graph) in the report. Drill bar DrillBar exposes drill and report filters, and specific drill objects added by the user. A drill object can be a dimension, or a detail. Defining the drill operation A drill operation is defined in terms of the drill path. The drill path is represented in ReportEngine SDK by the DrillPath interface, and consists of a set of parameters such as the IDs of the objects (dimensions) from and to which the user is drilling. Defining the drill operation, therefore, involves setting the parameters of the drill path object. To define the drill operation: 1. Enter drill mode. 2. Define the query string parameters, if required. 3. Get the parameters of the drill request. 4. Set the drill path. Entering and leaving drill mode You need to put Web Intelligence into a special mode so that it can perform the drilling functions. There are two modes: ReportMode.Viewing and ReportMode.Analysis. Calling DrillInfo.beginDrill puts a report in ReportMode.Analysis (drill) mode. Calling DrillInfo.endDrill stops the drill session and puts a report in ReportMode.Viewing mode. ReportEngine Developer Guide 81
  • 82. 5 Drilling in Web Intelligence Reports Drilling in reports Defining the query string parameters In Web Intelligence users drill with hyperlinks and a popup menu generated by Web Intelligence using Javascript functions and style sheets (see “Generating the HTML and viewing a drilled report” on page 80). You can redefine the query string parameters with the DrillOption interface, then use the new names to retrieve the details of the user’s drill request and, hence, to set the DrillPath. Note: You cannot change the name and path of the image used to indicate the drill up hyperlinks. This is always ApplicationName/images/cdz/drillup.gif Example: Defining the query string parameters The following code fragment shows how to define the query string parameters used to pass drill information to the Javascript functions that generate the hyperlinks and popup menu, which provide the user with drilling functions. //set up the query string parameters used for drilling DrillOption option = info.getDrillOption(); option.setBlockHolder("Block"); option.setBlockSynchronized(true); option.setCallBackScript("drillHandler.jsp?ReportIdx=0”); option.setCallBackFrame("_self"); option.setDrillActionHolder("Action"); option.setToHolder("To"); option.setFromHolder("From"); option.setFilterHolder("Filter"); option.setHierarchyHolder("Hierarchy"); option.setStorageTokenHolder("Token"); Notice that you can add your own query string parameters to the call back script definition. Depending on the architecture of your application, and how you manage storage tokens (document state) you might need to include the storage token in the call back script definition. If you do this, remember that drilling methods such as beginDrill and executeDrill generate new tokens for the document. Getting the parameters of the drill request To get the parameters of the drill request use request.getParameter and request.getParameterValues. For example: String token = request.getParameter("Token"); String block = request.getParameter("Block"); String action = request.getParameter("Action"); String[] to = request.getParameterValues("To"); String[] from = request.getParameterValues("From"); String[] hierarchy = request.getParameterValues("Hierarchy"); String[] filter = request.getParameterValues("Filter"); 82 ReportEngine Developer Guide
  • 83. Drilling in Web Intelligence Reports Drilling in reports 5 Setting the drill path The DrillPath defines the drill operation. To set the drill path: 1. Get the DrillPath object. 2. Set the drill action. See “Setting the action: up, down, by, or slice” on page 83 below. 3. Set the block id. 4. Set the object id of the drill to element. 5. Set the object id and filter of the drill from element. Setting the action: up, down, by, or slice A user’s drill actions are classified by how they move through the drill hierarchies. Drill action Resulting report engine action Up The report engine replaces the current object with its parent in the drill hierarchy. Down The report engine replaces the current object with its child in the drill hierarchy. By The report engine replaces the current object with an object that is not adjacent to it in the drill hierarchy. Slice The report engine adds or removes the filtered values. hierarchy 1 hierarchy 2 dimension 1 dimension 5 down up dimension 2 dimension 6 by dimension 3 dimension 7 down or by dimension 4 slice Table 5-2 Different drill actions You set the drill action with DrillPath.setAction. The actions are enumerated by DrillActionType. Setting the from and to parameters To set the from and to parameters of the drill, you define the elements of the drill. The elements of the drill are the dimensions involved in the drill action and are represented by the DrillElements interface. There is a DrillElements object for the to and for the from dimensions. Individual from and to elements are represented by DrillFromElement and DrillToElement. ReportEngine Developer Guide 83
  • 84. 5 Drilling in Web Intelligence Reports Drilling in reports For each drill operation: 1. Get the drill from and to elements with DrillPath.getTo and DrillPath.getFrom. 2. Add drill elements to each collection. 3. Set the object IDs of each drill element using the values you retrieve from the query string. 4. For each from element, set the filter, if any. Note: The filter remains for drill-by actions between dimensions in the same hierarchy. However for drill-up actions the filter is removed. Note: For example, in the Time Period hierarchy, if you drill down to Quarters from Year = 2003, all the quarters for 2003 are displayed, then if you drill by Year, only Year= 2003 is displayed. However if you drill up from Quarters to Year, all the values for Years are displayed. Example: Setting the drill path The following code fragment shows how to set the values of the drill path. The parameters of the drill (action, from, to, block) are retrieved as described in “Getting the parameters of the drill request” on page 82. DrillPath drill = info.getDrillPath(); //set the ACTION if (action.equals("down")) drill.setAction(DrillActionType.DOWN); else if (action.equals("up")) drill.setAction(DrillActionType.UP); else if (action.equals("slice")) drill.setAction(DrillActionType.SLICE); else if (action.equals("by")) drill.setAction(DrillActionType.BY); //set the BLOCK drill.setBlockID(block); //set the TO drill elements if (to.length > 0) { DrillElements toElements = drill.getTo(); for (int j = 0;j < to.length; j++) { DrillToElement toElement = (DrillToElement) toElements.add(); toElement.setObjectID(to[j]); } } //set the FROM drill elements if (from.length > 0) { DrillElements fromElements = drill.getFrom(); for (int k = 0; k < from.length; k++) { DrillFromElement fromElement = (DrillFromElement) fromElements.add(); fromElement.setObjectID(from[k]); if ((filter != null) && (filter.length > 0)) fromElement.setFilter(filter[0]); 84 ReportEngine Developer Guide
  • 85. Drilling in Web Intelligence Reports Drilling in reports 5 } } This example assumes that there is only one value in the array filter — fromElement.setFilter(filter[0]). This is true for simple drilling, however, to handle more sophisticated drilling you need to use all the values in the array of filters. Also, in the part that sets the filter, you can add the condition ‘if !action.equals(“up“)’ since there is no filtering in a drill-up operation, however, if you set a filter for a drill-up operation, it is ignored. Generating the HTML and viewing a drilled report To generate the HTML for the report execute the drill with DrillInfo.executeDrill, then view the generated HTML using HTMLView.getContent(see “Displaying the drilled report” on page 86. See also “Viewing an individual report in DHTML” on page 62). In drill mode (ReportMode.Analysis) when you call Report.getView(OutputFormatType.DHTML) Web Intelligence generates DHTML that uses scripts and style sheets to provide the drilling interface. Copying the Java script files for drilling The Java script files used to create the drilling user interface are stored in /businessobjects/enterprise11/desktoplaunch/viewers/cdz/. Copy the following files from this directory to the same directory as your script that displays the DHTML view of the report. • bomenuIE.js • browserDetection.js • drillcontext.js • drillcontextDom.js • /language/language/message.js Where language is the language of the messages. These scripts use the styles defined in bomenu.css and the .gif files in the images folder. To get these files, copy the following to the directory containing the copied Java script files: ReportEngine Developer Guide 85
  • 86. 5 Drilling in Web Intelligence Reports Drilling in reports • /businessobjects/enterprise11/desktoplaunch/viewers/cdz/style/ skin_name/bomenu.css skin_name is one of: skin_default, skin_corporate, or skin_coloredline. The fonts used in bomenu.css do not include some special characters. To display characters such as the yen symbol (¥) use bomenu_fe.css. • /businessobjects/enterprise11/desktoplaunch/viewers/cdz/images/ Referencing the Javascript files for drilling The DHTML generated by Report.getView references these files and you need to include this in your header with HTMLView.getString("head", false). For an example of how to do this, see “Displaying the drilled report” on page 86. Displaying the drilled report To display the drilled report, call HTMLView.getContent. Alternatively you can call HTMLView.getString() which retrieves both the appropriate HTML header and the drilled report, however, it means you can't add supplementary HTML to the page. Example: Displaying the drilled report The following code fragment illustrates how to display a report after executing the drill. <% HTMLView htmlView = null; htmlView = (HTMLView) rep.getView(OutputFormatType.DHTML); String htmlHeader = htmlView.getStringPart("head", false); %> <html> <!-- DRAW HEADER --> <head> <link rel="stylesheet" type="text/css" href="style/bomenu.css"> <%=htmlHeader%> </head> <!-- DRAW REPORT--> <%=htmlView.getStringPart("body", true)%> </html> 86 ReportEngine Developer Guide
  • 87. Drilling in Web Intelligence Reports Drilling in reports 5 Manually handling out of scope drill requests Once you have set the DrillTo and DrillFrom elements you can detect if a drill dimension is not in scope with DrillDimension.isInScope. If the defined drill operation contains out of scope dimensions with DrillInfo.willGoOutOfScope. If the DrillDimension is outside the scope of analysis you can manually extend the scope of analysis with DrillInfo.extendScopeOfAnalysis. This method returns a DrillElements collection to which you can add the extra drill dimensions that the user wants to include in the analysis. You commit the changes you make to the scope of analysis by calling DrillInfo.executeDrill. If you want to add a query filter to the extended scope of analysis, use DrillInfo.addQueryConditions. This returns a DrillElements collection to which you can add the ID of the filter dimensions and the associated filter values. You commit this change with DrillInfo.executeDrill. See also, “Adding query conditions using the drill bar” on page 88. Adding objects that have prompts If you extend the scope with an object that contains a prompt in its universe definition, you need to fill the prompts it raises before you execute the drill. See “Handling prompts” on page 64 to find out how to do this. Filtering with a drill bar The DrillBar object exposes the drill filters and specific objects added by the user. By default, the drill bar is initialized with the report filter, but it can be customized by the user to add or remove drill objects. Drill objects can be dimensions, or details. In the example below, the DrillBar object contains three objects, the Country dimension filtered on the US value, the Resort dimension filtered on the Bahamas Beach value, and the unfiltered Service Line object. You access the drill bar using DrillInfo.getDrillBar, and you add and remove objects to and from the drill bar with DrillBar.add and Drillbar.remove. ReportEngine Developer Guide 87
  • 88. 5 Drilling in Web Intelligence Reports Drilling in reports Note: When you remove an object from the drill bar, it is automatically removed from the report filter. Adding query conditions using the drill bar You can use the filters in the drill bar to add query conditions when extending the scope of analysis. For example, if the drill bar has the filter Country = US, when the scope is extended you can use this object to form a query condition before executing the SQL. This limits the amount of information returned into the cube to results for Country = US, and is more rapid than retrieving the results for all the values of Country. The filters set in the drill bar can affect other result objects. For example, if you set the filter Month = February, the results for Quarter are automatically limited to Quarter = Q1; you cannot view the results for Month = February and Quarter = Q3. Note: Changing the query affects all the reports in the document. If you add a condition to the query, information in other reports in the document might change. For more information see “Manually handling out of scope drill requests” on page 87. Taking a snapshot of a drill You can use DrillInfo.snapshot to put aside a drilled view and continue drilling. This method adds a report containing the current view to the document’s report list and report map. 88 ReportEngine Developer Guide
  • 89. ReportEngine Developer Guide Building and Editing Data Providers chapter
  • 90. 6 Building and Editing Data Providers Overview Overview A data provider holds information about a query. Using a data provider you can get the SQL for a query, retrieve the data returned when the query is executed, and explore the data source (universe) through which the data was retrieved. This chapter explains how to use ReportEngine SDK to build data providers and edit queries for Web Intelligence and Desktop Intelligence reports. Data providers A data provider has two parts: a query and a data source. The query The query part of a data provider defines the data to be retrieved. The query is expressed in terms of the data source objects (universe objects, also known as result objects) of interest and conditions which restrict the data retrieved. The query can also have an associated scope of analysis which includes more data in the retrieved microcube than the query requires. This helps when you are providing drilling features (see “Scope of analysis” on page 97 and “The drilling process” on page 78). The query of a data provider is exposed in ReportEngine through the Query and Scope objects. Conditions on queries are expressed as a syntax tree in which conditions and operators (for example AND, and EQUAL TO) are nodes in the tree. This syntax tree is created with the ConditionContainer set of classes. See “Conditions” on page 98. The data source The data source of a data provider gives you access to the universe used to define the query. ReportEngine SDK exposes the following universe elements: • class • hierarchy • dimension • measure • detail • predefined condition 90 ReportEngine Developer Guide
  • 91. Building and Editing Data Providers Building a data provider 6 Using the classes that expose these universe elements, you can present the contents of a universe to users as classes and objects for query editing, or as drill hierarchies in a drill bar. Use the following classes to explore a universe: • DataSource (universe) • DataSourceObjects (classes and hierarchies in the universe) • DataSourceObject (elements of the universe) Universe elements can be classes, conditions, dimensions, details, measures, or hierarchies. DataSourceObject is a specialization of the TreeNode class. You use DataSourceObject to create and edit the query, but after you execute the query the objects are stored in the document's dictionary as ReportExpression objects. Building a data provider You can build a data provider by: • Integrating the Web Intelligence Java Report Panel into your application. • Building a data provider manually with ReportEngine SDK. Integrating the Web Intelligence Java Report Panel into your application The Web Intelligence Java Report Panel is the standard method for users to create data providers and edit queries. ReportEngine Developer Guide 91
  • 92. 6 Building and Editing Data Providers Building a data provider Table 6-1 The Web Intelligence Java Report Panel Note: This applet is different from previous releases of Web Intelligence. Launching the Web Intelligence Java Report Panel You use the <applet> or <object> tag to declare the applet, and the <param> tag to specify the applet’s parameters. All parameters are of the type java.lang.String. 92 ReportEngine Developer Guide
  • 93. Building and Editing Data Providers Building a data provider 6 Parameters Value(s) Description Applet parameters code “com.businessobjects.w The path to the p.tc.TCMain” applet. useslibrary “Web Intelligence The name of the Report Panel” applet. useslibrarycodebase “/webiApplet/ The path to the ThinCadenza.jar” archive containing the applet HelpRoot - The path to the online help. Lang “en”; “jp” The language of the user interface. Server parameters Server - The name of the server from which the applet is downloaded. Isapi “/servlet/ The path to the com.businessobjects.cd servlet through which zlet. the server and the CadenzaServlet” browser communicate. Port default is “8080” The port used for the application server CdzSession use the string returned The session identifier by ReportEngine. for the open getServerInstance document. Document parameters Token use the string returned The storage token for by DocumentInstance. the document. getStorageToken when editing an open document RepoType “corporate”; “inbox”; The type of the “personal”. repository in which the document is stored. DocumentID - The id of the document. ReportEngine Developer Guide 93
  • 94. 6 Building and Editing Data Providers Building a data provider Parameters Value(s) Description DocumentName - The name of the document. OpenFirstClassOfUniverse - If present, the applet automatically opens the first class of the universe. Data source parameters UniverseID “UnivCUID=universe The id of the universe cid value” on which the query will be run. You can use the implicit request object (javax.servlet.http.HttpServletRequest) to get the values for some of these parameters. For example, you can use request.getServerName and request.getServerPort to populate the Server and Port parameters. Note: Some parameters are optional depending on what you are doing with the applet. For example, if you are creating a new document, you do not need to provide a storage token. Example: Launching the Java Report Panel The following example shows functions that use BusinessObjects Enterprise SDK to recover a universe object from a valid ID. This Universe can be used to supply information necessary to start the Java Report Panel <%! IInfoObject getUniverse(IInfoStore iStore, String ID){ IInfoObjects universes = null; IInfoObject universe = null; try{ String sQuery = "SELECT SI_CUID, SI_NAME FROM” + “ CI_APPOBJECTS WHERE SI_ID = " + ID + " AND SI_KIND = '"+ CeKind.UNIVERSE +"'"; universes = (IInfoObjects) iStore.query(sQuery); if(universes.size() > 0) universe = (IInfoObject)universes.get(0); }catch(Exception e){ universe = null; } return universe; } %> // The following script retrieves all necessary // parameters and then launches the Web Intelligence Java // Report Panel. <% IInfoStore iStore = (IInfoStore) session.getAttribute("InfoStore"); 94 ReportEngine Developer Guide
  • 95. Building and Editing Data Providers Building a data provider 6 ReportEngine wiRepEngine = (ReportEngine) session.getAttribute("ReportEngine"); String ID = request.getParameter("uID"); universe = getUniverse(iStore, ID); if (universe != null){ String currPath = request.getServletPath(); String contextPath = request.getContextPath(); String serverName = request.getServerName(); int serverPort = request.getServerPort(); currPath = currPath.substring( 0, currPath.lastIndexOf( '/' ) + 1 ); currPath = contextPath + currPath; String instanceID = wiRepEngine.createServerInstance(); String strWISession = instanceID.substring(0,instanceID.indexOf(",")); %> <APPLET CODE="com.businessobjects.wp.tc.TCMain" CODEBASE="<%= contextPath %>/webiApplet/" ARCHIVE="ThinCadenza.jar" style=" width: 100%; height: 100%;"> <PARAM NAME=CODE VALUE="com.businessobjects.wp.tc.TCMain" > <PARAM NAME=CODEBASE VALUE="<%= contextPath %>/webiApplet/"> <PARAM NAME=ARCHIVE VALUE="ThinCadenza.jar" > <PARAM NAME="type" VALUE="application/x-java-applet;version=1.4"> <PARAM NAME="Isapi" VALUE="<%= contextPath %>/CadenzaServlet"></PARAM> <PARAM NAME="Server" VALUE="<%= serverName %>"></PARAM> <PARAM NAME="Protocol" VALUE="http"></PARAM> <PARAM NAME="Port" VALUE="<%= serverPort %>"></PARAM> <PARAM NAME="Type" VALUE="signed"></PARAM> <PARAM NAME="WebiSession" VALUE="<%= strWISession %>"></PARAM> <PARAM NAME="CdzSession" VALUE="<%= instanceID %>"></PARAM> <PARAM NAME="DocumentID" VALUE=""></PARAM> <PARAM NAME="UniverseID" VALUE="UnivCUID=<%=universe.getCUID()%>"></PARAM> <PARAM NAME="bRobot" VALUE="false"></PARAM> <PARAM NAME="bTraceInLogFile" VALUE="false"></PARAM> <PARAM NAME="HelpRoot" VALUE="<%= contextPath.substring(1) %>"></PARAM> <PARAM NAME="SaveAs" VALUE="<%= contextPath %>save.jsp"></PARAM> <PARAM NAME="Lang" VALUE="<%= request.getLocale().getLanguage() %>" ></param> </APPLET> ReportEngine Developer Guide 95
  • 96. 6 Building and Editing Data Providers Building a data provider Building a data provider manually When you create a new document instance, Web Intelligence automatically creates an empty data provider for the document. The data provider has a data source and an empty query object. Building a data provider consists in populating the query object with the data source objects in which you are interested. To build a data provider: 1. Get the collection of data providers for the document. 2. Get the universe elements in which you are interested. 3. Get the query for the data provider. 4. Add result objects. 5. Add condition objects (optional). 6. Execute the query. Example: Building a data provider The following code fragment illustrates how to populate the query object of a data provider. //select a universe ==> sID ... //create a new document instance DocumentInstance doc = reportEngine.newDocument(sID); DataProviders dps = doc.getDataProviders(); // Retrieve the 1st data provider DataProvider dp = dps.getItem(0); // Retrieve the universe objects DataSource ds = dp.getDataSource (); DataSourceObject city = ds.getClasses().getChildByName("city"); DataSourceObject year = ds.getClasses().getChildByName ("year"); DataSourceObject sales = ds.getClasses().getChildByName ("sales"); Query q = dp.getQuery(); // Add result objects to the query q.addResultObject (city); q.addResultObject (year); q.addResultObject (sales); // Run the query: execute the query and fetch the data dp.runQuery(); Editing queries A query is represented by the Query object and has the following parts: • a list of result objects 96 ReportEngine Developer Guide
  • 97. Building and Editing Data Providers Building a data provider 6 • a scope of analysis that defines the amount of data available in the cube • conditions that restrict the amount of data retrieved from the data source To get the query for a data provider, use DataProvider.getQuery. Result objects A result object is a class or an object in a universe. Including a result object in the query is the same as dragging and dropping an object into the Results area of the Query Panel of the Web Intelligence Java Report Panel. When you execute the query, the result object is added to the report dictionary (as a report expression, see “Block structure: axes and report expressions” on page 108) and is available for editing reports. To add a result object to the query, use Query.addResultObject. To remove a result object from the query, use Query.removeResultObject. Scope of analysis The scope of analysis is a feature that enables you to include more information in a cube than the query requires. This is very helpful in drilling as it is avoids modifying the query for every drill operation. See “Drilling in reports” on page 80. The scope of analysis is defined in terms of the scope level and is represented by the Scope interface. The scope level specifies how many objects of a class hierarchy are retrieved when you run the query. The scope level can be LEVEL_1, LEVEL_2, LEVEL_3, or CUSTOM. A scope level of LEVEL_1 indicates that just the result object specified in the query is retrieved. A scope level of LEVEL_3 indicates that the first three objects in the class hierarchy, starting with the result objects specified in the query, will be included in the retrieved results. If you modify the elements in the scope of analysis, Web Intelligence changes the scope level accordingly. If you create a scope of analysis that does not match an existing hierarchy, for example, if you remove the Quarter object from the scope of analysis so that a drill on the Year goes to the Month object, the scope level is set to CUSTOM, however, if you remove the third level from a LEVEL_3 scope of analysis, Web Intelligence sets the scope level to LEVEL_2. To get the scope of analysis for a query, use Query.getScope. To modify a scope of analysis add and remove the objects you want in the scope of analysis with Scope.addScopeObject and Scope.removeScopeObject. ReportEngine Developer Guide 97
  • 98. 6 Building and Editing Data Providers Building a data provider Conditions A condition is a constraint on the data retrieved when you run a query, and is sometimes called a query filter. For example, if you add the result objects Year, Revenue, Store, and Company Average, then define the condition ((Year between 1995 and 1999) AND (Revenue < Company Average)), the query would return only data about the stores that, between 1995 and 1999, achieved revenues below the company average. For more information on conditions see Web Intelligence User’s Guide. Simple conditions The simplest condition consists of a container, a data source object, and unary operator. For example, in the condition (Revenue is not NULL), “Revenue” is the object, and “is not NULL” is the operator. In ReportEngine SDK, this condition is represented as follows. FilterConditionContainer ConditionObject getDataSourceObject = Revenue FilterCondition getOperator = NOT_IS_NULL The FilterCondition class holds information about operators and operands. For some operators, such as BETWEEN, the FilterCondition contains more than one operand. Example: Creating a simple condition The following JSP code fragment creates the condition (Revenue < 10000). Query q; //query to which the condition is applied //create a container for the condition ConditionContainer c1 = q.createCondtion(); //create an object for the condition ConditionObject co = c1.createConditionObject(revenue); //create a FilterCondition object to contain information //about the operator and the operand FilterCondition fc = co.createFilterCondition(Operator.LESS); fc.createFilterConditionConstant("10000"); Complex conditions By combining containers with operators and adding extra condition objects you can build very complex conditions. 98 ReportEngine Developer Guide
  • 99. Building and Editing Data Providers Building a data provider 6 Example: Structure of a complex condition The following is a representation in REBean of the condition: (Revenue < 1000000) OR ((Year = 2002) AND (Holiday)). FilterConditionContainer(OR) ConditionObject getDataSourceObject = Revenue FilterCondition getOperator = LESS getOperand = 1000000 FilterConditionContainer(AND) ConditionObject ConditionObject getDataSourceObject = Year getDataSourceObject = Holiday FilterCondition getOperator = EQUAL getOperand = 2002 In this example the data source object used for the last part of the condition (Holiday) is a predefined condition that is part of the universe, and it does not need a corresponding FilterCondition object. Including a prompt in a condition To include a prompt in a condition use FilterCondition.createConditionPrompt. This method returns a ConditionPrompt object that you can use to define a prompt that is activated when the query is executed. As with normal prompts when you create a condition prompt you need to define the name of the prompt (that is, the question that is asked). You can also define properties such as its default value, and whether or not it is constrained to a list of values. You handle these prompts with the same workflows that are described in “Handling prompts” on page 64. Example: Including a prompt in a condition The following JSP code fragment creates the condition prompt “Year?” //get the query (q) to which the condition is applied //... //create a container for the condition ConditionContainer cc = q.createCondition(); //create an object for the condition ConditionObject co = cc.createConditionObject(country); //create a FilterCondition object to contain the prompt FilterCondition fc = co.createFilterCondition(Operator.EQUAL); //define the prompt ReportEngine Developer Guide 99
  • 100. 6 Building and Editing Data Providers Executing queries and retrieving the data ConditionPrompt cp = fc.createConditionPrompt("Country?"); cp.setConstrained(false); cp.setMonoValue(true); cp.addDefault("Australia"); Executing queries and retrieving the data When a query is executed and data retrieve, contexts and prompts are raised that need to be handled. It is possible to execute a query without retrieving data, in which case no prompts or contexts need to be handled. To execute the query and… Use… not retrieve the data DataProvider.executeQuery The user does not need to set any prompts or contexts. retrieve the data DataProvider.runQuery If there are prompts or contexts, the user must set these using the same procedure as for viewing a document. DataProvider.runQuery puts the data it retrieves into the results recordset of the data provider. Use DataProvider.getResults to retrieve the recordset. For an example of how to access the values in the recordset see “Working with Recordsets” on page 117. Getting the SQL for the query Web Intelligence uses the properties of the Query object to create the SQL statement it executes when you execute the query. To get the SQL for a query, use Query.getSQL. 100 ReportEngine Developer Guide
  • 101. ReportEngine Java Developer Guide Formatting Reports chapter
  • 102. 7 Overview Report Engine SDK contains classes and methods for controlling the format of reports. Applications for formatting Web Intelligence reports (*.wid) create and edit document structures, sections, cells, and page decoration. This chapter discusses how to use REBean to format Web Intelligence reports. Creating and editing the document structure You can access and change the structure of a Web Intelligence document. A Web Intelligence document is made up of at least the following elements: • report • page header/footer • report body A document can also contain: • sections • blocks • report cells • free cells It is often useful to create a blank Web Intelligence document within which you can manually build queries and report structures. To create a blank document use DocumentInstance.newDocument. Example: Creating a blank document This example shows a JSP functions that use BusinessObjects Enterprise SDK to recover the ID of the Universe parent folder. Using this ID an IInfoObjects containing information about Universes stored in the Central Management System is returned. IInfoObjects getUniverses(IInfoStore iStore, int searchID) { int ROOT_FOLDER_ID = 95; IInfoObjects rootDirs = null; IInfoObjects universes = null; String rootQuery = "SELECT SI_ID, SI_NAME FROM” + “ CI_APPOBJECTS WHERE SI_PARENTID=" + ROOT_FOLDER_ID ; String unvQuery = "SELECT SI_ID, SI_NAME, SI_CUID,” + “ SI_OWNER, SI_PARENTID, SI_KIND" + " FROM CI_APPOBJECTS WHERE SI_ANCESTOR="; 102 ReportEngine Java Developer Guide
  • 103. 7 try{ //get the Universe Root directory rootDirs = iStore.query(rootQuery); if (rootDirs.size() > 0){ //Get the Universes IInfoObject rootDir = (IInfoObject)rootDirs.get(0); unvQuery += rootDir.getID(); universes = iStore.query(unvQuery); } }catch (SDKException sdke){ universes = null; } catch (Exception e){ universes = null; } return universes; } The following code fragment creates a blank document using the first universe in the collection of universes as a data source. //Recover the universe list IInfoStore iStore = (IInfoStore)session.getAttribute("InfoStore"); ReportEngines webiRepEngines = (ReportEngine)session.getAttribute("ReportEngines"); ReportEngine webiRepEngine = webiRepEngines.getService( ReportEngineType.WI_REPORT_ENGINE); IInfoObjects universes = getUniverses(iStore, iID); //Get the first universe IInfoObject universe = (IInfoObject)universes.get(0); //then create the blank document DocumentInstance doc = webiRepEngine.newDocument(universe.getID()); ReportEngine Java Developer Guide 103
  • 104. 7 Representing document structure through containment Document elements are structured according to their containment relationship. This element… Can contain these elements… report page header/footer, report body report body sections, blocks, and cells page header/footer cells section sections, blocks, and cells The containment relationship between the elements of a document is represented in the object model as a tree using TreeNode, ReportElementContainer, and ReportElement. report report page header page header free cell free cell report body report body free cell section section report cell block section block block free cell page footer page footer free cell free cell Table 7-1 Structures of a document with one report, one section, and two blocks, and another with one report, two sections, and one block. Notice that, to have two sections in a report, the relationship between the sections is containment. 104 ReportEngine Java Developer Guide
  • 105. 7 Example: Creating a document structure The following code fragment creates the document structure shown in the diagram. This code creates a new document and a report and adds information to the header and footer parts. It then creates a section and a block and adds universe objects (report expressions) to the block. //create an empty document and a new report DocumentInstance doc = engine.newDocument("1"); ReportContainer report = doc.createReport("My Report"); PageHeaderFooter header = report.getPageHeader(); Cell headerCell = header.createFreeCell("header cell"); PageHeaderFooter footer = report.getPageFooter(); Cell footerCell = footer.createFreeCell("footer cell"); BodyReport body = report.getBodyReport(); // create a section SectionContainer sectionYear = body.createSection(); sectionYear.getAxis().addExpr(yearExpr); //[Year] // create a block ReportBlock block1 = sectionYear.createBlock (); BlockAxis hAxis = block1.getAxis(TableAxis.HORIZONTAL); hAxis.addExpr(quarterExpr); //[Quarter] // create another block ReportBlock block2 = body.createBlock (); BlockAxis hAxis2 = block2.getAxis(TableAxis.HORIZONTAL); hAxis2.addExpr(revenueExpr); //[Sales Revenue] doc.applyFormat(); Table 7-2 Report structure defined by the code example above Note: The header, footer, and report body elements are created by default. Also, when you create a block, the default type is TableType.HTABLE. ReportEngine Java Developer Guide 105
  • 106. 7 Positioning document elements By default, elements are positioned using x-y co-ordinates referenced from the top left corner of the containing element. x y body report free cell You can express x and y in millimeters or inches. Using attachments to avoid overlapping elements Since the size of some elements, for example table blocks, is not known at the time the report is formatted, sometimes elements overlap. To avoid this you can use the attachment feature. An attachment is a way to position a Cell or ReportBlock element relative to other elements. An attachment consists of a vertical anchor, horizontal anchor and a pair of x-y co-ordinates. Vertical anchors can be either TOP, BOTTOM or NONE. Horizontal anchors can be either RIGHT or LEFT or NONE. For example, in the diagram below the attachment between block 1 and block 2 has a vertical anchor set to BOTTOM and a horizontal anchor set to NONE, and the anchor between block 1 and cell 1 has a vertical anchor set to NONE and a horizontal anchor set to RIGHT. xb1 xc1 yb1 attachmentb1-c1 block 1 cell 1 attachmentb1-b2 yb2 block 2 Table 7-3 Positioning elements relative to the parent container and siblings. 106 ReportEngine Java Developer Guide
  • 107. 7 Example: Creating an attachment The following Java code fragment creates and positions the elements shown in the diagram above. In this example, the x and y co-ordinates’ parameters are in millimeters and are cast to the required type (double) using the “d” operator. //units = UnitType.MILLIMETER // Create block 1 (b1) as child of the ReportBody container ReportBlock b1 = report.getReportBody().createBlock(); // Set the block’s position relative to its container b1.setX(150d); // Xb1 b1.setY(10d); // Yb1 // Create block 2 (b2) and cell 1 (c1) ReportBlock b2 = report.getReportBody().createBlock(); ReportBlock c1 = report.getReportBody().createFreeCell(" "); // Attach cell 1 to block 1 (RIGHT attachment): b1-c1 c1.setAttachTo(b1, VAnchorType.NONE, HAnchorType.RIGHT); // Position cell 1 relative to block 1 c1.setX(200d); // Xc1 // Attach block 2 to block 1 (BOTTOM attachment): b1-b2 b2.setAttachTo(b1, VAnchorType.BOTTOM, HAnchorType.NONE); // Position block 2 relative to block 1 b2.setY(200d); // Yb2 Creating and editing sections A report can have zero or more sections, each one containing blocks, cells and/or other sections. A section has one axis with one report expression, and, by default, each report expression has a corresponding report cell. To check if a report cell is a section container use: ReportCell.isSection. When you add report expressions to the section’s axis, they are added to the right of the last one added. Example: Editing the sections of a report The following code fragment creates two sections, one for Year and another for Country. SectionContainer sc, sc2; ReportExpression reYear; ReportExpression reCountry; sc.getAxis().addExpression(reYear); sc2 = sc.createSection(); sc2.getAxis().addExpression(reCountry); ReportEngine Java Developer Guide 107
  • 108. 7 When you add an expression to the axis of a section, a cell for the expression is automatically created. In the example above, report cells for =[Year] and =[Country] are created. Creating and editing blocks Block is a generic name for tables, cross tables, forms, and graphs. Block structure: axes and report expressions A block axis is an oriented collection of one or more report expressions. A report expression is a report object or a variable. For example, [Customer]. Report expressions are stored in the document dictionary when a query is executed, and are represented in REBean by the ReportExpression interface. Sections and report blocks have axes. A section has one axis. A report block has one, two, or three axes. The following table shows the axes for each type of block. Block type Axes vertical table one horizontal axis horizontal table one vertical axis cross table horizontal, vertical, and content axes graph x, y, and z axes For a vertical table the report expressions are displayed in columns. Table 7-4 Structure of a vertical table Note: The block type determines the operators applied to the expression in the report. For example, in the above example the report expression [year] is shown in the table as NameOf([year]) and =[year]. For a horizontal table the report expressions are displayed in rows. 108 ReportEngine Java Developer Guide
  • 109. 7 Table 7-5 Structure of a horizontal table For a cross table the report expressions are displayed in columns and rows with a shared body. Table 7-6 Structure of a cross table In a graph the report expressions are displayed as a picture with two or three dimensions. ReportEngine Java Developer Guide 109
  • 110. 7 Table 7-7 Structure of a graph Example: Building a report: adding expressions to axes The following code fragment builds a report structure by retrieving the report expressions from the document dictionary. // Retrieve the dictionary associated with the document // populated by the last call to Document.runQuery ReportDictionary dico = doc.getDictionary(); // Create a new report ReportContainer report = doc.createReport("My Report"); BodyReport body = report.getBodyReport(); // Create a section as the body report child SectionContainer section = body.createSection (); ReportExpression ctryExpr = dico.getChildByname("ParentCountryID"); // Add the country object on the section axis section.getAxis().addExpr(ctryExpr); // Create a block in the section container ReportBlock block = section.createBlock (); ReportExpression yearExpr = dico.getChildByName("ParentYearID"); ReportExpression revExpr = dico.getChildByName("ParentRevenueID"); // Add the Year and Revenue objects on the vertical axis of // the horizontal table. block.getAxis (TableAxis.HORIZONTAL).addExpr (yearExpr); block.getAxis (TableAxis.HORIZONTAL).addExpr (revExpr); 110 ReportEngine Java Developer Guide
  • 111. 7 doc.applyFormat (); Sorting report expressions You can sort report expressions into ascending or descending natural order. The natural order of an object is the one used in the database. Sorts are stored in a collection (Sorts) that defines the type and priority of the sort. By default the first sort in the collection has the highest priority. Breaks You can add breaks to report expressions. You can add breaks to report expressions belonging to an axis, and you can show or hide the break’s header and footer using the BreakElement interface. By default the header and footer are hidden. Breaks are stored in a collection. The first element in the collection has the highest priority. Calculations You can add a calculation to a report expression. For example, the predefined calculation Sum adds the values of the report expression. By default, the results of a calculation are placed in the footer of a table, and use the name of the calculation as a label for the result. For a percentage calculation, a Percentage column is also added. Representing a block A block can be represented as a vertical or horizontal table, a cross table, a form, or a graph. The interface Representation defines how a block is represented. Vertical and horizontal tables The header, footer and body of the table are exposed through the Table class as a CellMatrix collection, which contains TableCell objects. Vertical and horizontal tables use the SimpleTable specialization of Table. You can change the following properties of the header, footer and body of a table with the Table interface: • visibility • repetition • decoration ReportEngine Java Developer Guide 111
  • 112. 7 The settings on low level objects are inherited from their parents but, if changed, override those of their parents. Cross tables Cross tables use the CrossTable specialization of Table, and the cells in a cross table are grouped into zones. Top - Left Top - Body Top - Right Body - Left Body - Body Body - Right Bottom - Left Bottom - Body Bottom - Right The zones correspond to parts of a cross table in structure view. Zones that can contain more than one cell, for example Body - Body, contain a matrix of TableCell objects that are contained in the collection CellMatrix. Note: If you add a break to the report expressions in a cross table, each break has its own header and footer and each zone (except Body - Body) contains a division for each break. Forms Forms are represented by the Form interface. The cells in the form are represented by a CellMatrix object, and you can set the decoration of labels and values separately. Graphs Graphs are represented by the Graph interface, and a set of interfaces that represent parts of the graph: Legend, GraphTitle, GraphData, GraphAxisValues, GraphAxisProperties, Graph3D, and Wall. Developer Suite supports the following graphs. 112 ReportEngine Java Developer Guide
  • 113. 7 Graph category Graph type Bar Vertical Grouped Horizontal Grouped Vertical Line and Bar Horizontal Line and Bar Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D Line Vertical Mixed Horizontal Mixed Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D 3D Surface Area Vertical Absolute Horizontal Absolute Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D Area 3D Surface Pie Pie Doughnut 3D Pie 3D Doughnut Radar & Scatter Stacked Area Radar Polar Scatter Radar Line ReportEngine Java Developer Guide 113
  • 114. 7 Creating and editing cells A cell is a report element that contains information such as the title of the report, or the heading of a section. There are two types of cell: free cell, and report cell. Free cells contain a string and are exposed with the class FreeCell. Report cells contain a formula of a section axis and are exposed with the class ReportCell. You can add a cell to all the elements contained in a report element. For more information on containment rules see “Representing document structure through containment” on page 104. Creating and editing the page decoration Page decoration refers to the display aspects of the contents of a cell. For example, the font, color, and size of the text in the cell. You can control the decoration of most cells in a report using the Decoration interface. The Decoration interface provides a gateway for other interfaces such as Alignment, Attributes and Font. Alignment Using the Alignment interface you can set the horizontal and vertical alignment of the cell contents. You can also set the wrapping properties of text in the cell. Attributes The Attributes interface represents the “non-font” aspects of the cell’s presentation. Using this interface you can set properties such as the background and foreground image, the color of the foreground and background, and the properties of the cell border (which is represented by the interface Border). Font The Font interface allows you to determine the color, style, size and font name of the text in the cell. 114 ReportEngine Java Developer Guide
  • 115. 7 Page layout You can control the page layout of a report using the PageLayout, Visibility and Repetition classes. The classes give you control over how blocks behave around page breaks, repeating blocks on every page, displaying calculations and breaks, and hiding and showing the elements of a report. Paper size You can set the page size for the document to the following paper sizes: Custom, A4 to A0, and Letter, and orient the page in landscape, or portrait views. All the margins are adjustable and you can set the units to millimeters, or inches. ReportEngine Java Developer Guide 115
  • 116. 7 116 ReportEngine Java Developer Guide
  • 117. ReportEngine Developer Guide Working with Recordsets chapter
  • 118. 8 Working with Recordsets Overview Overview ReportEngine SDK often uses the recordset data structure for storing information such as the results in a data provider. This chapter explains how to use the recordset classes of the ReportEngine SDK. Anatomy of a recordset In ReportEngine SDK recordsets provide a generic way of representing the data about, or contained in, a group of objects. a b c 10.0 field d e f 20.0 fields current record g h i 30.0 j k l 40.0 recordset m n o 50.0 p q r 60.0 s t u 70.0 Each recordset is divided into rows and columns. Each row can be considered a record (or a set of fields) and you can access only one record at a time. Recordsets In ReportEngine SDK the Recordset interface represents recordsets. Field names Recordset.getColumnName(n) gives the name of the nth field in the current record. The names of the fields in most recordsets are fixed. You can find the names listed under the method descriptions in the ReportEngine SDK API Reference. The exception to this is DataProvider.getResult which returns a recordset in which the names of the fields are the names of the results (columns) of the query. 118 ReportEngine Developer Guide
  • 119. Working with Recordsets Anatomy of a recordset 8 Moving around the recordset Recordsets can contain only one record (row) at a time. To load it use the move methods of Recordset: • first, last, next, previous, and setRow The Recordset class has a feature for setting the direction. You can set the direction to FORWARD(default) or REVERSE. When the direction is set to forward calling Recordset.next moves to the next row in the collection and when it is set to reverse calling Recordset.previousmoves to the previous row in the collection. Recordset.first IRecordset.Firstand Recordset.last do not depend on the direction and always move to row 0 and row (Recordset.getColumnCount - 1) respectively. It is good practice to set the direction and call Recordset.first IRecordset.Firstor Recordset.last before you start processing a recordset so that you know which row the Recordset object contains. You can use Recordset.first IRecordset.Firstand Recordset.isFirst IRecordset.IsFirstto control loops that move through recordsets. Accessing the value of a field In ReportEngine SDK you can access the values of a field directly. To access the fields of a record, use Recordset.getCellObject and provide the index of the column in which you are interested. Example: Accessing the values in a recordset The following code fragment prints the types of the columns and the contents of the results of a query contained in a data provider. Recordset rs = dp.getResult(0); // 0: assume query has one flow rs.first(); // Print the column types. They can be Integer, String, // or Date. for (int i = 0; i < rs.getColumnCount(); i++) { Class c = rs.getColumnType(i); StringBuffer sbt = new StringBuffer(); if ( c.equals(Integer.class) ) sbt.append("Integer"); if ( c.equals(String.class) ) sbt.append("String"); if ( c.equals(Date.class) ) sbt.append("Date"); sbt.append(";"); System.out.println(sbt.toString()); } ReportEngine Developer Guide 119
  • 120. 8 Working with Recordsets Anatomy of a recordset // Print the recordset contents: column names and data while (!rs.isLast()) { // column names StringBuffer sbn = new StringBuffer(); for (int j = 0; j < rs.getColumnCount(); j++) { sbn.append( rs.getColumnName(j).toString() ); sbn.append(";"); } System.out.println(sbn.toString()); // data for (int k= 0; k< rs.getColumnCount(); k++) { sbd.append( rs.getCellObject(k).toString() ); sbd.append(";"); } System.out.println(sbd.toString()); rs.next(); } This code fragment assumes that rs.getDirection equals FORWARD, and that the data provider (dp) has been populated. For more information on populating data providers see “Executing queries and retrieving the data” on page 100. 120 ReportEngine Developer Guide
  • 121. ReportEngine Developer Guide Business Objects Information Resources appendix
  • 122. A Business Objects Information Resources Documentation and information services Documentation and information services Business Objects offers a full documentation set covering its products and their deployment. Additional support and services are also available to help maximize the return on your business intelligence investment. The following sections detail where to get Business Objects documentation and how to use the resources at Business Objects to meet your needs for technical support, education, and consulting. Documentation You can find answers to your questions on how to install, configure, deploy, and use Business Objects products from the documentation. What’s in the documentation set? View or download the Business Objects Documentation Roadmap, available with the product documentation at http://www.businessobjects.com/support/. The Documentation Roadmap references all Business Objects guides and lets you see at a glance what information is available, from where, and in what format. Where is the documentation? You can access electronic documentation at any time from the product interface, the web, or from your product CD. Documentation from the products Online help and guides in Adobe PDF format are available from the product Help menus. Where only online help is provided, the online help file contains the entire contents of the PDF version of the guide. Documentation on the web The full electronic documentation set is available to customers on the web from support website at: http://www.businessobjects.com/support/. Documentation on the product CD Look in the docs directory of your product CD for versions of guides in Adobe PDF format. 122ReportEngine Developer Guide
  • 123. Business Objects Information Resources Customer support, consulting and training A Send us your feedback Do you have a suggestion on how we can improve our documentation? Is there something you particularly like or have found useful? Drop us a line, and we will do our best to ensure that your suggestion is included in the next release of our documentation: [email protected]. Note: If your issue concerns a Business Objects product and not the documentation, please contact our Customer Support experts. For information about Customer Support visit: http://www.businessobjects.com/ support. Customer support, consulting and training A global network of Business Objects technology experts provides customer support, education, and consulting to ensure maximum business intelligence benefit to your business. How can we support you? Business Objects offers customer support plans to best suit the size and requirements of your deployment. We operate customer support centers in the following countries: • USA • Australia • Canada • United Kingdom • Japan Online Customer Support The Business Objects Customer Support website contains information about Customer Support programs and services. It also has links to a wide range of technical information including knowledgebase articles, downloads, and support forums. http://www.businessobjects.com/support/ ReportEngine Developer Guide123
  • 124. A Business Objects Information Resources Useful addresses at a glance Looking for the best deployment solution for your company? Business Objects consultants can accompany you from the initial analysis stage to the delivery of your deployment project. Expertise is available in relational and multidimensional databases, in connectivities, database design tools, customized embedding technology, and more. For more information, contact your local sales office, or contact us at: http://www.businessobjects.com/services/consulting/ Looking for training options? From traditional classroom learning to targeted e-learning seminars, we can offer a training package to suit your learning needs and preferred learning style. Find more information on the Business Objects Education website: http://www.businessobjects.com/services/training Useful addresses at a glance Address Content Business Objects product Information about the full range of information Business Objects products. http://www.businessobjects.com Product documentation Business Objects product http://www.businessobjects.com/ documentation, including the support Business Objects Documentation Roadmap. Business Objects Documentation Send us feedback or questions mailbox about documentation. [email protected] Online Customer Support Information on Customer Support http://www.businessobjects.com/ programs, as well as links to support/ technical articles, downloads, and online forums. 124ReportEngine Developer Guide
  • 125. Business Objects Information Resources Useful addresses at a glance A Address Content Business Objects Consulting Information on how Business Services Objects can help maximize your http://www.businessobjects.com/ business intelligence investment. services/consulting/ Business Objects Education Information on Business Objects Services training options and modules. http://www.businessobjects.com/ services/training ReportEngine Developer Guide125
  • 126. A Business Objects Information Resources Useful addresses at a glance 126ReportEngine Developer Guide
  • 127. ReportEngine Developer Guide Logging with ReportEngine SDK Overview appendix
  • 128. B Logging with ReportEngine SDK Overview Logging Systems The are a number of ways to trace a ReportEngine SDK application including a Java package optimized for ReportEngine SDK. This appendix discusses how to use the various logging systems available. Logging Systems ReportEngine SDK provides logging systems. Logging in REBean In a Java programming environment you can use the following logging systems. • Jakarta log4j The Jakarta log4j system is part of the Jakarta project. See http://Jakarta.apache.org/log4j. • java.util.logging The java package java.util.logging is the logging system provided with JDK 1.4.1. See http://java.sun.com/j2se/1.4.1/docs/guide/util/logging/ index.html. • log4j.logger.com.businessobjects.rebean.ReportEngines The <BOProductName>Web Intelligence SDK package log4j.logger.com.businessobjects.rebean.ReportEngines allows you to integrate trace messages from your own application with those generated by the Business Objects servers and <BOProductName>Web Intelligence SDK. Trace Levels The following table shows the trace levels available through these trace systems. Trace Level Provides messages on DEBUG • helper classes • calls from REBean to the report engine server • JHSAL activity INFO • entry of each JSP • calls to the methods exposed by REBean 128 ReportEngine Developer Guide
  • 129. Logging with ReportEngine SDK Overview Activating logging by editing the configuration files B Trace Level Provides messages on WARN • potentially harmful situations ERROR • non-fatal exceptions FATAL • exceptions that stop the application executing Activating logging by editing the configuration files To activate logging you edit the webi.properties file. When you change this file you need to restart Tomcat for your changes to take effect. Using the default settings To activate the logging system using the default settings: 1. Add the following line to the webi.properties configuration file: Trace=1 2. Start, or restart Tomcat. This activates logging, by default the log4j logging system is selected, and the trace level is set to INFO. If there is no log4j.properties file, log4j.properties.todo is generated. Setting the trace level To activate the logging system, set the trace level and use the default logging system: • Add the following line to the webi.properties configuration file Trace=1, LEVEL Where LEVEL can be one of: DEBUG, INFO, WARN, ERROR, or FATAL This automatically selects the log4j logging system and sets the trace level to LEVEL. If there is no log4.properties file, log4.properties.todo is generated. ReportEngine Developer Guide 129
  • 130. B Logging with ReportEngine SDK Overview Activating logging by editing the configuration files Selecting the logging system To activate the logging system, and set the trace level and logging system: • Add the following lines to the webi.properties configuration file: Trace=1, LEVEL Adapter=log4j.logger.com.businessobjects.rebean.ReportEngines.s ystem Where: LEVEL can be one of: DEBUG, INFO, WARN, ERROR, or FATAL system is one of: Log4jLogger (log4j), or StandardLogger (debugdiag) This activates logging, selects the system logging system, and sets the trace level to LEVEL. If there is no configuration file for the logging system a .todo fileis generated. Activating logging while Tomcat is running To activate logging while Tomcat is running, put the following code in a file called traces.jsp and put the file in the same folder at the InfoView files. Then, to activate logging, open traces.jsp in a web browser and select the options (logging system, and trace level) you want. The following is an example of the traces.jsp file. <%@ taglib uri="/WEB-INF/wilog.tld" prefix="log" %> <jsp:useBean id="systems" class="java.util.Hashtable" scope="application" /> <% if (systems.isEmpty()) { systems.put("fake", "log4j.logger.com.businessobjects.rebean.ReportEngines.FakeLogger "); systems.put("debugdiag", "log4j.logger.com.businessobjects.rebean.ReportEngines.StandardLogger "); systems.put("log4j", "log4j.logger.com.businessobjects.rebean.ReportEngines.Log4jLogge r"); } %> <html> <head><title><BOProductName>Web Intelligence Logging System</title></head> <body> <% String uri = request.getRequestURI(); String sys = request.getParameter("sys"); 130 ReportEngine Developer Guide
  • 131. Logging with ReportEngine SDK Overview Activating logging by editing the configuration files B String level = request.getParameter("level"); String prop = request.getParameter("prop"); String adapter = request.getParameter("adapter"); if (sys == null) { out.println("<form method="POST" action="" + uri + "">"); out.println("<h4>Change the <BOProductName>Web Intelligence Logging System</ h4>"); out.println("<input name="sys" value="log4j" type="RADIO" CHECKED/>Enable Log4J, "); out.println(" properties <input value="Choose" name="prop" type="FILE" size="25"/> "); out.println("<br><input name="sys" value="debugdiag" type="RADIO"/>Enable Debugdiag "); out.println("<br><input name="sys" value="fake" type="RADIO"/>Disable Any "); out.println("<br><br>Level <input name="level" value="debug" type="RADIO"/>DEBUG "); out.println("<input name="level" value="info" type="RADIO" CHECKED/>INFO "); out.println("<input name="level" value="warn" type="RADIO"/>WARN "); out.println("<input name="level" value="error" type="RADIO"/>ERROR "); out.println("<input name="level" value="fatal" type="RADIO"/>FATAL "); out.println("<br><br><input type="SUBMIT" SELECTED value="GO" /><br><br>"); } else { %> <log:reinit adapter="<%=(String)systems.get(sys) %>" level="<%=level %>" lib="" prop="<%=prop %>"/> <% out.println("<h5><a href=""+ uri +""> Back</a></h5>"); } %> </body> </html> ReportEngine Developer Guide 131
  • 132. B Logging with ReportEngine SDK Overview Configuring the Jakarta log4j logging system Configuring the Jakarta log4j logging system The Jakarta log4j logging system uses a configuration file called log4j.properties. This file must be present in the classes directory of the web application, for example, webappswijspWEB-INFclasses. If the configuration file is not present log4j.properties.todo is created in the bin folder of the application server, however you should move this file to the classes directory for your web application (and remove the “todo” from the file name) so you can have one configuration file for each application. This logging system is delivered with the BusinessObjects platform. It is installed in $INSTALLDIRclasses. See also http://jakarta.apache.org/log4j/ docs/index.html for further explanation of the configuration options for this tool. Setting the trace level You set the trace level in log4j.properties. The possible levels are DEBUG, INFO, WARN, ERROR, and FATAL. The trace level setting in log4j.properties takes precedence over the trace level setting in webi.properties. Setting the trace mechanism You set the trace output mechanism in log4j.properties. Possible output mechanisms are: file, console (stdout), or a socket. Setting the trace output You can set the output format in log4j.properties. The following table shows the formatting tokens you can use. This token Adds this to the trace %d date %t thread %p trace level %c the name of the logger. %r time since the trace system was initialized 132 ReportEngine Developer Guide
  • 133. Logging with ReportEngine SDK Overview Configuring the Jakarta log4j logging system B This token Adds this to the trace %x thread content, for example, the session ID %m the message See Specifying the trace level for individual classes You can specify the trace level for a package or a class. For example, if the root trace level is DEBUG, but you do not want to see the trace for the REBean package, add the line log4j.logger.com.businessobjects.rebean.wi=WARN to log4j.properties. Similarly, you can exclude the trace for the ReportEngine interface with log4j.logger.com.businessobjects.rebean.wi.ReportEngine=WARN log4j.properties Example log4j.properties The following lists the contents of log4j.properties. In this example, the root trace level is set to DEBUG, and traces from the Report interface are excluded. log4j.rootCategory=DEBUG, A1 # Console output log4j.appender.A1=org.apache.log4j.ConsoleAppender # File output #log4j.appender.A1=org.apache.log4j.FileAppender #log4j.appender.A1.File=infoview.log # Socket output #log4j.appender.A1=org.apache.log4j.net.SocketAppender #log4j.appender.A1.RemoteHost=bergame #log4j.appender.A1.Port=8887 # Format log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern= %-4r %-5p %c{10} (%x) - %mn ## to filter REBean logging, uncomment #log4j.logger.com.businessobjects.rebean.wi=WARN #log4j.logger.com.businessobjects.rebean.wi.AxisType=WARN #log4j.logger.com.businessobjects.rebean.wi.BarType=WARN #log4j.logger.com.businessobjects.rebean.wi.HTMLView=WARN log4j.logger.com.businessobjects.rebean.wi.Report=WARN ## to filter REPORT ENGINE SERVLET, uncomment #log4j.logger.com.businessobjects.cdzlet=WARN ## to filter INFOVIEW JSP logging, uncomment #log4j.logger.scripts=WARN #log4j.logger.viewers=WARN ReportEngine Developer Guide 133
  • 134. B Logging with ReportEngine SDK Overview Configuring the Jakarta log4j logging system 134 ReportEngine Developer Guide
  • 135. ReportEngine Developer Guide Configuring ReportEngine using webi.properties appendix
  • 136. C Configuring ReportEngine using webi.properties Configuring ReportEngine SDK web applications Configuring ReportEngine SDK web applications You can configure individual ReportEngine SDK or viewer applications such as InfoView to improve their efficiency on application server on which they have been deployed. The purpose of this chapter is to tell you how to improve BusinessObjects Enterprise application efficiency. What is webi.properties? Each ReportEngine web application can have a webi.properties file. For BusinessObjects Enterprise XI R2 applications this file is optional. The webi.properties file is located in the WEB-INFclasses subdirectory of the <BOProductName>Web Intelligence application. For example, if you have deployed InfoView on a Tomcat application server the webi.properties file would be found in the following directory. <TOMCAT_HOME>webappsbusinessobjectsenterprise115desktopl aunchWEB-INFclasseswebi.properties How to update webi.properties The webi.properties file is a plain text file containing variables used to tune the individual <BOProductName>Web Intelligence web application. The variables defined in the webi.properties file are taken in to account when your <BOProductName>Web Intelligence server starts up. To change variable settings in webi.properties, Business Objects recommends that you do the following: 1. Navigate to the classes subdirectory in your <BOProductName>Web Intelligence web application, 2. that is to say <MyWebIntelligenceApp>/WEB-INF/classes. 3. Make a copy of the webi.properties file. This copy is to stay in the <MyWebIntelligenceApp>/WEB-INF/classes subdirectory as a backup. 4. Copy webi.properties to a temporary directory. 5. Edit webi.properties using your favorite text editor, set the value of the variables as required. 6. Replace <MyWebIntelligenceApp>/WEB-INF/classes/webi.properties with your updated version. 7. Restart Business Objects XI R2. 136 ReportEngine Developer Guide
  • 137. Configuring ReportEngine using webi.properties Configuring ReportEngine SDK web applications C A comprehensive list of variables to update can be found in the next section. Configuration Options The following variables can be used to tune web applications: Variable Name Description Default Value TEMP_DIR The directory where temporary same as the Java files generated by temporary directory <BOProductName>Web Intelligence are stored. XML_TRANSFORMER The parser used for XML org.apache.xalan.proce translation. ssor.TransformerFactor yImpl CHUNK_SIZE The size of binary or character In bytes: 60000 object sent between the client In kilobytes: 60k browser and the <BOProductName>Web Intelligence server. FAILOVER_SIZE The size of binary or character 10 object sent between the client browser and the <BOProductName>Web Intelligence server. MAX_HEAP_SIZE Prevent the web application 750m from consuming all the heap of the Java Virtual Machine. Trace Set the application to trace Commented out. internal Uncomment and set to <BOProductName>Web 1 to activate. Intelligence calls. STORAGE_TOKEN_STACK_SIZE Sets the limit of undo actions 10 possible for DocumentInstance objects. Set to 0 for no limit for file persistence and token are storage until memory reaches FAILOVER_SIZE. Note: For application servers running with the Java Virtual Machine 1.4 and above, runtime.maxMemory is used to set the MAX_MEMORY variable internally. This ensures that your <BOProductName>Web Intelligence application does not consume the Java Virtual Machine heap. ReportEngine Developer Guide 137
  • 138. C Configuring ReportEngine using webi.properties Configuring ReportEngine SDK web applications In order to optimize resources on the Web Intelligence server, the STORAGE_TOKEN_STACK_SIZE parameter is used to limit the size of the size of stack by limiting document serialization. For the end user, this means the number of undo actions that can be done. The default value of STORAGE_TOKEN_STACK_SIZE is 10, the same as the FAILOVER_SIZE variable. • If STORAGE_TOKEN_STACK_SIZE =0 their is no limit for file persistence and token are stored into memory until reaching FAILOVER_SIZE. If failover happens, the maximum number of DocumentInstance objects in the storage manager will fail over to a backup application server. • If STORAGE_TOKEN_STACK_SIZE <= FAILOVER_SIZE their is no file persistence. • If STORAGE_TOKEN_STACK_SIZE > FAILOVER_SIZE up to (STORAGE_TOKEN_STACK_SIZE minus FAILOVER_SIZE) instances are stored in file system. The memory footprint for a document state that is higher than the value of STORAGE_TOKEN_STACK_SIZE in the stack is deleted. If a client tries to use an out of stack token to access a document state the ReportEngine will throw an exception. You can retrieve the stack size programmatically and validate storage tokens using: int ReportEngine.getStorageTokenStackSize() boolean ReportEngine.IsStorageTokenValide(String storageToken) 138 ReportEngine Developer Guide
  • 139. Index A training services 124, 125 accessing Business Objects Enterprise sessions user profiles 25 creating 46 actions storage tokens 38 drilling 83 Adobe Acrobat 34 C see also PDF calculations 111 alignment 114 categories 38–46 anchors category details 45 vertical and horizontal 106 category moving 45 applets creating 44 Java Report Panel 92 deleting 44 area graph 112 getting details 45 attachments 106 renaming 44 authentication user rights, and 39 passwords 19 categorizing documents 38 axis (block) 108 cells creating 114 B CESDK background 114 creating a ISessionMgr object 18 bar graph 112 referencing 17 batched lists of values 72 CESDK object blocks creating 20 cells 114 chunking creating 108 lists of values 72 cross tables 112 classes forms 112 referencing 17 graphs 112 closing repeating 115 ReportEngine object 32 representing 111 ReportEngine SDK sessions 21 borders 114 colors 114 breaks 111 conditions 98 browsers prompts 99 storage tokens 38 structure 99 building data providers 89 consultants, Business Objects 124 Business Objects contexts consulting services 124, 125 opening documents 46 support services 123 creating Developing with Web Intelligence Report Engine SDK 139
  • 140. blocks 108 categories 44 cells 114 see also reports document structure 102 building data providers 89 ISessionMgr object 18 categories 38 sections 107 changing names 48 cross tables 112 creating 102 custom 57 dictionaries 91 customer support 123 displaying document lists 47 D drillable 79 drilling 77 data providers 89–100 format 80 building 91 formatting reports 101 data sources 90 opening 13, 46 executing queries 100 prompts 64 data sources 90 properties 56 decoration refreshing 13, 64, 73 pages 114 document lists 47 deleting report maps 74 categories 44 saving 48 Developer Suite sending 50 migration 11 structure 102 dimensions types 34 drilling 80, 83 Web Intelligence and Desktop Intelligence scope of analysis, and 87 format 30 displaying drill bars 81, 87 document lists 47 drill hierarchies 80 report maps 74 drill mode 79, 80 document structure 102 entering and leaving 81 attachments 106 drill options 82 blocks 108 drill path 79, 79, 81 positioning elements 106 setting 79, 81, 83 report expressions 107 drilling 77–88 sections 107 actions 83 documentation dimensions 80 feedback on 123 drill bars 81 on product CD 122 drill hierarchies 81 on the web 122 drill mode 79, 85 roadmap 122 drill path 79, 81, 83 documents 48 filtering 87 Developing with Web Intelligence Report Engine SDK 140
  • 141. generating HTML 80, 85 hierarchies 80, 83 hyperlinks 79, 81, 82 saving 48 images 85 formatting Java script files 85 layout 115 overview 78 page query string parameters 79, 79, 79, 81, 82 decoration 114 reports 80–88 paper size 115 scope of analysis 80, 87, 97 reports 101 setting parameters 83 forms 112 slice 83 free cells 114 snapshots 88 transparent drill out of cube 80 G getHTMLView 36 E drilling 80, 85 editing getting started 11, 16 blocks 108 graphs 112 cells 114 data providers 89 H document structure 102 handling queries 96 context prompts 74 sections 107 exceptions 29 education. See training out of scope drill requests 87 Enterprise Mode authentication 20 prompts 64 errors 29 hello world example 16 exceptions 29 hierarchies executing queries 100 drilling 81, 83 hyperlinks F generating for drilling 79, 80, 81, 82, 85 feedback, on documentation 123 fields I recordsets 118 images filtering drilling 85 drill bars 81, 87 importing code in JSP 24 drill-by and drill-up actions 84 include directive queries 98 in JSP 24 query conditions 88 information resources 122 fonts 114 InfoView foreground 114 example workflows 13 formats Developing with Web Intelligence Report Engine SDK 141
  • 142. user profiles 24 Introduction 9 J N Java Report Panel 91 navigating launching 92 reports 74 Java Report Panel seeJava Report Panel nested prompts 72 Java script files NT Challenge Mode authentication 20 drilling 85 java.util.Properties 26, 56 O JSP objects importing code 24 query results 97 reading a user profile 26 Online Customer Support 123 opening L documents 13, 46 landscape layout 115 out of scope drills 80, 87, 97 layout 115 line graph 112 P listing packages documents 47 java.util.Properties 56 lists of values 68–74 page batched 72 layout 115 chunking 72 page decoration 114 constrained prompts, and 69 paper size 115 displaying 68 passwords 19 multicolumn 70 storage token 36 prompts in (nested) 72 PDF refreshing 73 displaying reports 60 log in and log out 16 output format 63 logins 19 .pdf see PDF LOV see lists of values pie chart 113 portrait layout 115 M prompts 64–74 managing conditions 99 documents 34 constrained 69 Microsoft Excel context 64, 74 displaying reports 60 drilling 87 output format 63 entering values 70, 71 migration 11, 48 lists of values 68 multivalued prompts 69 multicolumn lists of values 70 Developing with Web Intelligence Report Engine SDK 142
  • 143. multivalued 69 nested 72 storage tokens 36 report maps 74 properties 57 snapshots, and 88 documents 56 Report Panel see Java Report Panel ReportEngine object Q closing 32 ReportEngine SDK queries 90 creating a ISessionMgr object 18 editing 96 exceptions 29 executing 100 features 34 query conditions 88, 98 hello world 16 query strings login 19 drilling 79, 79, 79, 81, 81, 82 migration 11 packages 10 R referencing classes 17 radar & scatter graph 113 ReportEngine sessions REBean closing 21 creating a ReportEngine object 30 reports exceptions 29 drilling 77, 80, 85 features 10 filters 87 formatting reports 101 formatting 101–115 recordsets 117–120 report maps 74 changing records 119 viewing all the reports in a document 61 fields 118 repository referencing opening documents 46 CESDK 17 sending documents 51 ReportEngine SDK classes 17 RESDK refreshing building data providers 89 document lists 47 document properties 56 documents 13, 64, 73 resolving universe contexts 74 lists of values 73 resources 122 renaming categories 44 result objects 97 RENET running queries 100 exceptions 29 features 10 S report expressions 107, 108 save to corporate see publishing adding to axes 110 saving documents 48 breaks 111 scope of analysis 78, 80, 97 calculations 111 handling manually 87 sorting 111 Developing with Web Intelligence Report Engine SDK 143
  • 144. scripts drilling 85 sections transparent drill out of cube 80 creating 107 traversing sending documents 50–53 categories 41 session ID report maps 74 cookies, and 20 triggers sessions generating storage tokens 36 closing 21 creating 20, 46 U setting universes 90 drill actions 83 resolving contexts 74 drill parameters 83 user names 19 user profiles 27 user profiles 24, 47 settings in user profiles 24 accessing 25 slice drill action 83 adding to 28 snapshots 88 setting 27 SQL user rights 47 executing 100 categories, for 39 storage tokens transparent drill out of cube 80 advantages 38 user sessions see Business Objects Enterprise browser navigation 38 sessions generation triggers 36 life cycle 35 opening documents 46 V viewing reports 61 values support prompts 68 customer 123 viewing locations 123 binary view 61 technical 123 reports 59–75 web site 123 W T web tables customer support 123 cross tables 112 getting documentation via 122 vertical and horizontal 111 useful addresses 124 technical support 123 web sites temporary files support 123 storage tokens 35 training 124 training, on Business Objects products 124 Developing with Web Intelligence Report Engine SDK 144
  • 145. Index Developing with Web Intelligence Report Engine SDK 145
  • 146. Index 146 Developing with Web Intelligence Report Engine SDK