Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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. 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.
Patents
Contents
Chapter 1 Chapter 2 Introduction Introduction to WebIntelligence SDK 7 9 Packages for customizing WebIntelligence . . . . . . . . . . . . . . . . . . . . . . . . 10 Migrating to BusinessObjects XI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 A typical Web Intelligence SDK application . . . . . . . . . . . . . . . . . . . . . . . . 11 Chapter 3 Application Essentials 15
Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 BusinessObjects Enterprise sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Implementing Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 User preferences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Exception handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Reporting essentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 Chapter 4 Document Management 33
Document types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Document state: storage tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 Organizing documents in categories and folders . . . . . . . . . . . . . . . . . . . . 39 Working with documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Document properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Chapter 5 Viewing Web Intelligence Reports 61
Viewing reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Handling prompts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Displaying a report map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 Chapter 6 Drilling in Web Intelligence Reports 79
Chapter 7
91
Data providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Building a data provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Executing queries and retrieving the data . . . . . . . . . . . . . . . . . . . . . . . . 102 Chapter 8 Formatting Reports 103
Creating and editing the document structure . . . . . . . . . . . . . . . . . . . . . . 104 Creating and editing cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116 Page layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Appendix A Working with Recordsets 119
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 Customer support, consulting and training . . . . . . . . . . . . . . . . . . . . . . . . 125 Useful addresses at a glance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Examples
Referencing BusinessObjects Enterprise SDK 17 Instantiating the ISessionMgr class 18 HTML form for gathering a users login information 19 Establishing a session 20 Printing a users preferences 26 Setting a users report panel preference to Java 28 Adding a new preference to a users profile 29 Importing the REBean package 31 Instantiating a ReportEngine object 31 Storage token life cycle 36 how to check that a user has the right to create categories 40 Recursively traversing the category tree 41 Retrieve a users Inbox and Favorites folder IDs 43 Creating a new folder or category 45 Moving and renaming categories or folders 46 Retrieve the properties for a category 46 Displaying a document list 49 Save a Web Intelligence document 50 Scheduling a document 51 Retrieve the list of groups to which a user belongs 52 Sending a document to folders and categories 53 Send a document to the inbox of groups of users 55 Getting the name of a Web Intelligence document using REBean 58 Adding a property to a Web Intelligence document 58 Viewing all the reports in a Web Intelligence document 63 Viewing a report in a Web Intelligence document 63 Viewing a report in Microsoft Excel format 64 Handling a single, simple prompt 66 Dynamically creating input names 68
Examples
Handling many, simple prompts 68 Displaying a simple list of values 70 Handling multivalued prompts 72 Handling multicolumn lists of values 72 Order of filling a hierarchy of nested prompts 74 Handling nested prompts 74 Refreshing a list of values containing nested prompts 75 Traversing the report map for a Web Intelligence document 77 Defining the query string parameters 84 Setting the drill path 86 Displaying the drilled report 88 Launching the Web Intelligence Java Report Panel 96 Building a data provider 98 Creating a simple condition 100 Structure of a complex condition 101 Including a prompt in a condition 101 Creating a blank document 104 Creating a document structure 107 Creating an attachment 109 Editing the sections of a report 109 Building a report: adding expressions to axes 112 Accessing the values in a recordset 121
Introduction
chapter
chapter
1
Overview
WebIntelligence 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 WebIntelligence SDK and the workflows a typical application needs to implement.
Web Intelligence SDK You use Web Intelligence SDK to customize Web Intelligence. BusinessObjects Enterprise SDK The "platform package," provides platform functions of the Business Objects servers, and document scheduling. Web Intelligence Report Engine SDK This package plugs into Business Objects Enterprise SDK. It provides the functions of the Web Intelligence Report Engine.
BusinessObjects Enterprise SDK Crystal Enterprise Documents View Refresh Analyze Platform functions Manage sessions and users Manage documents and categories List universes, documents Schedule
Web Intelligence SDK Web Intelligence documents View Refresh Analyze Create Format Metadata (universe) Explore
BusinessObjects Enterprise SDK is called the platform package because it exposes the platform functions of the Business Objects servers. Web Intelligence Report Engine exposes the functions of the Web Intelligence Report Engine.
1
Migrating to BusinessObjects XI
If you already have a business intelligence solution based on previous versions of Developer Suite you might need to migrate your solution. Migration affects the following areas:
referencing components of the Business Objects 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 6 Customized Applications to BusinessObjects XI guide.
Application essentials
Every application that uses Web Intelligence SDK needs to perform a few common tasks such as importing the appropriate Java packages, and creating and managing the users BusinessObjects Enterprise session (login). While it is not absolutely necessary, 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 25.
Document management
Document management features include the ability to list the documents that the current user can view, and, depending on the users rights, allowing the user to browse and manage categories and folders used to organize the documents.
1
Document management can also include features such as saving, and scheduling documents.
Viewing reports
An application that provides a feature for viewing reports can display reports using the default HTML format. It is easy to extend this to handle reports that contain prompts, and to provide drilling functions. These extended functions have to be handled when a document is refreshed. How you provide these viewing features depends on the type of document. The report-viewing part of the application should include routines for viewing reports in the following document types:
Web Intelligence (*.wid) Crystal Reports documents other document types, for example Adobe Acrobat, Microsoft Excel or XML format.
Formatting documents
Formatting documents involves creating and positioning the elements of a report (blocks, sections, and cells) in the appropriate document structure. Using Web Intelligence Report Engine SDK you can build reports from scratch. Web Intelligence Report Engine SDK also includes classes for controlling the page decoration (fonts, colors, headers, and footers) and page layout of a report.
Example workflows
InfoView is implemented using BusinessObjects Enterprise SDK and Web Intelligence SDK. The Web Intelligence InfoView viewer interface has three zones:
the document tool bar, which shows the users position in the document
1
the report map, which shows the structure of a report the rendering area, which is where reports are displayed The pages manage these zones in sequence. First the document is opened, the prompts are filled and the position is set, then the report map is populated and finally the report is rendered and displayed.
get the report map get the report in the requested format
1
Refresh document workflow
The following diagram shows the workflow for refreshing a document.
Client pages Web Intelligence SDK
refresh the report refresh check for prompts fill prompts until there are none left unfilled set the position
get the report map get the report in the requested format
Application Essentials
chapter
2
Overview
Before providing viewing, reporting, and editing functions Web Intelligence 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 Web Intelligence must use.
Hello World
The simplest application you can write with Web Intelligence SDK is one that creates a BusinessObjects Enterprise session, that is, provides log in and log out functions. You can use this as a basis for building much more sophisticated applications that provide, for example, functions to list, view and create documents, and publish them in hierarchical categories.
open a session
close session
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
2
the user clicks the logout link, the application closes the users 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 22 for code that implements this application.
You need to include this line in every page that uses BusinessObjects Enterprise SDK.
2
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 Web Intelligence SDK.
2.
name password the Central Management System (CMS) the user wishes to log into authentication type (Enterprise or LDAP)
2
Example: HTML form for gathering a users 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> </select> </TD> </TR> <TR> <TD><input id=submit1 name=submit1 type=submit value="Login"></TD> </TR></TABLE> </FORM>
Note: 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:
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. For more information on authentication in Windows, see the BusinessObjects Enterprise XI Administrators Guide.
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 using J2EE.
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){ ; }
2
Closing a session is important:
It frees the resources held by the users 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.
The users JSP page will not have access to objects such as IInfoStore stored in the users application server session variables. Session objects created on the BusinessObjects Enterprise server will not be liberated correctly. This will degrade server performance.
2
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.
index.jsp Name = janderson Pass = ******** login.jsp
logout.jsp
home.html
In this implementation index.jsp displays a form which collects the users 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>
2
<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> </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" %> <%@ page import="com.businessobjects.rebean.wi.*" %> <% String CMS = request.getParameter("CMS"); String userID = request.getParameter("Name"); String password = request.getParameter("pass"); String auth = request.getParameter("auth"); if if if if ( ( ( ( CMS == null) CMS = ""; userID == null) userID = ""; password == null) password = ""; auth == null) auth = "";
2
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");
%>
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; }
%>
2
User preferences
Users can set their InfoView and Web Intelligence Report Engine viewing options using the Preferences page. When designing a Web Intelligence 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 HTML Report Panel.
webi_panel
java
html
DOCUMENT_WIStartNewDrill
duplicate existing
2
Variable Name Possible Values Meaning Prompt if drill requires additional data. (default) Do not prompt if Drill requires additional data. Synchronize Drill on report blocks. (default) Do not Synchronize Drill on report blocks. Show the Drill bar. Hide the Drill bar. (default) DOCUMENT_WIPromptDrillOutScope N
Y DOCUMENT_WISyncDrillBlocks N
Y DOCUMENT_WIDrillBar N Y
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 users profile on page 29.
Example: Printing a users preferences The following JSP code functions show how to retrieve a users Web Intelligence preferences and print them to an HTML response stream.
<%! //Return a string containing a users 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();
2
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) webiPrefs.put(st2.nextToken(), st2.nextToken()); } return webiPrefs; } %>
The following code fragment shows how to use the functions declared above to print a users Web Intelligence 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>"); } } %>
2
Setting an option in a user profile
To set an option: 1. 2. 3. 4. Get a users preferences. Update a standard option in the Map continuing the user preferences. Convert the Map to a String. Update the user profile with IInfoStore.commit.
Example: Setting a users report panel preference to Java The following JSP code functions enables a users profile to be updated to use the Java Report Panel.
<%! //Update the users 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){ 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 users Web Intelligence preferences.
<% //Update a users Web Intelligence preferences
2
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 users preferences on page 26
Example: Adding a new preference to a users profile The following JSP 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 users preferences on page 26.
2
Exception handling
BusinessObjects Enterprise SDK generates exceptions of the type SDKException. Depending on the cause of the exception, Web Intelligence Report Engine SDK generates exceptions of the following type:
Exceptions and their descriptions are listed in the online reference documentation. Note: All exception classes (above) are subclasses of the REException class.
2
Reporting essentials
All applications that view, edit or format Web Intelligence documents need to:
reference Web Intelligence Report Engine SDK initialize the ReportEngine object This links the report engine and platform packages. close the ReportEngine object
Note: You use Web Intelligence Report Engine to view, edit and format Web Intelligence documents.
Note: You need to include this line in every JSP page that uses REBean classes.
Note: Business Objects recommends that this object is created when the user logs in to the BusinessObjects Enterprise server.
2
Note: The locale used by the ReportEngine must match the locale used by the client browser.
The ReportEngine object is recuperated in further JSP scripts using the following code.
ReportEngine webiRepEngine = (ReportEngine) session.getAttribute("ReportEngine");
You need to include this on every JSP page that uses the ReportEngine object. Since the scope is set to session, there can be several ReportEngine objects existing at the same time.
Document Management
chapter
3
Overview
Two key parts of a typical Web Intelligence SDK application are listing the documents that the user can view, and depending on the users 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 Crystal Reports documents third-party documents, for example Microsoft Excel (.xls), and Adobe Acrobat (.pdf) files
Using Web Intelligence SDK you can do everything Web Intelligence users can do with Web Intelligence documents:
view as HTML view as PDF view as Excel view as XML refresh create categorize delete drill save schedule send
3
Document state: storage tokens
Storage tokens are a way to save and, later, reconstruct the state of a document.
when you open a document when the microcube contents are modified or formatted
When you open a document, Web Intelligence creates a DocumentInstance object that has a storage token. Web Intelligence also creates some temporary files that contain information about the documents current state.
Temporary files Executing file doc object
open doc
StorageToken = r0
r0
view1
As the document changes state through the execution of JSP files, the storage token changes too, and more temporary files, representing the documents states, are created. Web Intelligence generates a new storage token and corresponding set of temporary files at the following triggers: User interface Triggers refreshing the document drilling creating and editing a document applying new formats running a query SDK Triggers calling DocumentInstance.getView modifying the DrillPath object calling DataProvider.getResult calling DataProvider.runQuery opening a document
3
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 to temporary files 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.
3
e.
Temporary files 1
Executing files
docInstance object
open docInstance
StorageToken = r0
r0
GIF
run query
StorageToken = r0-s0
r0-s0
view1
r0-s0
2
GIF GIF
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
3
Table 3-1 Storage token life cycle
3
Organizing documents in categories and folders
In Web Intelligence, categories and folders are used to classify documents in the central management system. Documents that are organized in the hierarchical category and folder structures are easier to find for users who need to search for them. In Web Intelligence, a user can save a document to selected categories and folders. A document can be assigned to one or more public or personal categories.
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
3
Folder and category-related settings in a Web Intelligence users rights InfoView Advanced Right User can move and copy objects, create shortcuts and add object to the favorites folder. Can use InfoView simple search Can use InfoView advanced search User has a favorites folder User can create categories Variable Name CeInfoViewRightID.ORGANIZE User can change preferences CeInfoViewRightID.PREFERENCE
CeInfoViewRightID.SIMPLESEARCH CeInfoViewRightID.ADVANCEDSEARCH
Can use InfoView filter feature CeInfoViewRightID.FILTER CeInfoViewRightID.FAVORITES CeInfoViewRightID.CREATECATEGORIES User can view inbox contents CeInfoViewRightID.VIEWINBOX User can assign categories to CeInfoViewRightID.ASSIGNCATEGORIES users or groups User can send documents to users and groups User can create dashboards User can create folders CeInfoViewRightID.SENDDOCUMENTS CeInfoViewRightID.CREATEDASHBOARDS CeInfoViewRightID.CREATEFOLDERS
A list of a users rights over an object in the InfoStore can be recovered by retrieving the users 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){
3
ISecurityInfo secInfo = infoView.getSecurityInfo(); if (secInfo.checkCustomRight( CeInfoViewRightID.CREATECATEGORIES, infoView.getKind())) { ... }
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 users Web Intelligence rights the query string would include CeKind.WEBINTELLIGENCE in the place of CeKind.INFOVIEW.
3
} //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 + 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; } %> }catch (SDKException sdke){ return FolderID;} return FolderID;
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 49.
3
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 users personal directories. Once the root directory ID is retrieved, you can list and navigate the contents in the same way corporate folders are navigated. Example: Retrieve a users Inbox and Favorites folder IDs The following example shows JSP functions that use BusinessObjects Enterprise SDK to recover the ID of the parent folder for a users 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 users Inbox int getInboxFolderId(IInfoStore iStore, int userID){ return getFolderId(iStore,userID,(String)CeKind.INBOX); } //Retrieve the ID of a users 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 users Inbox. See Displaying a document list on page 49 for the definition of getList. <% IEnterpriseSession enterpriseSession; IInfoObjects docList = null; enterpriseSession = (IEnterpriseSession) session.getAttribute("EnterpriseSession"); IInfoStore iStore = (IInfoStore)
3
session.getAttribute("InfoStore"); int userID = enterpriseSession.getUserInfo().getUserID(); int inboxID = getInboxFolderId(iStore, userID); docList = getList(iStore, inboxID, (String)CeKind.WEBI ); %>
Note: See Displaying a document list on page 49 for the definition of getList.
3
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 JSP 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); %>
3
Moving and renaming categories and folders
You can move categories and folders from one parent to another with:
IInfoObject.setParentID myIInfoObject.setTitle
You can rename categories and folders using: 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;
} %>
3
<%! IInfoObject getProps(IInfoStore iStore, int ID){ 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 InfoStore 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()); %>
3
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 users session on page 20) you can open a document on behalf of the user. In general, to open a document you: 1. 2. Establish a BusinessObjects Enterprise session for the user. 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 documents ID. 3. Open the document using the ReportEngine.openDocument method for Web Intelligence documents.
3
Note: IInfoObject is the base BusinessObjects Enterprise type. An IInfoObject can be used to store any type of object in the central management system.
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); ...
%>
3
Saving documents
To save a document use DocumentInstance.save and DocumentInstance.saveAs. Example: Save a Web Intelligence 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 = myReportEngine.openDocument(docToken); docToSave.save(); %>
Note: Go to Sending documents to users, groups and categories on page 52 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 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. 2. 3. 4. Query the IInfoStore to get the IInfoObject representing the specific document. Get the document IInfoObjects ISchedulingInfo object. Set the type and frequency of the scheduling. 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.
3
Example: Scheduling a document The following JSP 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; 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); %>
3
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 users permissions. Action To these groups and/or Depending on the current users users settings for these permissions groups and categories to DocumentInstance.saveAs which the current user has access groups to which the IInfoStore.schedule current user belongs, 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 objects settings. This means that 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.
3
Procedure for sending a document to folders and categories
BusinessObjects Enterprise documents are organized by folder and categories. 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. 2. Display the name of the document to be sent. Retrieve the IDs of:
3. 4. 1. 2.
corporate folders and categories the root directory of the current user's personal categories
Get and display the list of folders and categories to which the current user can send documents. Pass this information to the second JSP page. Get the details entered by the user. Call DocumentInstance.saveAs.
Example: Sending a document to folders and categories The following JSP code fragments are used to save a document in specific folders and categories. saveDocAs.jsp is called by a JSP 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, saveDoc.jsp is executed and the document is sent according to the users selections. Note: The function getCatOrFoldersRadioButtons and webiPrefsToMap is declared in the example Recursively traversing the category tree on page 41. In saveDocAs.jsp
<%! //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)
3
} %> FolderID=((IInfoObject)folders.get(0)).getParentID(); }catch (SDKException sdke){ return FolderID;} return FolderID;
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 IDs of the corportate and personal category chosen by the active user in which to store the document.
3
1. 2. 3. 4. 5. 6. 7. 8. 9. Query the IInfoStore to get the IInfoObject representing the document to be sent. Get the documents ISchedulingInfo object. Retrieve the Inbox plugin used to send a document to users. Set the destination and send options for the Inbox plugin. Create a Set containing the IDs of users or groups to which the current user can send the document. Allow the user to choose the users/groups to send the document to. Add the set of IDs created in the previous step to the Inbox plugin options. Set the type and frequency of the scheduling. 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 InfoStore. The returned IInfoObjects object contains the IDs 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){
3
} 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; Set IDs = new HashSet(); 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();
3
destOptions.setDestinationOption( IManagedOptions.CeDestinationOption.ceInbox); destOptions.setSendOption( IManagedOptions.CeManagedSendOption.ceCopy); Set IDs = getUserGroupIDs(iStore); Set destinationIDs = destOptions.getDestinations(); destinationIDs.clear(); destinationIDs.addAll(IDs); destination.setFromPlugin(inboxPlugin); schedulingInfo.setIntervalDays(7); schedulingInfo.setType(CeScheduleType.DAILY); iStore.schedule(documentList); }
} %>
3
Document properties
Some of the important characteristics of Web Intelligence documents are stored as part of the document. You can access these properties using the DocumentInstance object. For REBean the process for accessing a property of a Web Intelligence document is: 1. 2. 3. Get the collection of properties. Set/Read the property. Commit the change, if any, to the collection of properties.
Example: Getting the name of a Web Intelligence document using REBean The following Java 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);
3
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 these properties that you have set in the new collection take precedence over those in the one attached to the DocumentInstance.
Property persistence
You do not need to save the document for the properties you set to persist after the document is closed.
chapter
4
Overview
Web Intelligence SDK contains classes and methods for viewing documents. Applications for viewing Web Intelligence documents (*.wid) handle prompts and provide report and section navigation with a report map. This chapter discusses how to use REBean to view Web Intelligence reports. See also and Formatting Reports on page 103.
Viewing reports
You can view complete documents (all reports) in either Adobe Acrobat (PDF) or Microsoft Excel (XLS) format. You can view individual reports or report pages (?) in XML and HTML format as well as PDF and XLS. The following table shows viewing possibilities. Type Document Report Report Page XLS X X X PDF X X X X X X X XML HTML
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 HTML format, you need to get views of each report in HTML and display those separately. See Viewing an individual report in HTML on page 63. 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.
4
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.msexcel. 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 DocumentInstance doc = repEng.openDocument(docID); //get the report contents as a binary stream in PDF format BinaryView docBinaryView = (BinaryView) doc.getView(OutputFormatType.PDF); byte[] abyBinaryContent = docBinaryView.getContent(); //output the binary stream via the response object response.setContentType("application/pdf"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(abyBinaryContent); %>
Note: This example starts Adobe Acrobat Reader and displays the document using this application. Depending on the users browser configuration, the document will appear in either in the browser or in a separate application window.
Example: Viewing a report in a Web Intelligence document The following JSP code fragment displays a selected report in a Web Intelligence document in HTML format.
<% // Get query string parameters and initialize variables
4
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.openDocument(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); //get a view of the report in HTML format HTMLView docHtmlView = null; docHtmlView = (HTMLView)rep.getView(OutputFormatType.HTML); String sHTMLView = docHtmlView.getContent(); %> <%=sHTMLView%>
4
response.setContentType("application/vnd.ms-excel"); ServletOutputStream outputStream = response.getOutputStream(); outputStream.write(abyBinaryContent);
4
Handling prompts
Prompts are a way to get supplementary information before executing a query. Prompts can resolve filters in the query, ask for passwords on protected documents, and resolve context clashes in universes (do you want the customers details to come from the Sales table, or the Customer Service table?). In Web Intelligence 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 documents. For Web Intelligence documents you use the REBean packages to handle prompts. 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 76.
4
%> <formname="PromptsForm" action="refresh.jsp?Token=<%=doc.getStorageToken()%>" method="post"> <input name="PromptInput" type="text"/> <input name="Submit" type="submit" value="OK" /> </form> <%
} response.sendRedirect("view.jsp? Token="+doc.getStorageToken());
Note: This example does not show how to set 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. 2. 3. Get the DocumentInstance object for the document. Get the collection of prompts for the document. Try to enter values for the prompt 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 JSP is executed. The forms action parameter is set to refresh.jsp so that this JSP is executed when the user clicks the submit (OK) button.
4
Documents with many simple prompts
To handle many simple prompts you can extend the workflow for the single simple prompts (page 66) with a form into which the user can enter values for all the prompts, and a script that handles these values. 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 JSP 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 document. (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.
<% //get the document and its prompts DocumentInstance doc = reportEngine.openDocument(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));
4
} } doc.setPrompts(); //also sets getMustFillPrompts to false if ((values != null)&&(values.length != 0)) prompts.getItem(j).enterValues(values);
//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 needed now 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.
4
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, however 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 74.
Table 4-1 Viewing the list of values for the Quarter object in Universe Designer.
Handling prompts for objects that have lists of values involves extending the workflow for many, simple prompts (page 68). To do this you detect if the prompt (object) has an associated list of values with Prompt.hasLOV, 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 Values.getValue, 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 74. The select tag for the list uses the same dynamic input naming described in Dynamically creating input names on page 68. Example: Displaying a simple list of values The following JSP code fragment illustrates how to get the values of a LOV 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"
4
method="post"> <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 72 shows how to modify the select tag to handle multivalued prompts.
Constrained prompts
A prompt is constrained if the answer must come from the prompts list of values. 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 only considered 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.
4
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 JSP code fragment illustrates how to modify the <select> tag of the previous example (page 70) 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>
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: The 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.
4
Chunking long lists of values
Some objects, for example Customer name, can have a very long list of values. The Lov class 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:
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 and Lov.setNestedPrompts to enter values for and set the nested prompts. Example: Handling nested prompts The following JSP 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 (docInstance.getMustFillPrompts()) {
4
} 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(); } this.fillPrompts (prompts, null); docInstance.setPrompts();
Note: You can use the methods described in Prompts with simple lists of values on page 70 to get the user input and enter the values for nested prompts.
4
//get and display the LOV //if the user clicks "Refresh List" ... lov.refresh(); Prompts nestedPmts = lov.getNestedPrompts(); this.fillPrompts (nestedPmts, lov);
4
Displaying a report map
A report map is a representation of the reports and report sections in a Web 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 use DocumentInstance.getReportMap. Example: Traversing the report map for a Web Intelligence document The following JSP code fragment traverses the following report structure and gets a section as HTML.
Section1 Report1 map.getStructure() Report2 Report3 Section2 Section1 Section2 Section2
Section1
ReportMapNodes = 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
4
// 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 HTML page associated with this section Report report = doc.setPath(sectionPath); HTMLView view = report.getView(OutputFormatType.HTML);
chapter
5
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.
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 data provider (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 data provider, 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 82. Note: The user executing the query might not be the user that set the scope of analysis. You use REBean to drill in Web Intelligence reports.
5
3. The script instructs Web Intelligence to generate the HTML for the drilled report. Web Intelligence uses the information in the documents drilling classes to generate the drilled view. 4. 5. The script displays the drilled view generated by Web Intelligence. Repeat steps 2 to 4 for each request for a drill operation.
1
s ue req ll t
Drill Option
dri
dri ll
req
ue st
Table 5-1 The process you need to implement to provide a drilling function
getting the parameters of the drill request defining the query string parameters entering and leaving drill mode setting the drill path
5
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 83.
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.
5
Drilling in Web Intelligence reports
To provide drilling functions in Web Intelligence reports you can implement the process described in The drilling process on page 80, or use the drill bar to filter the query.
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 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.
5
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.
Note: 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.
5
String[] from = request.getParameterValues("From"); String[] hierarchy = request.getParameterValues("Hierarchy"); String[] filter = request.getParameterValues("Filter");
Setting the action: up, down, by, or slice A users drill actions are classified by how they move through the drill hierarchies. Drill action Resulting report engine action Up Down By Slice The report engine replaces the current object with its parent in the drill hierarchy. The report engine replaces the current object with its child in the drill hierarchy. The report engine replaces the current object with an object that is not adjacent to it in the drill hierarchy. The report engine adds or removes the filtered values.
hierarchy 1 dimension 1 down down or by dimension 2 dimension 3 hierarchy 2 dimension 5 up dimension 6 by dimension 7 slice
dimension 4
You set the drill action with DrillPath.setAction. The actions are enumerated by DrillActionType.
5
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. For each drill operation: 1. 2. 3. 4. Get the drill from and to elements with DrillPath.getTo and DrillPath.getFrom. Add drill elements to each collection. Set the object IDs of each drill element using the values you retrieve from the query string. 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 84.
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]); } }
5
//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]); } }
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.
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 of wijsp. To get these files, copy the following to the directory containing the copied Java script files:
/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/
5
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 89.
You access the drill bar with DrillInfo.getDrillBar, and you add and remove objects to and from the drill bar with DrillBar.add and Drillbar.remove. Note: When you remove an object from the drill bar, it is automatically removed from the report filter.
5
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 88.
chapter
6
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 REBean to build data providers and edit queries for Web 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 99 and The drilling process on page 80). The query of a data provider is exposed in REBean 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 100.
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.
Note: 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.
6
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 REBean classes
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.
6
Parameters Applet parameters code useslibrary useslibrarycodebase com.businessobjects.w The path to the p.tc.TCMain applet. Web Intelligence Report Panel /webiApplet/ ThinCadenza.jar en; jp The name of the applet. The path to the archive containing the applet The path to the online help. The language of the user interface. The name of the server from which the applet is downloaded. The path to the servlet through which the server and the browser communicate. The port used for the application server The session identifier for the open document. The storage token for the document. Value(s) Description
Isapi
/servlet/ com.businessobjects.cd zlet. CadenzaServlet default is 8080 use the string returned by ReportEngine. getServerInstance use the string returned by DocumentInstance. getStorageToken when editing an open document corporate; inbox; personal.
Port CdzSession
RepoType
The type of the repository in which the document is stored. The id of the document.
DocumentID
6
Parameters DocumentName Value(s) Description The name of the document. If present, the applet automatically opens the first class of the universe. The id of the universe on which the query will be run.
OpenFirstClassOfUniverse -
You can use the implicit JSP 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 Web Intelligence Java Report Panel The following example shows JSP 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 JSP script retrieves all necessary // parameters and then launches the Web Intelligence Java // Report Panel. <% IInfoStore iStore = (IInfoStore) session.getAttribute("InfoStore");
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>
6
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. 2. 3. 4. 5. 6. Get the collection of data providers for the document. Get the universe elements in which you are interested. Get the query for the data provider. Add result objects. Add condition objects (optional). Execute the query.
Example: Building a data provider The following JSP 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:
6
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 110) 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. 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.
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 Web Intelligence Reports on page 79. 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.
6
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 Users 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 REBean, this condition is represented as follows.
FilterConditionContainer ConditionObject FilterCondition
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.
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 FilterCondition
ConditionObject
getDataSourceObject = Holiday
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.
6
ConditionPrompt cp = fc.createConditionPrompt("Country?"); cp.setConstrained(false); cp.setMonoValue(true); cp.addDefault("Australia");
Formatting Reports
chapter
7
Overview
Web Intelligence 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.
report page header/footer report body 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=";
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"); ReportEngine webiRepEngine = (ReportEngine)session.getAttribute("ReportEngine"); 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());
7
Representing document structure through containment
Document elements are structured according to their containment relationship. This element report report body page header/footer section Can contain these elements page header/footer, report body sections, blocks, and cells cells 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 page header free cell report page header free cell
report body free cell section block block free cell report cell
report body
page footer
free cell
page footer
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.
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();
Note: The header, footer, and report body elements are created by default. Also, when you create a block, the default type is TableType.HTABLE.
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
attachmentb1-c1
yb2
Table 7-3 Positioning elements relative to the parent container and siblings.
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 blocks 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
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.
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.
For a cross table the report expressions are displayed in columns and rows with a shared body.
In a graph the report expressions are displayed as a picture with two or three dimensions.
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);
7
doc.applyFormat ();
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 breaks 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.
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 Body - Left Bottom - Left Top - Body Body - Body Bottom - Body Top - Right Body - Right 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.
7
Graph category Bar Graph type Vertical Grouped Horizontal Grouped Vertical Line and Bar Horizontal Line and Bar Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D Vertical Mixed Horizontal Mixed Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D 3D Surface Vertical Absolute Horizontal Absolute Vertical Stacked Horizontal Stacked Vertical Percent Horizontal Percent 3D Area 3D Surface Pie Doughnut 3D Pie 3D Doughnut Stacked Area Radar Polar Scatter Radar Line
Line
Area
Pie
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 106.
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 cells 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.
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.
chapter
8
Overview
Web Intelligence 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 Web Intelligence SDK.
Anatomy of a recordset
In Web Intelligence SDK recordsets provide a generic way of representing the data about, or contained in, a group of objects.
a field current record d g j m p s b e h k n q t c f i l o r u 10.0 20.0 30.0 40.0 50.0 60.0 70.0 recordset fields
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 REBean
In REBean the Recordset class 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 Web Intelligence SDK Online Reference. The exceptions to this are DataProvider.getResult which returns a recordset in which the names of the fields are the names of the results (columns) of the query.
8
Moving around the recordset
Recordset can contain only one record (row) at a time. To load it use the move methods of Recordset:
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 (Recordset.getRow + 1) and when it is set to REVERSE calling Recordset.previous moves to (Recordset.getRow -1). Recordset.first and 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 or Recordset.last before you start processing a recordset so that you know which row the Recordset object contains. You can use Recordset.isLast and Recordset.isFirst to control loops that move through recordsets.
8
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 102.
appendix
Documentation
You can find answers to your questions on how to install, configure, deploy, and use Business Objects products from the documentation.
Index
A
accessing user profiles 25 actions drilling 85 Adobe Acrobat 34 see also PDF alignment 116 anchors vertical and horizontal 108 applets Web Intelligence Java Report Panel 94 area graph 114 attachments 108 authentication passwords 19 axis (block) 110 training services 126, 127
C
calculations 113 categories 3947 category details 46 category moving 46 creating 45 deleting 45 getting details 46 renaming 45 user rights, and 39 categorizing documents 39 cells creating 116 CESDK creating a ISessionMgr object 18 referencing 17 CESDK object creating 20 chunking lists of values 74 classes referencing 17 closing ReportEngine object 32 Web Intelligence sessions 20 colors 116 conditions 100 prompts 101 structure 101 consultants, Business Objects 126 contexts opening documents 48 cookies sending with JSP 20 creating blocks 110
B
background 116 bar graph 114 batched lists of values 74 blocks cells 116 creating 110 cross tables 114 forms 114 graphs 114 repeating 117 representing 113 borders 116 breaks 113 browsers storage tokens 38 building data providers 91 Business Objects consulting services 126, 127 support services 125
document structure 104 ISessionMgr object 18 ReportEngine object 31 sections 109 cross tables 114 custom 58 customer support 125
D
data providers 91102 building 94 data sources 92 executing queries 102 data sources 92 decoration pages 116 deleting categories 45 Developer Suite migration 11 dimensions drilling 82, 85 scope of analysis, and 88 displaying document lists 48 report maps 77 document structure 104 attachments 108 blocks 110 positioning elements 108 report expressions 109 sections 109 documentation feedback on 125 on product CD 124 on the web 124 roadmap 124 documents 50
see also reports categories 39 changing names 50 creating 104 dictionaries 93 displaying document lists 48 drillable 81 drilling 79 opening 13, 48 prompts 66 properties 58 refreshing 14, 66, 75 document lists 49 report maps 77 saving 50 sending 52 structure 104 types 34 Web Intelligence format 31, 83 drill bars 83, 89 drill hierarchies 82 drill mode 81, 82 entering and leaving 83 drill options 84 drill path 81, 81, 83 setting 81, 83, 85 drilling 7990 actions 85 dimensions 82 drill bars 83 drill hierarchies 83 drill mode 81, 87 drill path 81, 83, 85 filtering 89 generating HTML 82, 87 hierarchies 82, 85 hyperlinks 81, 83, 84 images 87
query string parameters 81, 81, 81, 83, 84 scope of analysis 82, 88, 99 setting parameters 86 slice 85 snapshots 90 transparent drill out of cube 82 Web Intelligence reports 8390
page decoration 116 paper size 117 reports 103 forms 114 free cells 116
E
editing blocks 110 cells 116 data providers 91 document structure 104 queries 98 sections 109 education. See training Enterprise Mode authentication 19 errors 30 exceptions 30 executing queries 102
G
getHTMLView 36 drilling 82, 87 getting started 11, 16 graphs 114
H
handling context prompts 76 exceptions 30 out of scope drill requests 88 prompts 66 hello world example 16 hierarchies drilling 83, 85 hyperlinks generating for drilling 81, 82, 83, 84, 87
F
feedback, on documentation 125 fields recordsets 120 filtering drill bars 83, 89 drill-by and drill-up actions 86 queries 100 query conditions 89 fonts 116 foreground 116 formats saving 50 formatting layout 117
I
images drilling 87 importing code in JSP 24 include directive in JSP 24 information resources 124 InfoView example workflows 13 user profiles 25 Introduction 9
J
Java Report Panel see Web Intelligence Java Report Panel Java script files drilling 87 java.util.Properties 26, 58 JSP importing code 24 reading a user profile 26 sending cookies 20 reports 77 nested prompts 74 NT Challenge Mode authentication 20
O
objects query results 99 Online Customer Support 125 opening documents 13, 48 out of scope drills 82, 88, 99
L
landscape layout 117 layout 117 line graph 114 listing documents 48 lists of values 7076 batched 74 chunking 74 constrained prompts, and 71 displaying 70 multicolumn 72 prompts in (nested) 74 refreshing 75 log in and log out 16 logins 18 LOV see lists of values
P
packages java.util.Properties 58 page layout 117 page decoration 116 paper size 117 passwords 18 storage token 36 PDF displaying Web Intelligence reports 62 output format 64 .pdf see PDF pie chart 115 portrait layout 117 prompts 6676 conditions 101 constrained 71 context 66, 76 drilling 89 entering values 72 lists of values 70 multicolumn lists of values 72 multivalued 71 nested 74 storage tokens 36
M
managing documents 34 Microsoft Excel displaying Web Intelligence reports 62 output format 64 migration 11, 50 multivalued prompts 71
N
navigating
properties 58 documents 58
Q
queries 92 editing 98 executing 102 query conditions 89, 100 query strings drilling 81, 81, 81, 83, 83, 84
R
radar & scatter graph 115 REBean building data providers 91 creating a ReportEngine object 31 document properties 58 exceptions 30 features 10 formatting reports 103 prompts 66 RECOM creating a ReportEngine object 31 prompts 66 RECOM.dll 31 recordsets 119122 changing records 121 fields 120 referencing CESDK 17 Web Intelligence SDK classes 17 refreshing document lists 49 documents 14, 66, 75 lists of values 75 renaming categories 45 RENET exceptions 30 features 10 report expressions 109, 110 adding to axes 112
breaks 113 calculations 113 sorting 113 report maps 77 snapshots, and 90 Report Panel see Web Intelligence Java Report Panel ReportEngine object 31 closing 32 reports drilling 79, 82, 87 filters 89 formatting 103117 report maps 77 viewing all the reports in a document 62 repository opening documents 48 sending documents 52 resolving universe contexts 76 resources 124 result objects 99 running queries 102
S
save to corporate see publishing saving documents 50 scope of analysis 80, 82, 99 handling manually 88 scripts drilling 87 sections creating 109 sending documents 5254 session ID cookies, and 20 sessions closing 20 creating 20, 48
drill parameters 86 user profiles 28 settings in user profiles 25 slice drill action 85 snapshots 90 SQL executing 102 storage tokens advantages 38 browser navigation 38 generation triggers 35 life cycle 35 opening documents 48 viewing reports 62 support customer 125 locations 125 technical 125 web site 125
user names 18 user profiles 25, 48 accessing 25 adding to 29 setting 28 user rights 48 categories, for 39 transparent drill out of cube 82 user sessions see Web Intelligence sessions
V
values prompts 70 viewing binary view 62 Web Intelligence reports 6178
W
web customer support 125 getting documentation via 124 useful addresses 127 Web Intelligence documents building data providers 91 formatting reports 103 saving 50 sending 52 Web Intelligence Java Report Panel 94 launching 94 Web Intelligence SDK creating a ISessionMgr object 18 exceptions 30 features 34 hello world 16 login 18 migration 11 packages 10 referencing classes 17
T
tables cross tables 114 vertical and horizontal 113 technical support 125 temporary files storage tokens 35 training, on Business Objects products 126 transparent drill out of cube 82 traversing categories 41 report maps 77 triggers generating storage tokens 35
U
universes 92 resolving contexts 76
Index
Web Intelligence sessions closing 20 creating 48 storage tokens 38 web sites support 125 training 126
Index