Querying the InfoStore


For most everything else that cannot be invoked from the EnterpriseSession object, you need to query the InfoStore first. This includes creating objects, scheduling them, updating them, or simply retrieving them.

InfoStore objects include reports, users, groups, folders, categories, dashboards, schedules, license keys, server registrations, Universes, and Business Viewsevery bit of information that is presented through the portal and which the system needs to function. Regardless of type, they are all InfoObjects that implement the InfoObject interface. Every InfoObject has certain common properties, such as an ID, name, and kind. Other properties are stored as name-value pairs in a property bag datastructure.

Objects are all stored physically in the Business Objects repository database in both primitive (common properties) and composite binary fields (the rest of the bag). If you like, you can inspect the CMS_InfoObjects4 table in a database browser. The model is highly denormalized for performance. In BusinessObjects Enterprise XI, additional tables were added to speed up alias and hierarchy access associated with the inclusion of many-to-many object categorization in the design.

Note

Did you know that the original Seagate Info had more than 20 physical tables? Its successor, Crystal Enterprise 8.0, implemented a new InfoStore service that made much greater use of binary fields in the database and eliminated reliance on database-enforced referential integrity. Smart engineers in Vancouver found that performance increased considerably and that linear scalability was now attainable.


Now that you understand that certain properties are represented physically and indexed in the database and others are buried in binary fields, please forget that there is a physical database behind InfoStore. You will never access this or any of the other tables in the system directly. Rather, you will retrieve objects using an SQL-style syntax executed against an API object called the InfoStore.

The statement below returns a list of all user-names in the system. This code snippet, like others in this chapter, assumes that valid local IInfoStore (iStore) and EnterpriseSession (es) instances have been instantiated.

IInfoObjects objs=iStore.query('SELECT SI_NAME FROM CI_SYSTEMOBJECTS WHERE  SI_KIND='USER'')


Under the covers, the Central Management Server (CMS) service sometimes runs a query against the physical tables, but more often it runs a query against in-memory datastructures it maintains as the system is used.

Note

If you want to speed up your InfoStore queries, you can put a loop in your application initialization code that requests a bunch of the objects from the InfoStore. There are obviously short-term performance implications in doing this.


The InfoStore functions much like an object-relational persistence tier with its own proprietary methods of accessing and updating objects. Here are some unusual characteristics that will help you understand some of the other examples in this chapter and the product documentation:

  • Everything is an IInfoObject The InfoStore contains many objects of many types or classes. However, they all inherit from the common IInfoObject class that permits them to be queried and persisted in a common manner and allows them to share certain common properties and methods. Casting is the conversion of one data type to another. When retrieving an IInfoObject object, it is sometimes necessary to cast it to a more specific object type, such as IReport. At a minimum, when iterating through IInfoObjects returned by an InfoStore query, objects must be cast to an IInfoObject.

  • Creating an object with Plugins When you create an object, you won't find a CreateThisTypeOfObject() method in the API. Rather, you need to look up the object type in the InfoStore and first get a reference to a system object called the Plugin interface. Similarly, if you want to schedule to a destination such as e-mail, you must get a destination plugin from the InfoStore. This design is flexible, in that new object types and destinations may be added without affecting the API, but it can be awkward to use.

  • Embedded objects Certain objects have what appear to be embedded objects. Job scheduling or report processing objects are accessed from their container objects through the SI_SCHEDULEINFO and SI_PROCESSINFO properties respectively. For instance, iStore.query("SELECT SI_SCHEDULEINFO FROM CI_INFOSTORE WHERE SI_NAME='World Sales Report'") will return each of the schedules created for the World Sales Report. Embedded objects, such as scheduling or processing information, must be cast before they can be accessed.

  • Committing changes to objects There is, in fact, no way to commit changes to one object. Every change to an InfoStore object starts with selecting all objects that meet certain criteria, iterating through the collection, modifying one or more InfoObject, and then committing all of the originally retrieved objects to the InfoStore.

Knowing what types of objects and their properties that are available for selection and/or for filtering the InfoStore will help you understand what you can do with BusinessObjects Enterprise. These topics are covered next.

BusinessObjects Enterprise Categories, Kinds, and Casting

