Querying the InfoStore
来源:互联网 发布:玻璃优化切割软件 编辑:程序博客网 时间:2024/06/13 13:34
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 commonIInfoObject 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 anIInfoObject 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 anIInfoObject.
Creating an object with Plugins When you create an object, you won't find aCreateThisTypeOfObject() 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 theSI_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 selectingall objects that meet certain criteria, iterating through the collection, modifying one or more InfoObject, and then committingall 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 asFolder, belong to more than one category. In BusinessObjectsEnterprise XI you no longer need to use the CI_PROGID identifier to find a certain type of object, but rather you use the more friendlyCI_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 aSI_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
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 objectIInfoObject obj=(IInfoObject)objs.get(0);//get the SI_INSTANCE propertyint 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 asSI_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
SI_APPLICATION_OBJECT=falseSI_AUTHOR=Copyright © 2004 Business ObjectsSI_BUSINESSVIEWSSI_BUSINESSVIEWS.SI_TOTAL=0SI_CHILDREN=28SI_COMPONENT=falseSI_CORPORATE_CATEGORIESSI_CORPORATE_CATEGORIES.SI_TOTAL=0SI_CREATION_TIME=Mon Dec 06 17:58:25 PST 2004SI_CUID=AaCbu62TlMdDo60E358dydASI_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_FILESSI_FILES.SI_FILE1=~ce14483a4783797718.rptSI_FILES.SI_FILE2=~ce14483a478383d719.jpegSI_FILES.SI_NUM_FILES=2SI_FILES.SI_PATH=frs://Input/a_194/024/000/6338/SI_FILES.SI_VALUE1=728064SI_FILES.SI_VALUE2=23015SI_FLAGS=2050SI_GUID=AbzQfLTci61CnFu8C6sIH3YSI_HASSAVEDDATA=falseSI_HASTHUMBNAIL=trueSI_HIDDEN_OBJECT=falseSI_ID=6338SI_INSTANCE_OBJECT=falseSI_INSTANCE=falseSI_IS_SCHEDULABLE=trueSI_KIND=CrystalReportSI_LAST_RUN_TIME=Fri Feb 18 14:25:09 PST 2005SI_LAST_SUCCESSFUL_INSTANCE_ID=32052SI_NAME=Product CatalogSI_OBJECT_IS_CONTAINER=falseSI_OBTYPE=2SI_OWNER=AdministratorSI_OWNERID=12SI_PARENT_CUID=ARD1V.IRaKdPs3fPUzttR3kSI_PARENT_FOLDER_CUID=ARD1V.IRaKdPs3fPUzttR3kSI_PARENT_FOLDER=6322SI_PARENTID=6322SI_PERSONAL_CATEGORIESSI_PERSONAL_CATEGORIES.SI_TOTAL=0SI_PLUGIN_OBJECT=falseSI_PROGID=CrystalEnterprise.ReportSI_REFRESH_OPTIONS=-2SI_RUID=AaCbu62TlMdDo60E358dydASI_RUNNABLE_OBJECT=falseSI_SENDABLE=trueSI_SYSTEM_OBJECT=falseSI_TABLE=0SI_TOPIC_TOPIC_FOR_SUBJECT_GENERICENTITYSI_TOPIC_TOPIC_FOR_SUBJECT_GENERICENTITY.SI_TOTAL=0SI_TURNONREPOSITORY=falseSI_TURNONTHUMBNAIL=trueSI_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 propertiesSI_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'sSI_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 toSI_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 onSI_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 propertySI_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 forSI_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 thatSI_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 functionfolderBreadCrumbs(String folderID, IInfoStore iStore) found in BOEUtil.java onwww.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 calledidToName(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, andCeScheduleType. 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. TheC 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_PARENTID="+BOEUtil.getObjectByCUID(CeSecurityCUID.RootFolder.FOLDERS,"CI_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 WHERESI_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 asCeSecurityCUID.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 theISecurityInfo.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_ID="+objID); IInfoObject obj=(IInfoObject)objs.get(0); Iterator iter=props.entrySet().iterator(); while (iter.hasNext()){ Object key=(String)iter.next(); obj.properties().setProperty(key,props.get(key)); } iStore.commit(objs);}
Note that custom properties cannot be accessed directly using syntax such asSI_MY_CUSTOM_PROPERTY. To access them you must use the asterix (*) in the SELECT clause when searching for custom properties and then use thegetProperty() 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 usingSELECT TOP N. You can see whether you are looking at all of the records that satisfy your query by comparing theresultInfoObjcts.getResultSize() method to the actual number of records found through theresultInfoObjcts.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
- Querying the InfoStore
- Querying the X$ structures
- Querying the Composition Container
- Querying the Alert Log using External Tables
- XPath Querying Over DataSets with the DataSetNavigator - Arpan Desai
- Querying XML Data Using XPATH Expression and the XML DOM
- 5. Querying
- Querying Metadata
- Querying JSON
- Querying data
- Ado.net Querying the Database for Multiple Result Sets(多数据结果集)
- 【文档摘要】J2EE Persistence - Introduction to the Java Persistence API【Querying Entities】
- Error querying database. Cause: java.sql.SQLException: The user specified as a definer (''@'') doe
- error: SObject row was retrieved via SOQL without querying the requested fiel:
- Ad hoc querying
- rails active record querying
- Spring JdbcTemplate Querying Examples
- Mel Querying UI Widgets
- 类的友函数、友类、继承、多继承
- 两分钟彻底让你明白Android Activity生命周期(图文)!
- [生活大杂烩-2] 人生需要四种修为
- Webview使用总结
- 使用多线程还是用IO复用select/epoll? epoll 或者 kqueue 的原理是什么?
- Querying the InfoStore
- centos6.0下Error: Connection activation failed: Device not managed by NetworkManager解决办法
- 一个小知识点------在Jlabel当中让文字居中显示,及更改字体颜色,大小!
- 逗号和分号
- Documentation/x86/pat.txt
- php global define const static 等关键字的定义
- 【Github】向github推送代码出现error: gnutls_handshake() failed GIT repository错误的解决方案
- Cocos2D-x背景音乐和音效的控制方法
- 实木地板起翘原因及解决措施