InfoStore objects live virtually in one of three categories which are accessed in the FROM clause of an InfoStore query. Different types of objects belong to different categories. In fact, several objects, such as Folder, belong to more than one category. In BusinessObjects Enterprise XI you no longer need to use the CI_PROGID identifier to find a certain type of object, but rather you use the more friendly CI_KIND property. Kinds can be accessed literally or through the com.crystaldecisions.sdk.plugin.CeKinds enumeration. Note that sometimes the enumerated constant is not the same as the literal value. The following query string will return no values:

[View full width]

IInfoObjects objs=iStore.query('SELECT TOP 1 FROM CI_INFOOBJECTS WHERE SI_KIND='CRYSTAL_REPORT'');


These two, however, will work:

[View full width]

IInfoObjects objs=iStore.query('SELECT TOP 1 FROM CI_INFOOBJECTS WHERE SI_KIND=''+ com .crystaldecisions.sdk.plugin.CeKinds.CRYSTAL_REPORT+''); IInfoObjects objs=iStore.query('SELECT TOP 1 FROM CI_INFOOBJECTS WHERE SI_KIND='CrystalReport'');


This is because the literal value "CRYSTAL_REPORT" is not a SI_KIND. However, com.

crystaldecisions.sdk.plugin.CeKinds.CRYSTAL_REPORT evaluates to 'CrystalReport'.


Tables 30.430.7 list what kinds of objects can be found in each category, as well as the interface objects to which they must be cast for all of their properties to be accessible. Certain object types specific to the Application Foundation and Performance Management suite of products are unpublished.

Table 30.4. CI_INFOOBJECTS Kinds

SI_KIND Value

CeKind Enumeration

Interface

AFDashboardPage

AFDASHBOARDPAGE

Unpublished

Analytic

ANALYTIC

Unpublished

Category

CATEGORY

ICategory

CrystalReport

CRYSTAL_REPORT

IReport

Excel

EXCEL

IExcel

FavoritesFolder

FAVORITESF

IFolder

Folder

FOLDER

IFolder

Hyperlink

HYPERLINK

IHyperlink

Inbox

INBOX

IInbox

MyInfoView

MYINFOVIEW

Unpublished

ObjectPackage

OBJECTPACKAGE

IObjectPackage

Pdf

PDF

IPDF

PersonalCategory

PERSONALCAT

ICategory

Powerpoint

POWERPOINT

IPowerpoint

Program

PROGRAM

IProgram

Shortcut

SHORTCUT

IShortcut

Txt

TEXT

ITxt

Webi

WEBI

IWebi

Word

WORD

IWord


Table 30.5. CI_SYSTEMOBJECTS Kinds

SI_KIND Value

CeKind Enumeration

Interface

Calendar

CALENDAR

ICalendar

Connection

CONNECTION

IConnection

Event

EVENT

IEvent

LicenseKey

LICENSEKEY

ILicenseKey

Server

SERVER

IServer, IServerGeneralMetrics

User

USER

IUser

UserGroup

USERGROUP

IUserGroup


Table 30.6. CI_APPOBJECTS Kinds

SI_KIND Value

CeKind Enumeration

Interface

AppFoundation

APPFOUNDATION

Unpublished

CMC

CMC

Unpublished

Designer

DESIGNER

Unpublished

Discussions

DISCUSSIONS

Unpublished

InfoView

INFOVIEW

Unpublished

StrategyBuilder

STRATEGY_BUILDER

Unpublished

Universe

UNIVERSE

IUniverse

WebIntelligence

WEBINTELLIGENCE

IWebi


Table 30.7. Other Object Kinds

SI_KIND Value

CeKind Enumeration

Interface

Destination

DESTINATION

IDestination

DiskUnmanaged

DISKUNMANAGED

IDiskUnmanaged

Ftp

FTP

IFTP

Managed

MANAGED

IManged

Overload

OVERLOAD

IOverload

Rtf

RTF

IRTF

secEnterprise

SEC_ENTERPRISE

IsecEnterprise

secLDAP

SEC_LDAP

IsecLDAP

secWinAD

SEC_WINAD

IsecWinAD

secWindowsNT

SEC_WINDOWSNT

IsecWinNT

ServerGroup

SERVER_GROUP

IServerGroup

Smtp

SMTP

ISMTP


Although not shown, Folder objects can be referenced from all three table contexts.

  • CI_INFOOBJECTS Contains portal content

  • CI_SYSTEMOBJECTS Contains system objects required for the system to function and that are displayed and managed in the user interface

  • CI_APPOBJECTS Other objects stored in the repository but managed through client-server tools or add-ons to the system

Several other kinds of objects require more sophisticated query statements to access. They include destination and security plugins.

BusinessObjects Enterprise Object Properties

Object properties are discussed next, organized first by common, indexed properties, and then by the types of objects or functions for which they are used. These properties can be found in the CePropertyID enumerated list and a complete list can be found in the SDK documentation itself. Usage notes are provided inline and several of the more commonly used ones will reappear in the sections and samples that follow.

Property Bags

All InfoObject propertiesboth indexed and nonindexedare accessible from the object's property bag interface, properties(). These properties are accessed with their CePropertyID identifier as shown here:

//get the object IInfoObject obj=(IInfoObject)objs.get(0); //get the SI_INSTANCE property int SI_INSTANCE =obj.properties().getProperty(CePropertyID.SI_INSTANCE). getValue();


However, certain indexed properties have direct accessor methods as noted. For instance, getID() saves a few keystrokes on obj.properties().getProperty(CePropertyID.SI_ID).getValue(). Should you want to list everything in an IInfoObject, you could use call a function to recursively display the object property bags. This is such a useful function that it is provided in Listing 30.1 in its entirety.

Listing 30.1. Recursively Listing IInfoObject Properties

    public static String infoObjectToString(IInfoObject obj){         return propertyBagToString(obj.properties());     }     public static String propertyBagToString(IProperties propMap) {         return propertyBagToString(propMap,"");     }     private static String propertyBagToString(IProperties propMap,String  prefix) {         StringBuffer buff = new StringBuffer();         buff.setLength(0);         if ((propMap != null) && (propMap.size() > 0)) {             Iterator iter = propMap.entrySet().iterator();             while (iter.hasNext()) {                 Map.Entry p = (Map.Entry) iter.next();                 Integer id=(Integer)p.getKey();                 buff.append(prefix+CePropertyID.idToName(id));                 IProperty prop=(IProperty)p.getValue();                 if (prop.isContainer()){                     IProperties props=(IProperties)prop.getValue();                     buff.append("\n"); buff.append(propertyBagToString(props,prefix+CePropertyID.idToName(id)+"."));                 } else {                     buff.append("="+prop.getValue()+"\n");                 }             }         }         return buff.toString();     }

This function returns property objects that fall into one of three categories:

  • Top-level properties that contain values such as strings and integers

  • Composite properties that contain other properties that require casting

  • Composite properties that actually represent embedded objects with their own identifiers in the system

The SI_SCHEDINFO property, for instance, contains a collection of job objects that spawn new instances on a schedule. Listing 30.2 shows many of the properties for the Product Category report, which has not been assigned to any corporate or personal categories, scheduled, or had its default processing options modified; Microsoft Access requires none and the system default printer is assigned by default. The listing shows the output properties for the Product Catalog sample report shipping with BusinessObjects Enterprise. Properties such as SI_FILE are composite properties. There are no embedded objects in this listing as the report has not been scheduled.

Listing 30.2. Product Catalog Report Property Listing

[View full width]

SI_APPLICATION_OBJECT=false SI_AUTHOR=Copyright © 2004 Business Objects SI_BUSINESSVIEWS SI_BUSINESSVIEWS.SI_TOTAL=0 SI_CHILDREN=28 SI_COMPONENT=false SI_CORPORATE_CATEGORIES SI_CORPORATE_CATEGORIES.SI_TOTAL=0 SI_CREATION_TIME=Mon Dec 06 17:58:25 PST 2004 SI_CUID=AaCbu62TlMdDo60E358dydA SI_DESCRIPTION=Product catalog, grouped by Product Class, Product Type and  Product Name  with Product Type picture and description. Drill down on  Product Name for item numbers,  sizes, etc. SI_FILES SI_FILES.SI_FILE1=~ce14483a4783797718.rpt SI_FILES.SI_FILE2=~ce14483a478383d719.jpeg SI_FILES.SI_NUM_FILES=2 SI_FILES.SI_PATH=frs://Input/a_194/024/000/6338/ SI_FILES.SI_VALUE1=728064 SI_FILES.SI_VALUE2=23015 SI_FLAGS=2050 SI_GUID=AbzQfLTci61CnFu8C6sIH3Y SI_HASSAVEDDATA=false SI_HASTHUMBNAIL=true SI_HIDDEN_OBJECT=false SI_ID=6338 SI_INSTANCE_OBJECT=false SI_INSTANCE=false SI_IS_SCHEDULABLE=true SI_KIND=CrystalReport SI_LAST_RUN_TIME=Fri Feb 18 14:25:09 PST 2005 SI_LAST_SUCCESSFUL_INSTANCE_ID=32052 SI_NAME=Product Catalog SI_OBJECT_IS_CONTAINER=false SI_OBTYPE=2 SI_OWNER=Administrator SI_OWNERID=12 SI_PARENT_CUID=ARD1V.IRaKdPs3fPUzttR3k SI_PARENT_FOLDER_CUID=ARD1V.IRaKdPs3fPUzttR3k SI_PARENT_FOLDER=6322 SI_PARENTID=6322 SI_PERSONAL_CATEGORIES SI_PERSONAL_CATEGORIES.SI_TOTAL=0 SI_PLUGIN_OBJECT=false SI_PROGID=CrystalEnterprise.Report SI_REFRESH_OPTIONS=-2 SI_RUID=AaCbu62TlMdDo60E358dydA SI_RUNNABLE_OBJECT=false SI_SENDABLE=true SI_SYSTEM_OBJECT=false SI_TABLE=0 SI_TOPIC_TOPIC_FOR_SUBJECT_GENERICENTITY SI_TOPIC_TOPIC_FOR_SUBJECT_GENERICENTITY.SI_TOTAL=0 SI_TURNONREPOSITORY=false SI_TURNONTHUMBNAIL=true SI_UPDATE_TS=Fri Feb 18 14:25:09 PST 2005

Indexed Properties

Every property in the property bag can be supplied in the SELECT clause (but not necessarily in the WHERE clause) of an InfoView query. Embedded object properties make no sense in the WHERE clause, but the full path to embedded object properties might. Querying for IInfoObjects WHERE SI_FILES.SI_NUM_FILES > 1 is a bogus, but valid, example. However, when querying the InfoStore, it is vital to include at least one common, indexed property to help reduce the working set. These properties exist physically in the repository database and can be queried at will without degrading system performance. Filtering exclusively on a nonindexed property forces the InfoStore API to open and examine every object in the InfoStore table to find a match. Such fields must be read, parsed, and loaded into the InfoStore memory cache before they can be used by the system, which can take time and precious CPU cycles.

Note

Don't worry about the order of fields in the WHERE clauseBusinessObjects Enterprise will reorder evaluation from indexed to nonindexed properties appropriately prior to execution.


Table 30.8 lists all of the indexed properties. The boolean properties SI_HIDDEN_OBJECT, SI_NAMED_USER, and SI_PLUGINOBJECT are rarely used and have been omitted from this table. Certain job-specific properties might be null. Especially in Java, you must always test for nulls to avoid the dreaded and never specific Null Pointer Exception. Code defensively!

Table 30.8. Indexed Properties

Property

Type

InfoObject Accessor Method

Description/Usage Notes

SI_ID

Integer

getID()

A sequence number unique to a single installation unless it is a common, default system object below 350. Remember that your code will not work if you hard-code an object's SI_ID and then move that object from your development to test to production environments.

SI_CUID

String

getCUID()

A string identifier, unique and consistent across all environments. Migration safe.

SI_GUID

String

getGUID()

Reserved for future use.

SI_RUID

String

getRUID()

A string identifier that uniquely identifies an InfoObject within an object package. Outside of a package, it is equivalent to SI_CUID.

SI_NAME

String primitive

getTitle()

Object name or title. Note that instances and jobs share the same name. It is typically insufficient to query on SI_NAME alone.

SI_KIND

String

getKind()

New to BusinessObjects Enterprise XI, this property replaces SI_PROGID as the preferred method for retrieving objects of a certain type (as discussed above).

SI_DESCRIPTION

String

getDescription()

Longer description.

SI_PROGID

String

getProgID()

The internal object type identifier. For example, CrystalEnterprise.CrystalReport.

SI_OWNERID

Integer

getOwnerID()

The owner of this object. Particularly useful when trying to find a user's recurring or one-time job schedules or historical instances they have created.

SI_PARENTID

Integer

getParentID()

The parent of this object. For report templates, this refers to the parent folder. For report instances, SI_PARENTID points to the report template rather than the containing folder. The noninteger property SI_PARENT_FOLDER is the best way to finds an instance's folder.

SI_UPDATE_TS

Timestamp

Property bag

The last time any property of the object was modified. Date is returned in the format MM/DD/YYYY HH:MM:SS AM/PM. In the WHERE clause, these formats are valid: yyyy.mm.dd.hh.mm.ss, yyyy/mm/dd/hh/mm/ss, yyyy/mm/dd.hh.mm.ss, yyyy/mm/dd,hh:mm:ss. For example, SELECT SI_ID, SI_NAME FROM CI_INFOOBJECTS WHERE SI_UPDATE_TS > '2000.01.11.18:00:00'.

SI_INSTANCE, SI_INSTANCE_OBJECT

Boolean 1/0

Property bag

Specifies whether to retrieve the report/document or an historical instance run by the scheduler as a job.

SI_NEXTRUNTIME

Timestamp

Property bag

Nullable. The next time that one of the job servers will attempt to create an instance. See usage notes for SI_UPDATE_TS.

SI_RECURRING

Boolean 1/0

Property bag

May be null. For job/schedule embedded objects, indicates whether a job will run more than once.

SI_RUNNABLE_OBJECT

Boolean 1/0

Property bag

May be null. Crystal Reports, Web Intelligence, Program Objects, and Object Packages can be scheduled. To be runnable, such an object must actually be scheduled to run and create an instance.

SI_SCHEDULE_STATUS

Integer

Property bag

May be null. Status of a runnable object. Constantly requires decoding using the ceScheduleStatus enumeration.


Composite Properties, Embedded Objects

As discussed earlier, certain properties contain other properties and, in the case of SI_SCHEDINFO, have identifiers that permit individual retrieval and manipulation. A simple example is that SI_PATH, which is for folder objects, returns the property bag that includes the IDs, names, and types of every folder ancestor for the object. The function folderBreadCrumbs(String folderID, IInfoStore iStore) found in BOEUtil.java on www.usingcrystal.com shows how this is used.

Table 30.9 highlights some other composite properties that contain both primitive and composite values. Subproperties can be queried using dot notation. For instance, the following code retrieves the names of all the users who scheduled the World Sales Report.

[View full width]

String sql = ' SELECT SI_SCHEDULEINFO.SI_SUBMITTER FROM CI_INFOOBJECTS WHERE SI_NAME='World Sales Report''; IInfoObjects objects = iStore.query(sql);


Table 30.9. Composite Properties (Incomplete List)

Composite Property

Sample Property Values (Vary Based on Data)

Embedded Object Properties

SI_SCHEDULEINFO

Returns multiple schedule (job) objects associated with an InfoObject or the schedule object itself (if accessed directly).

SI_ENDTIME=Wed Mar 16 00:00:00 PST 2005

SI_NAME=Product Catalog

SI_OBJID=31747

SI_OUTCOME=0

SI_PROGRESS=1

SI_RETRIES_ALLOWED=0

SI_RETRIES_ATTEMPTED=0

SI_RETRY_INTERVAL=1800

SI_SCHED_NOW=false

SI_SCHEDULE_INTERVAL_HOURS=0

SI_SCHEDULE_INTERVAL_MINUTES=0

SI_SCHEDULE_INTERVAL_MONTHS=0

SI_SCHEDULE_INTERVAL_NDAYS=0

SI_SCHEDULE_INTERVAL_NTHDAY=0

SI_SCHEDULE_TYPE=8

SI_STARTTIME=Wed Feb 16 18:13:00 PST 2005

SI_SUBMITTER=Administrator

SI_SUBMITTERID=12

SI_TIMEZONE_ID=0

SI_TYPE=2

SI_UISTATUS=9

SI_DEPENDANTS

SI_DEPENDENCIES

SI_DESTINATION

SI_RUN_ON_TEMPLATE

SI_PROCESSINFO

Contains report processing directives.

SI_DBNEEDLOGON=true

SI_DEPENDS_ON_CIV=false

SI_ALERT_INFO

SI_BUSINESS_VIEW_INFO

 

SI_DEPENDS_ON_METADATA=false

SI_GROUP_FORMULA=

SI_HAS_DCP=false

SI_FILES

SI_FORMAT_INFO

SI_HYPERLINK_INFO

 

SI_NAME=Statement of Account

SI_NUM_GROUPS=2

SI_OBJID=6333

SI_RECORD_FORMULA={Orders.Order Amount}>0 and {Orders.Shipped}=Yes and not {Orders.Payment Received}

SI_RFSH_HITS_DB=true

SI_ROW_LEVEL_SECURITY=false

SI_SESSION_NEEDINFO=false

SI_SESSION_USER=

SI_SHARE_INTERVAL=300

SI_SHARE_SETTINGS=false

SI_SHARE=true

SI_USES_FILE_DB=false

SI_LOGON_INFO

SI_PRINTER_INFO

SI_PROMPTS

SI_REPOSITORY_OBJECTS

SI_PATH

Ancestor folders.

SI_FOLDER_OBTYPE1=1

SI_FOLDER_ID1=6319

SI_FOLDER_NAME1=Report Samples

SI_NUM_FOLDERS=1

SI_FILES

Path to file report template and thumbnail in the File Input Server.

SI_FILE1=~ce14483a4783797718.rpt

SI_FILE2=~ce14483a478383d719.jpeg

SI_NUM_FILES=2

SI_VALUE1=728064

SI_VALUE2=23015

 


For more information on these composite properties, consult the documentation and use the property bag recurser function to explore them yourself.

Property Enumerations

In Listing 30.3 and in ones that follow, property values are represented as numeric constants or codes. Fortunately, there is an easy way to decode these valuesthe static method on CePropertyID called idToName(java.lang.Integer id). This function will work for every property, although you might want to write your own based on the appropriate SDK property enumeration.

Listing 30.3. Schedule Status Decoder

   public static String getScheduleStatusDescription(int status) {         switch (status) {             case (ISchedulingInfo.ScheduleStatus.COMPLETE):                 return "COMPLETE. Job completed successfully."; <SNIP></SNIP>             default:                 return "Status code not found";         }     }

Other enumerations to familiarize yourself with include CeEvents, CeKind, and CeScheduleType. Enumerations in the ISchedulingInfo interface include GroupChoice, ScheduleFlags, ScheduleOutcome, and ScheduleStatus. For a complete list of enumerations, please consult the API documentation.

Note

The etymology of the CI and SI in table and property names might reflect the company heritage of the product, first in Seagate Software's Seagate Info, and then in Crystal Decisions, Crystal Enterprise. The C could also stand for Catalog. This kind of legacy name pollution is common in the software industry.


System Objects and Root Folders

As you get into more advanced SDK programming, it will help to know the addresses of well-known system objects and root folders. There are more than 100 such objects installed by default with BusinessObjects Enterprise. Only their enumerations are listed here for brevity:

  • CeSecurityID.Folder The IDs of the BusinessObjects Enterprise system folders.

  • CeSecurityID.Limit The IDs of the BusinessObjects Enterprise system security limits.

  • CeSecurityID.Right The IDs of the BusinessObjects Enterprise system security rights.

  • CeSecurityID.User Common user and group IDs.

  • CeSecurityCUID.AppConfigObject Identifies the unique CUIDs that are used in a query to specify the application configuration components. Remember, these are in the CI_SYSTEMOBJECTS category.

  • CeSecurityCUID.Relation Identifies the unique CUIDs that are used in a query to retrieve related, dynamically generated objects.

  • CeSecurityCUID.RootFolder Identifies the unique CUIDs that are used in a query to specify the root folder. The following SELECT statement can be used to return top level folders:

    [View full width]

    sql = "Select * FROM CI_INFOOBJECTS where SI_KIND = 'Folder' and SI_PARENTCI_INFOOBJECTS" ,iStore).getID(); objects = iStore.query(sql);

  • CeSecurityCUID.SystemObject Identifies the unique CUIDs that are used in a query to specify the system objects. Remember, these are in the CI_SYSTEMOBJECTS category.

Note

Please note that the identifiers provided in these enumerations are the CUID unique identifiers, not numeric identifiers. As a result, filters such as SI_ANCESTOR that expect a numeric ID will not work.

This statement fails:

[View full width]

IInfoObjects objs=iStore.query("SELECT * CI_APPOBJECTS WHERE SI_ANCESTOR=" + CeSecurityCUID.RootFolder.UNIVERSES + " AND SI_KIND='Universe' ORDER BY SI_NAME");


However, this works:

[View full width]

IInfoObjects objs=iStore.query("SELECT SI_ID CI_APPOBJECTS WHERE SI_CUID='" + CeSecurityCUID.RootFolder.UNIVERSES+"'"); int UnvRootID=((IInfoObject)objs.get(0)).getID(); System.out.println("UnvRootID:"+UnvRootID); IInfoObjects unvs=iStore.query("SELECT SI_ID, SI_NAME, SI_CUID FROM CI_APPOBJECTS WHERE SI_ANCESTOR="+ UnvRootID+" AND SI_KIND='Universe' ORDER BY SI_NAME");


Remember, Universe objects are in the CI_APPOBJECTS category.


Certain system objects, unfortunately, are not in any enumeration. For instance, the only way to schedule objects to e-mail is to get a handle on an SMTP destination plugin, which is a child of the object known by its CUID as CeSecurityCUID.SystemObject.PLUGIN. You can iterate through these children yourself and see that the SMTP destination plugin has an ID of 29.

Permissions

Another set of constants is the rights registered for each object type. Global security rights are in the CeSecurityID.Right enumeration. Certain objects cannot be scheduled, so schedule-oriented rights naturally do not apply to those objects. System administrators will be familiar with the following enumerated rights from the CMC console:

  • CeSecurityID.Right ADD, COPY, DELETE, DELETE_INSTANCE, EDIT, MODIFY_RIGHTS, OWNER_DELETE, OWNER_DELETE_INSTANCE, OWNER_EDIT, OWNER_MODIFY_RIGHTS, OWNER_PAUSE_RESUME_SCHEDULE, OWNER_RESCHEDULE, OWNER_SECURED_MODIFY_RIGHTS,OWNER_VIEW, OWNER_VIEW_INSTANCE, PAUSE_RESUME_SCHEDULE, PICK_MACHINES, RESCHEDULE, SCHEDULE, SCHEDULE_ON_BEHALF_OF, SECURED_MODIFY_RIGHTS, SET_DESTINATION, VIEW, VIEW_INSTANCE

  • CeReportRightID DOWNLOAD, EXPORT, PRINT, REFRESH_ON_DEMAND

  • CeWebiRightID DOWNLOAD_FILES, EDIT_QUERY, EXPORT_REPORT_DATA, REFRESH_LIST_OF_VALUES, RUN_AND_REFRESH_DOC, USE_LIST_OF_VALUES, VIEW_SQL

Using the permissions model fully is very complicated because BusinessObjects Enterprise supports cascading, inherited rights on folders and from groups, as well as explicit denials. The most basic permissions (viewing a folder or report), are resolved transparently within an InfoStore query. Objects that cannot be seen by the user are not returned. However, for more advanced rights, you need to use the ISecurityInfo.checkCustomRights method. Listing 30.4 shows how to determine a user's WebI viewing rights.

Listing 30.4. Determining User Permissions

        // Webi app rights         IInfoObject app = getWebiAppObj(es, iStore);         if (app != null) {             int[] rightsToCheck = new int[]{                 CeWebIntelligenceRightID.INTERACTIVEVIEW,                 CeWebIntelligenceRightID.HTMLREPORTPANEL,                 CeWebIntelligenceRightID.JAVAREPORTPANEL,                 CeWebIntelligenceRightID.DRILLMODE,                 CeWebIntelligenceRightID.CREATEDOCUMENTS};             String kind = app.getKind();             String[] kinds = new String[rightsToCheck.length];             for (int i = 0; i < kinds.length; i++)                 kinds[i] = kind;             ISecurityInfo secInfo = app.getSecurityInfo();             boolean[] results = secInfo.checkCustomRights(rightsToCheck, kinds, false);             r.setWebiInteractiveViewingAllowed(results[0]);             r.setWebiHtmlReportPanelAllowed(results[1]);             r.setWebiJavaReportPanelAllowed(results[2]);             r.setWebiDrillModeAllowed(results[3]);             r.setWebiCreateDocsAllowed(results[4]);         }

Rights can also be checked individually. Please consult the product documentation for more information.

Setting Custom Properties

The BusinessObjects Enterprise InfoObject is a very versatile container that easily persists properties for every type of object. The following code shows how you can add custom properties to InfoObjects. Remember the process for updating a document: query for objects, choose an object, set properties on that object, commit (all) objects.

[View full width]

public static void propertiesSet(int objID, String category, HashMap props, IInfoStore iStore) throws SDKException { IInfoObjects objs = iStore.query("SELECT * FROM "+category+" WHERE SI_docText">Note that custom properties cannot be accessed directly using syntax such as SI_MY_CUSTOM_PROPERTY. To access them you must use the asterix (*) in the SELECT clause when searching for custom properties and then use the getProperty() method used in the recursive property bag lister.

Using * and Top N

As discussed, queries that return all properties using the asterisk operator (*) might actually return many objects. It is conceivable that a report could have 1,000 schedules associated with it. Selecting the SI_SCHEDINFO project might return 1,000 rows for 1 report alone.

Another must-know tip is how to use Top N. In BusinessObjects Enterprise, SELECT * returns an upper-limit of 1,000 objects. You can specifically ask for more or fewer objects using SELECT TOP N. You can see whether you are looking at all of the records that satisfy your query by comparing the resultInfoObjcts.getResultSize() method to the actual number of records found through the resultInfoObjcts.size() method.

Query Examples

Now that you understand the syntax of querying the InfoStore, some of the properties, and how they are nested, look at the following examples harvested from the documentation and the author's own BusinessObjects Enterprise projects. The example includes only the query statement itself and an explanation of what is returned by the query. The InfoStore only returns the objects that the user is permitted to view:

  • Report templates in the Report Samples folder or subfolders. SI_ANCESTOR can only be used in the WHERE clause.

    SELECT SI_NAME FROM CI_INFOOBJECTS WHERE SI_ANCESTOR=6319 AND SI_INSTANCE=0

  • List of universe meta-layers.

    SELECT * FROM CI_APPOBJECTS WHERE SI_KIND='Universe' ORDER BY SI_NAME ASC

  • Parent folder of all universes.

    SELECT SI_ID FROM CI_APPOBJECTS WHERE SI_PARENTID=95 AND SI_NAME='Universes'

  • Scheduled jobs submitted by WRichards for World Sales Report.

    [View full width]

    SELECT SI_ID FROM CI_INFOOBJECTS WHERE SI_NAME = 'World Sales Report' AND SI_SCHEDULEINFO .SI_SUBMITTER = 'WRichards'

  • Get recurring scheduled jobs owned by WRichards. SI_RECURRING will be null for nonjobs and 0 for one-time jobs.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards' AND SI_RECURRING=1

  • Get all scheduled jobs owned by WRichards. Note how selecting SI_SCHEDINFO forces selection of job objects.

    SELECT SI_SCHEDINFO FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards'

  • Get all objects owned by WRichards.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards'

  • Get report templates owned by WRichards. SI_INSTANCE will return null for nonreport objects, 1 for report instances, and 0 for templates.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_OWNERID='WRichards' AND SI_INSTANCE=0

  • Returns instances of report identified by 215.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_PARENTID=215 AND SI_INSTANCE=1

  • Returns top-level report templates that have been scheduled to run.

    SELECT * FROM CI_INFOOBJECTS WHERE SI_RUNNABLE_OBJECT=1




Crystal Reports XI(c) Official Guide
Crystal Reports XI Official Guide
ISBN: 0672329174
EAN: 2147483647
Year: N/A
Pages: 365

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net