| Oracle Internet File System Developer Reference Release 9.0.1.1.0 Part Number A90093-02 |
|
This chapter describes how to apply arbitrary metadata and behavior to content types. The chapter covers the following topics:
The first step in customizing Oracle 9iFS for your business is usually to define all of the physical types of information you wish to store and manage with Oracle 9iFS. Out-of-the-box, Oracle 9iFS manages standard types of information, such as documents and folders. Oracle 9iFS provides out-of-the-box content types (e.g., Document and Folder) that define the physical structure of the information (e.g., Content, Format, Size), and provide interfaces for manipulating the information (e.g., getContent() and listItems()). You can extend these content types to define other physical types of information, such as Image or Book. Chapter 5, "Extending Content Types and Attributes" and Chapter 17, "Customizing Content Type Behavior" discuss how to extend the custom type hierarchy to include attributes and behaviors for different physical types of information.
In defining your business' content types, however, you may find that you also need to manage arbitrary metadata and behaviors that can be applied to your information. The metadata and behaviors are arbitrary in that they may or may not be applied to selected instances of various physical types of information. For example, you might categorize specific instances of different content types into a common metadata structure, such as a subject catalog, according to how they are used in your business. You might define business rules for how certain operations should be performed on various content types, or on specific instances of a content type.
Oracle 9iFS provides the following mechanisms for applying arbitrary metadata and behaviors to your information:
This chapter provides instructions on how to create and apply Categories, PropertyBundles, PolicyPropertyBundles, and Relationships.
Categories allow you to organize information stored in Oracle 9iFS according to how it is used in your business. For example, you might organize your documents, folders, and images according to the projects that they are used for. By virtue of belonging to the category, you can add extra attributes and behaviors that pertain to that category. For example, you might add the attributes Project Name, and Project Record Number to documents and folders that belong to a Project category.
Oracle 9iFS provides a content type, Category, which you can use to create categorization schemes and apply them to your information. Category is a content type that can be extended to define different types of categories (e.g., Project) and the attributes that pertain to that category (e.g., Project Name, Project Record Number).
A document, folder, or any PublicObject can be associated with zero, one, or more categories. A PublicObject is categorized by associating it with an instance of the extended Category content type. The Category instance stores the values for the extra attributes that pertain to the PublicObject by virtue of it belonging to that category (e.g., Project Name = "Content Management Research Project", Project Record Number = "AR1098a"). The Category instance also stores a pointer to the PublicObject in an attribute AssociatedPublicObject.
Since any PublicObject (e.g., document, folder, image) can be associated with the same category types, categories provide a common scheme for organizing different physical types of information. In a way, categories provide a means for cross-inheriting attributes across different content types.
Because the Category content type extends PublicObject, Category instances can be foldered. This may be useful if you are building a custom user interface and wish to represent documents in different ways in different folders. For example, you could create a Project folder that contain all documents pertaining to a project. Rather than foldering the Document instances and listing them by Name, you could folder the Project category instances and list them by the Project Record Number attribute. You could then allow users to access the Document instance by calling the getAssociatedPublicObject() method on the Category instance.
Category instances are not versioned by Oracle 9iFS. If a document's category metadata changes with each version, then each document version can be associated with a new Category instance. However, the version information is maintained on the document, not its categories.
Access to Category instances is determined by the AccessControlList applied to the associated PublicObject. If a user has been granted getAttribute() on the PublicObject, he can access the category attributes as well.
Categories are automatically deleted when the associated PublicObject is freed. No notification will be generated when the Category instances are deleted in this manner.
From this section, you will learn how to:
Defining new types of Category entails the same steps required for defining any custom content type. As for any other content type, you create a set of SchemaObject instances to represent the Category type. You can also define custom behavior for the category type by implementing Java classes. However, implementing custom Java classes is not required to define a new category type. Afterwards, you can modify and delete the category type by editing or deleting its SchemaObjects. These development tasks can be done with the Java API, XML files, or the Oracle 9iFS Manager.
|
NOTE: For detailed instructions on creating, modifying and deleting custom content types, consult Chapter 5, "Extending Content Types and Attributes"and Chapter 17, "Customizing Content Type Behavior". If you have already read these chapters, this section provides quick review how to create, modify and delete category types with Java and XML. |
To create a new type of category, you create a new content type that extends Category and adds attributes that are pertinent to that category. For example, you could create a new category, Project Record, that extends Category and includes the extended attributes Project Name and Project Record Number.
To define the new category type, follow these steps:
See Chapter 17, "Customizing Content Type Behavior" to learn how to extend the category type's Java classes.
NOTE:
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>ProjectRecord</NAME> <SUPERCLASS RefType = "Name">Category</SUPERCLASS> <DESCRIPTION>Public Objects that pertain to a Project.</DESCRIPTION> <ATTRIBUTES> <ATTRIBUTE> <NAME>ProjectName</NAME> <DATATYPE>String</DATATYPE> </ATTRIBUTE> <ATTRIBUTE> <NAME>ProjectRecordNumber</NAME> <DATATYPE>String</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
|
NOTE: For a description of each element in an XML file used to create category types, consult the Chapter 5, "Extending Content Types and Attributes". |
session.setAdministrationMode(true);
ClassObjectDefinition codef = new ClassObjectDefinition(session); codef.setAttributeByUpperCaseName(ClassObject.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("ProjectRecord"));
ClassObject catco = session.getClassObjectByName("CATEGORY"); codef.setSuperclass(catco);
AttributeDefinition attdef1 = new AttributeDefinition(session); attdef1.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("ProjectName")); attdef1.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_STRING)); codef.addAttributeDefinition(attdef1); AttributeDefinition attdef2 = new AttributeDefinition(session); attdef2.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("ProjectRecordNumber")); attdef2.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_STRING)); codef.addAttributeDefinition(attdef2);
ClassObject mycatco = (ClassObject) session.createSchemaObject(codef);
You can add and remove attributes on a category type after it has been created.
session.setAdministrationMode(true);
ClassObject catco = session.getClassObjectByName("PROJECTRECORD");
AttributeDefinition attdef1 = new AttributeDefinition(session); attdef1.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("ProjectPriority")); attdef1.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_INTEGER)); catco.addAttribute(attdef1);
Attribute att2 = catco.getEffectiveClassAttributes("PROJECTRECORDNUMBER"); catco.removeAttribute(att2);
Attribute att3 = catco.getEffectiveClassAttributes("PROJECTPRIORITY"); Collection vdColl = session.getValueDomainCollection(); ValueDomain vd = (ValueDomain) vdColl.getItems("Projects"); att3.setValueDomain(vd);
You can use the Java API or Oracle 9iFS Manager to delete category types. If instances exist for the Category, then they must be removed before you can remove the Category type.
session.setAdministrationMode(true);
ClassObject catco = session.getClassObjectByName("PROJECTRECORD");
catco.free();
Once you have created a new Category type, you can use it to categorize documents, folders, or any PublicObject in Oracle 9iFS. This section describes the following tasks:
To categorize a PublicObject, you create a new instance of your category type and associate it with the PublicObject. You can apply Category instances when creating new PublicObjects, or to PublicObjects that already exist in Oracle 9iFS.
To categorize a PublicObject with the Java API, follow these steps:
CategoryDefinition cdef = new CategoryDefinition(session);
ClassObject co = session.getClassObjectByName("PROJECTRECORD"); cdef.setClassObject(co);
cdef.setAttributeByUpperCaseName(Category.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "Content Management Marketing Analysis Report")); cdef.setAttributeByUpperCaseName("PROJECTNAME", AttributeValue.newAttributeValue("Content Management Research Project")); cdef.setAttributeByUpperCaseName("PROJECTRECORDNUMBER", AttributeValue.newAttributeValue("AR1098a"));
FolderDefinition fdef = new FolderDefinition(session); fdef.setAttributeByUpperCaseName(Folder.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Collateral")); fdef.addCategoryDefinition(cdef); Folder f = (Folder) session.createPublicObject(fdef);
f.addCategory(cdef);
You can also use XML to categorize new PublicObjects. When the XML file is imported into Oracle 9iFS, the IfsSimpleXmlParser automatically parses the file and generate an instance of the category type to hold the category metadata for the PublicObject. The following are the key aspects of an XML file used to categorize a PublicObject:
<?xml version="1.0" standalone="yes"?> <FOLDER> <NAME>CMProject</NAME> <FOLDERPATH>/home/guest</FOLDERPATH> <CATEGORIES> <PROJECTRECORD> <NAME>Content Management Market Analysis</NAME> <PROJECTNAME>Content Management Research Project</PROJECTNAME> </PROJECTRECORD> <!-- You can have multiple Category elements here --> </CATEGORIES> </FOLDER>
|
NOTE: For a detailed overview of the syntax rules for XML configuration files, consult Chapter 10, "XML and the Oracle Internet File System". |
Once you have categorized a PublicObject, you may need to update the values of the attributes applied to it by the Category instance. You can update a PublicObject's category attributes with either XML configuration files or the Java API.
To update a Category instance, the XML file must:
<?xml version="1.0" standalone="yes"?> <PROJECTRECORD> <UPDATE RefType = "Name">Content Management Market Analysis</UPDATE> <PROJECTNAME>XML Research Project</PROJECTNAME> </PROJECTRECORD>
You can also update the values of attributes on Category instances with the Oracle 9iFS Java API. Each extended Category type inherits the methods getAttribute() and setAttribute() from the Category class. These methods provide a generic way to manipulate any attribute value.
You can also implement custom Java classes to provide convenience methods for getting and setting the values for the extended attributes on your custom category type. For instructions on implementing custom Java classes, consult Chapter 17, "Customizing Content Type Behavior".
Category cat = ......
cat.setAttribute("PROJECTPRIORITY", AttributeValue.newAttributeValue(new Integer(3)));
You can remove PublicObjects from a category by deleting the Category instance that holds the PublicObject's category attribute values. When a PublicObject is deleted, all of its categories are automatically deleted by Oracle 9iFS.
You can delete Category instances with the Oracle 9iFS Java API as you would any other object by calling the free() method. Oracle 9iFS does not support XML as a method for removing PublicObjects from a category, nor does the Oracle 9iFS Manager provide a user interface for deleting Category instances.
Selector s = new Selector(session); s.setSearchClassname("PROJECTRECORD"); LibraryObject[] cats = s.getItems(); Category c;
int i; int count = (cats == null) ? 0 : cats.length; for (i = 0; i < count; i++) { c = (Category) cats[i]; c.free(); }
Once you have categorized documents, folders, and other types of information, you can search for the information based on its category and category attributes.
For example, you could search for all documents, folders, and other types of information that are project records for the Content Management Research Project. To do this, you would search for all PublicObjects that have been categorized as a Project Record and that have the category attribute Project Name set to Content Management Research Project.
Oracle 9iFS also provides APIs that make it easy to traverse the association between information and their categories. For example, given a PublicObject instance, you can fetch all associated categories. Conversely, given a category instance, you can fetch the associated PublicObject.
You can build applications that search for PublicObjects based on their category metadata by constructing a Selector or Search with the Oracle 9iFS Java API. To construct the query, the Search or Selector would join the Category and PublicObject content types based on the reference between the AssociatedPublicObject attribute on Category, and the ID attribute on PublicObject. Then, the Search or Selector can include additional criteria about either the Category and/or PublicObject's attributes.
|
NOTE: For detailed instructions on building Selectors and Searches, see Chapter 8, "Building Search Applications". |
PublicObject po = .....
Selector s = new Selector(session); s.setSearchClassname("PROJECTRECORD"); s.setSearchSelection("ASSOCIATEDPUBLICOBJECT = " + po.getId() + " AND PROJECTNAME = 'XML Research Project'");
LibraryObject[] cats = s.getItems(); int i; int count = (cats == null) ? 0 : cats.length; for (i = 0; i < count; i++) { c = (Category) cats[i]; }
AttributeSearchSpecification asp = new AttributeSearchSpecification();
String[] searchClasses = {"PUBLICOBJECT", "PROJECTRECORD"}; SearchClassSpecification scp = new SearchClassSpecification(searchClasses); scp.addResultClass("PUBLICOBJECT"); asp.setSearchClassSpecification(scp);
JoinQualification jq = new JoinQualification(); jq.setLeftAttribute("PUBLICOBJECT", null); jq.setRightAttribute("PROJECTRECORD", "ASSOCIATEDPUBLICOBJECT");
AttributeQualification aq = new AttributeQualification(); aq.setAttribute("PROJECTRECORD", "PROJECTNAME"); aq.setOperatorType(AttributeQualification.EQUAL); aq.setValue("Content Management Research Project");
SearchClause sc = new SearchClause(aq, jq, SearchClause.AND); asp.setSearchQualification(sc);
Search srch = new Search(session, asp); srch.open(); int i; LibraryObject lo; SearchResultObject sro = srch.next(); String lName; while (sro != null) { lo = sro.getLibraryObject(); lName = lo.getName(); try { sro = srch.next(); } catch (IfsException e) { if (e.getErrorCode() == 22000) { break; } else { e.printStackTrace(); } } } srch.close();
The Oracle 9iFS Java API provides methods that make it easy to get the categories for PublicObjects, and the PublicObject associated with a Category instance.
The PublicObject class includes a method, getCategories(), which returns all Category instances that are associated with that PublicObject. Once you have the Category instance, you can retrieve the extra attributes applied to the PublicObject by the category.
PublicObject po = .....
Category[] cats = po.getCategories();
AttributeValue av; // variable to hold value of a category attribute Attribute[] catatts; // variable to hold the Attributes on the Category Category c; // variable to hold each Category instance ClassObject catco; // variable to hold the ClassObject // that represents the category type int i, j, icount, jcount; String catName, attName; // variables to hold the names of //the category and attributes icount = (cats == null) ? 0 : cats.length; for(i=0; i < icount; i++) { c = cats[i]; catco = c.getClassObject(); catName = catco.getName(); catatts = catco.getExtendedClassAttributes(); jcount = (catatts == null) ? 0 : catatts.length; for (j=0; j < jcount; j++) { attName = catatts[j].getName(); av = c.getAttribute(attName); } }
The Category class provides a convenience method, getAssociatedPublicObject(), that returns the PublicObject instance to which the category metadata applies. Once you have the PublicObject instance, you can retrieve all of the other attributes possessed by the PublicObject and call methods to manipulate the PublicObject.
Category cat = ......
PublicObject po = cat.getAssociatedPublicObject();
ClassObject co = po.getClassObject(); Attribute[] atts = co.getEffectiveClassAttributes(); String coName = co.getName(); AttributeValue av; //variable to hold value of a PublicObject's attribute int i, icount; String attName; icount = (atts == null) ? 0 : atts.length; for (i = 0; i < icount; i++) { attName = atts[i].getName(); av = po.getAttribute(attname); }
PropertyBundles are useful for persistently storing a "bag" of properties in Oracle 9iFS.
Compared to categories, PropertyBundles are relatively unstructured. The PropertyBundle consists of a set of Properties, each of which consists of a name/value pair. A PropertyBundle can exist independently in Oracle 9iFS, and be associated with zero, one, or more PublicObjects. PropertyBundles are a more flexible way to store data, but are not as easy to work with as more structured constructs such as categories.
PropertyBundles can be used to store ad-hoc metadata for processing systemwide tasks, one or more content types, or specific instances.
Since PropertyBundles can exist independently in Oracle 9iFS, and are used frequently for application processing, it may be useful to associate the PropertyBundle with a ValueDefault. By associating the PropertyBundle with a ValueDefault, it can be uniquely referenced by a string, the ValueDefault's UniqueName. PropertyBundles do not possess a UniqueName attribute, as do SchemaObjects such as ValueDefault. Although PropertyBundles possess a unique ID, the ID attribute does not provide a convenient way to reference PropertyBundles. ValueDefaults make it convenient to reference PropertyBundles. For example, in an XML configuration file, the UniqueName of the ValueDefault can be supplied as the value for an element referencing the PropertyBundle (e.g., <Update RefType = "ValueDefault">ContentTypeLookupByFileExtension</Update>). The Oracle 9iFS Java API also provides special methods for retrieving objects via a ValueDefault (e.g., LibrarySession.getValueDefaultCollection()).
|
NOTE: To learn more about ValueDefaults, see Chapter 7, "Attribute Validation". |
A PropertyBundle consists of an array of name/value pairs. Each pair is represented by a Property object, which possesses a Name attribute and a Value attribute. The Value attribute can have any datatype supported by Oracle 9iFS (e.g., String, Integer, PublicObject, DirectoryObject_Array). The Property object possesses a third attribute, Bundle, which references the PropertyBundle to which it belongs.
Text description of the illustration pbobmod.gif
All objects in Oracle 9iFS possesses a PropertyBundle attribute. A PublicObject instance can use the inherited attribute to associate a PropertyBundle that is used to process a specific content type instance. A ClassObject instance can use the inherited attribute to associate a PropertyBundle that is used to process all instances of the content type that ClassObject represents.
The Oracle 9iFS SDK supports two methods to define PropertyBundles:
You can use XML files to define PropertyBundles in Oracle 9iFS. When the XML file is imported into Oracle 9iFS, the IfsSimpleXmlParser automatically uses it to create or modify a PropertyBundle instance. Oracle 9iFS does not support deleting PropertyBundles using XML.
It is recommended that a ValueDefault be created for each PropertyBundle so that the PropertyBundle can be referenced uniquely by a string. The following examples illustrate how to use XML to create PropertyBundle and ValueDefault in an XML file using the <OBJECTLIST> tag, and how to use a ValueDefault to update a PropertyBundle with an XML file.
<?xml version='1.0' standalone='yes'?> <OBJECTLIST> <PROPERTYBUNDLE> <NAME>Title Translation PropertyBundle</NAME> <PROPERTIES> <PROPERTY> <NAME>English</NAME> <VALUE>Guide</VALUE> </PROPERTY> <PROPERTY> <NAME>Italian</NAME> <VALUE>Guida</VALUE> </PROPERTY> </PROPERTIES> </PROPERTYBUNDLE> <VALUEDEFAULT> <NAME>TranslatedTitleValueDefault</NAME> <VDVALUE Datatype="PublicObject" ClassName = "PropertyBundle" RefType = "Name"> Title Translation PropertyBundle </VDVALUE> </VALUEDEFAULT> </OBJECTLIST>
<?xml version='1.0' standalone='yes'?> <PROPERTYBUNDLE> <UPDATE RefType='ValueDefault'>TranslatedTitleValueDefault</UPDATE> <PROPERTIES> <PROPERTY Action = 'add'> <NAME> Spanish </NAME> <VALUE DataType = 'String'> Guida </VALUE> </PROPERTY> <PROPERTY Action = 'Remove'> <NAME> Italian </NAME> </PROPERTY> <PROPERTY Action = 'Add'> <NAME> English </NAME> <VALUE DataType = 'String'> Manual </VALUE> </PROPERTY> </PROPERTIES> </PROPERTYBUNDLE>
Each element in the XML configuration file is used to specify the value for the attributes of the PropertyBundle and Property instances.
|
NOTE: For a detailed description of the syntax rules for XML configuration files, consult Chapter 10, "XML and the Oracle Internet File System". |
Table 6-1 lists each of the XML elements in a PropertyBundle configuration file. The table specifies the Java class and attribute in the Oracle 9iFS Java API that corresponds to the element, how the element is used, and any valid XML attributes for the element.
The Oracle 9iFS Java API provides a more robust interface for manipulating PropertyBundles. The Java API includes a set of classes, PropertyBundle and Property, that possess methods for manipulating ad-hoc data stored in PropertyBundles. The following examples illustrate how to create, modify and delete PropertyBundles with the Java API.
It is recommended that a ValueDefault be created for each PropertyBundle so that the PropertyBundle can be referenced uniquely by a string. The following examples also illustrate how to create a ValueDefault for a new PropertyBundle, and use the ValueDefault to access the PropertyBundle.
PropertyBundleDefinition pbdef = new PropertyBundleDefinition(session); pbdef.setAttribute(PropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Title Translation PropertyBundle"));
pbdef.addPropertyValue("English", AttributeValue.newAttributeValue("Guide"));
PropertyDefinition pd = new PropertyDefinition(session); pd.setName("Italian"); pd.setValue(AttributeValue.newAttributeValue("Guida")); pbdef.addPropertyDefinition(pd);
PropertyBundle pb = (PropertyBundle) session.createPublicObject(pbdef);
ValueDefaultPropertyBundleDefinition vdpbd = new ValueDefaultPropertyBundleDefinition(session); vdpbd.setAttributeByUpperCaseName(ValueDefaultPropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "TranslatedTitleValueDefaultPropertyBundle")); vdpbd.setValue(pb); ValueDefaultPropertyBundle vdpb = (ValueDefaultPropertyBundle) session.createPublicObject(vdpbd);
session.setAdministrationMode(true); ValueDefaultDefinition vdd = new ValueDefaultDefinition(session); vdd.setAttributeByUpperCaseName(ValueDefault.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "TranslatedTitleValueDefault")); ValueDefault vd = (ValueDefault) session.createSchemaObject(vdd); vd.setValueDefaultPropertyBundle(vdpb);
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("TranslatedTitleValueDefault"); AttributeValue av = vd.getPropertyValue(); PropertyBundle pb = (PropertyBundle) av.getPublicObject(session);
pb.putPropertyValue("Spanish", AttributeValue.newAttributeValue("Guida"));
pb.removePropertyValue("Italian");
pb.putPropertyValue("English", AttributeValue.newAttributeValue("Manual"));
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("TranslatedTitleValueDefault"); AttributeValue av = vd.getPropertyValue(); PropertyBundle pb = (PropertyBundle) av.getPublicObject(session);
session.setAdministrationMode(true); vd.free();
pb.free();
PropertyBundles exist independently in Oracle 9iFS, and do not have to be associated with any other PublicObject to be used by an application. However, you may want to associate a PropertyBundle with one or more content types, or specific instances of a content type.
Every content type and instance in Oracle 9iFS possesses a PropertyBundle attribute that can reference the PropertyBundle that applies extra metadata to it. To associate a PropertyBundle with a content type, you would set the value of the PropertyBundle attribute on the ClassObject instance that represents that content type. To associate a PropertyBundle with a document, you would set the value of the PropertyBundle attribute on the Document instance to reference the PropertyBundle. To disassociate a PropertyBundle from a content type or instance, you would set the PropertyBundle attribute to NULL.
Oracle 9iFS allows you to use either XML configuration files or the Java API to apply PropertyBundles to content types and instances. The following sections illustrate how.
You can use XML configuration files to apply PropertyBundles to content types and instances at any time:
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>Image</NAME> <SUPERCLASS RefType = "Name">Document</SUPERCLASS> <PROPERTYBUNDLE> <NAME>Title Translation PropertyBundle</NAME> <PROPERTIES> <PROPERTY> <NAME>English</NAME> <VALUE>Guide</VALUE> </PROPERTY> <PROPERTY> <NAME>Italian</NAME> <VALUE>Guida</VALUE> </PROPERTY> </PROPERTIES> </PROPERTYBUNDLE> <ATTRIBUTES> <ATTRIBUTE> <NAME>Artists</NAME> <DATATYPE>Integer</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>Image</NAME> <SUPERCLASS RefType = "Name">Document</SUPERCLASS> <PROPERTYBUNDLE RefType = "ValueDefault"> TranslatedTitleValueDefault </PROPERTYBUNDLE> <ATTRIBUTES> <ATTRIBUTE> <NAME>Artists</NAME> <DATATYPE>Integer</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <UPDATE RefType = "Name">IMAGE</UPDATE> <PROPERTYBUNDLE RefType = "ValueDefault"> TranslatedTitleValueDefault </PROPERTYBUNDLE> </CLASSOBJECT>
<?xml version="1.0" standalone="yes"?> <FOLDER> <NAME>Collateral</NAME> <PROPERTYBUNDLE RefType = "ValueDefault"> TranslatedTitleValueDefault </PROPERTYBUNDLE> </FOLDER>
<?xml version="1.0" standalone="yes"?> <FOLDER> <UPDATE RefType = "Path">/home/guest/Collateral</UPDATE> <PROPERTYBUNDLE RefType = "ValueDefault"> TranslatedTitleValueDefault </PROPERTYBUNDLE> </FOLDER>
The Java API gives you greater control over how PropertyBundles are applied to content types and instances. For example, you might want to programmatically apply a PropertyBundle if the instance meets certain criteria. Or, you might want to create a PolicyPropertyBundle and PublicObject in a single transaction, to ensure that neither are created if either cannot.
|
NOTE: For instructions on managing transactions in Oracle 9iFS, see Chapter 16, "Managing Sessions and Transactions". |
PropertyBundleDefinition pbDef = new PropertyBundleDefinition(session); pbDef.setAttributeByUpperCaseName(PropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Title Translation PropertyBundle")); pbDef.addPropertyValue("English", AttributeValue.newAttributeValue("Guide")); pbDef.addPropertyValue("Italian", AttributeValue.newAttributeValue("Guida")); PropertyBundle pb = (PropertyBundle) session.createPublicObject(pbDef);
session.setAdministrationMode(true); ClassObjectDefinition coDef = new ClassObjectDefinition(session); coDef.setAttributeByUpperCaseName(ClassObject.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("IMAGE")); ClassObject superClass = session.getClassObjectByName("DOCUMENT"); coDef.setSuperclass(superClass);
coDef.setAttributeByUpperCaseName(ClassObject.PROPERTYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(pb)); ClassObject classObj = (ClassObject) session.createSchemaObject(coDef);
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("TranslatedTitleValueDefault"); AttributeValue av = vd.getPropertyValue(); PropertyBundle pb = (PropertyBundle) av.getPublicObject(session);
ClassObject co = session.getClassObjectByName("IMAGE");
session.setAdministrationMode(true); co.setAttribute(ClassObject.PROPERTYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(pb));
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("TranslatedTitleValueDefault"); AttributeValue av = vd.getPropertyValue(); PropertyBundle pb = (PropertyBundle) av.getPublicObject(session); FolderDefinition fd = new FolderDefinition(session); fd.setAttributeByUpperCaseName(Folder.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Collateral")); fd.setAttributeByUpperCaseName(Folder.PROPERTYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(pb)); Folder f = (Folder) session.createPublicObject(fd);
You can use the Oracle 9iFS Java API to search for information based on PropertyBundle criteria. For example, you might search for all Properties that pertain to the file extension 'ppt'. You can build an application that queries for Properties based on their data by constructing a Selector with the Oracle 9iFS Java API.
Or, you might fetch all PublicObjects that have a Property named English whose value is Guide. You can use the Oracle 9iFS Java API to query for PublicObjects based on their PropertyBundles. To construct the query, the Search would include a PropertyQualification that joins the Property and PublicObject content types, and includes the additional criteria about the Property.
|
NOTE: For detailed instructions on building Selectors and Searches, consult Chapter 8, "Building Search Applications". |
session.setAdministrationMode(true);
Selector s = new Selector(session); s.setSearchClassname("PROPERTY"); s.setSearchSelection("NAME = 'ppt'");
LibraryObject[] props = s.getItems(); Property p; int count = (props == null) ? 0 : props.length; for (i = 0; i < count; i++) { p = (Property) props[i]; }
AttributeSearchSpecification asp = new AttributeSearchSpecification();
String[] searchClasses = {"PUBLICOBJECT"}; SearchClassSpecification scp = new SearchClassSpecification(searchClasses); scp.addResultClass("PUBLICOBJECT"); asp.setSearchClassSpecification(scp);
PropertyQualification pq = new PropertyQualification(); pq.setClassname("PUBLICOBJECT"); pq.setPropertyName("English"); pq.setOperatorType(AttributeQualification.EQUAL); pq.setValue(AttributeValue.newAttributeValue("Guide")); pq.setCaseIgnored(true); asp.setSearchQualification(pq);
Search srch = new Search(session, asp); srch.open(); SearchResultObject sro = srch.next(); LibraryObject lo; while (sro != null) { lo = sro.getLibraryObject(); try { sro = srch.next(); } catch ( IfsException e) { if (e.getErrorCode() == 22000) { break; } else { e.printStackTrace(); } } } srch.close();
PolicyPropertyBundles provide a means to define policies, or business rules, for how certain operations are performed by an application. The logic for the business rule is implemented in a custom Java class. A policy is then defined to indicate that the business rule should be performed whenever a specific operation is called. A set of policies can be bundled together and associated with one or more content types or instances to hold all policies for how operations are performed on those objects. Subsequently, when an application tries to perform an operation, it can reference the PolicyPropertyBundle to determine if a policy has been defined for that operation. If a policy has been defined, the application can retrieve the Java class that implements the business rule and use it to perform the operation.
For example, Oracle 9iFS uses PolicyPropertyBundles to implement its Rendering framework. The Rendering framework provides an easy way for developers to plug-in renderers, which are automatically called by Oracle 9iFS to render instances of content types when fetched from different protocols. For example, the developer could configure Oracle 9iFS to render VCard instances in XML when fetched via FTP, and in VCard format when fetched via SMB. To configure the renderer, the developer creates a policy in the VCard content type's PolicyPropertyBundle. The Policy associates an operation named 'FtpContentRenderer' with the fully qualified name of the XML renderer that the developer wishes to use (e.g., 'MyApplication.Renderers.MyXMLRenderer'). Subsequently, when an instance of the content type is fetched, each protocol server is programmed to call a specific operation name. The Oracle 9iFS server references the PolicyPropertyBundle associated with the instance's content type to determine if a renderer has been associated with the operation specified. If it has, Oracle 9iFS retrieves the fully qualified name of the renderer, passes the instance to the renderer to be processed, and then passes the results to the protocol server.
PolicyPropertyBundles can be used to store policies used to perform systemwide tasks, operations on all instances of a content type, or operations on a specific instance.
Since PolicyPropertyBundles can exist independently in Oracle 9iFS, and are used frequently for application processing, it may be useful to associate the PolicyPropertyBundle with a ValueDefault. By associating the PolicyPropertyBundle with a ValueDefault, it can be uniquely referenced by a string, the ValueDefault's UniqueName. For example, in an XML configuration file, the UniqueName of the ValueDefault can be supplied as the value for an element referencing the PolicyPropertyBundle (e.g., <Update RefType = "ValueDefault">MyPolicyPropertyBundleValueDefault</Update>). The Oracle 9iFS Java API also provides a special methods for retrieving objects via a ValueDefault (e.g., LibrarySession.getValueDefaultCollection()).
Each policy for an operation is defined in Oracle 9iFS as an instance of the Policy content type. Policy possesses attributes for storing the operation to which the policy applies, the fully qualified name of the Java bean that implements the behavior of the policy, and an enumerated key to identify the policy.
Policies are bundled together by a PolicyPropertyBundle instance. The PolicyPropertyBundle content type extends the PropertyBundle content type. Therefore, it has the same structure as a PropertyBundle. However, in this case, the value of a Property in the PropertyBundle references a Policy.
|
NOTE: For a description of the structure of PropertyBundles, see "PropertyBundles". |
The top-level content type in Oracle 9iFS, LibraryObject, possesses a PolicyBundle attribute. This attribute is inherited by all Oracle 9iFS content types. A ClassObject instance can use the inherited attribute to associate a PolicyPropertyBundle that is used to process all instances of the content type that the ClassObject represents. A PublicObject instance can use the inherited attribute to associate a PolicyPropertyBundle that is used to define policies for operations on that specific instance.
To implement policies for how operations are performed by a custom application, you need to define the following:
This section provides instructions on defining PolicyPropertyBundles that associate Java classes with custom operations. It does not discuss how to build the Java classes that implement the policy behavior or custom application logic since these are unique to your application. Oracle 9iFS places no special requirements on creating these Java classes.
Oracle 9iFS SDK supports several methods to define PolicyPropertyBundles:
You can use XML files to define PolicyPropertyBundles in Oracle 9iFS. When the XML file is imported into Oracle 9iFS, the IfsSimpleXmlParser automatically uses it to create or modify a PolicyPropertyBundle instance. Oracle 9iFS does not support deleting PolicyPropertyBundles using XML.
It is recommended that a ValueDefault be created for each PolicyPropertyBundle so that the PolicyPropertyBundle can be referenced uniquely by a string. The following examples illustrate how to use XML to create PolicyPropertyBundle and ValueDefault in an XML file using the <OBJECTLIST> tag, and how to use a ValueDefault to update a PolicyPropertyBundle with an XML file.
<?xml version='1.0' standalone='yes'?> <OBJECTLIST> <POLICYPROPERTYBUNDLE> <NAME>Delivery Policies PolicyPropertyBundle</NAME> <POLICIES> <PROPERTY> <NAME>Fax</NAME> <VALUE Datatype="SystemObject" ClassName="Policy"> <NAME>FaxPolicy</NAME> <OPERATION>SendByFax</OPERATION> <IMPLEMENTATIONNAME> MyCompany.MyApp.DeliveryServers.FaxServer </IMPLEMENTATIONNAME> <IMPLEMENTATIONENUM>1</IMPLEMENTATIONENUM> </VALUE> </PROPERTY> <PROPERTY> <NAME>Print</NAME> <VALUE Datatype="SystemObject" ClassName="Policy"> <NAME>PrintPolicy</NAME> <OPERATION>SendByPrinter</OPERATION> <IMPLEMENTATIONNAME> MyCompany.MyApp.DeliveryServers.PrintServer </IMPLEMENTATIONNAME> <IMPLEMENTATIONENUM>2</IMPLEMENTATIONENUM> </VALUE> </PROPERTY> </POLICIES> </POLICYPROPERTYBUNDLE> <VALUEDEFAULT> <NAME>DeliveryPoliciesValueDefault</NAME> <VDVALUE Datatype="PublicObject" ClassName = "PolicyPropertyBundle" RefType = "Name"> Delivery Policies PolicyPropertyBundle </VDVALUE> </VALUEDEFAULT> </OBJECTLIST>
<?xml version='1.0' standalone='yes'?> <POLICYPROPERTYBUNDLE> <UPDATE RefType='ValueDefault'>DeliveryPoliciesValueDefault</UPDATE> <POLICIES> <PROPERTY Action = 'add'> <NAME>Mail</NAME> <VALUE Datatype = 'SystemObject' ClassName="Policy"> <NAME>MailPolicy</NAME> <OPERATION>SendByMail</OPERATION> <IMPLEMENTATIONNAME> MyCompany.MyApp.DeliveryServers.MailServer </IMPLEMENTATIONNAME> <IMPLEMENTATIONENUM>2</IMPLEMENTATIONENUM> </VALUE> </PROPERTY> </POLICIES> </POLICYPROPERTYBUNDLE>
<?xml version='1.0' standalone='yes'?> <POLICYPROPERTYBUNDLE> <UPDATE RefType='ValueDefault'>DeliveryPoliciesValueDefault</UPDATE> <POLICIES> <PROPERTY Action = 'remove'> <NAME>Fax</NAME> </PROPERTY> </POLICIES> </POLICYPROPERTYBUNDLE>
<?xml version='1.0' standalone='yes'?> <POLICY> <UPDATE RefType = "Name">MailPolicy</UPDATE> <IMPLEMENTATIONENUM>1</IMPLEMENTATIONENUM> </POLICY>
Each element in the XML configuration file is used to specify the value for the attributes of the PolicyPropertyBundle and Policy instances.
Table 6-3 lists each of the XML elements in a PolicyPropertyBundle configuration file. The table specifies the Java class and attribute in the Oracle 9iFS Java API that corresponds to the element, how the element is used, and any valid XML attributes for the element.
You can also use the Oracle 9iFS Java API to define PolicyPropertyBundles. The Java APIs provide methods for manipulating the operation and policy implementation class defined in each policy.
session.setAdministrationMode(true);
PolicyDefinition poldef = new PolicyDefinition(session); poldef.setAttributeByUpperCaseName(Policy.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("FaxPolicy")); poldef.setAttributeByUpperCaseName(Policy.OPERATION_ATTRIBUTE, AttributeValue.newAttributeValue("SendByFax")); poldef.setAttributeByUpperCaseName(Policy.IMPLEMENTATIONNAME_ATTRIBUTE, AttributeValue.newAttributeValue( "MyCompany.MyApp.DeliveryServers.FaxServer")); Policy pol1 = (Policy) session.createSystemObject(poldef); poldef.setAttributeByUpperCaseName(Policy.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("PrintPolicy")); poldef.setAttributeByUpperCaseName(Policy.OPERATION_ATTRIBUTE, AttributeValue.newAttributeValue("SendByPrinter")); poldef.setAttributeByUpperCaseName(Policy.IMPLEMENTATIONNAME_ATTRIBUTE, AttributeValue.newAttributeValue( "MyCompany.MyApp.DeliveryServers.PrintServer")); Policy pol2 = (Policy) session.createSystemObject(poldef);
PolicyPropertyBundleDefinition ppbdef = new PolicyPropertyBundleDefinition(session); ppbdef.setAttributeByUpperCaseName(PolicyPropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Delivery Policies PolicyPropertyBundle")); ppbdef.addPropertyValue("Fax", AttributeValue.newAttributeValue(pol1)); ppbdef.addPropertyValue("Print", AttributeValue.newAttributeValue(pol2));
PolicyPropertyBundle ppb = (PolicyPropertyBundle) session.createPublicObject(ppbdef);
ValueDefaultPropertyBundleDefinition vdpbd = new ValueDefaultPropertyBundleDefinition(session); vdpbd.setAttributeByUpperCaseName(ValueDefaultPropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "DeliveryPoliciesValueDefaultPropertyBundle")); vdpbd.setValue(ppb); ValueDefaultPropertyBundle vdpb = (ValueDefaultPropertyBundle) session.createPublicObject(vdpbd);
ValueDefaultDefinition vdd = new ValueDefaultDefinition(session); vdd.setAttributeByUpperCaseName(ValueDefault.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "DeliveryPoliciesValueDefault")); ValueDefault vd = (ValueDefault) session.createSchemaObject(vdd); vd.setValueDefaultPropertyBundle(vdpb);
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault)vdColl.getItems("DeliveryPoliciesValueDefault"); AttributeValue av = vd.getPropertyValue(); PolicyPropertyBundle ppb = (PolicyPropertyBundle) av.getPublicObject(session);
PolicyDefinition poldef = new PolicyDefinition(session); poldef.setAttributeByUpperCaseName(Policy.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("MailPolicy")); poldef.setAttributeByUpperCaseName(Policy.OPERATION_ATTRIBUTE, AttributeValue.newAttributeValue("SendByMail")); poldef.setAttributeByUpperCaseName(Policy.IMPLEMENTATIONNAME_ATTRIBUTE, AttributeValue.newAttributeValue( "MyCompany.MyApp.DeliveryServers.MailServer")); Policy pol = session.createSystemObject(poldef); ppb.putPropertyValue("Spanish", AttributeValue.newAttributeValue(pol));
ppb.removePropertyValue("Fax");
AttributeValue av = ppb.getPropertyValue("Mail"); Policy pol = (Policy) av.getSystemObject(session); pol.setImplementationEnum(1);
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("DeliveryPoliciesValueDefault"); ValueDefaultPropertyBundle vdpb = vd.getValueDefaultPropertyBundle(); AttributeValue av = vd.getPropertyValue(); PolicyPropertyBundle ppb = (PolicyPropertyBundle) av.getPublicObject(session);
Property[] props = ppb.getProperties(); int count = (props == null) ? 0 : props.length;
session.setAdministrationMode(true); int i; Policy p; for (i = 0; i < count; i++) { p = (Policy) props[i].getValue().getSystemObject(session); p.free(); }
ppb.free();
vd.free(); vdpb.free();
PolicyPropertyBundles exist independently in Oracle 9iFS, and do not have to be associated with any other PublicObject to be used by an application. However, you can associate a PolicyPropertyBundle with one or more content types, or specific instances of a content type, to define custom policies for operations performed specifically on these objects.
Every content type and instance in Oracle 9iFS possesses a PolicyBundle attribute, which can reference the PolicyPropertyBundle. To associate a PolicyPropertyBundle with a content type, you would set the value of the PolicyBundle attribute on the ClassObject instance that represents that content type. To associate a PolicyPropertyBundle with a document, you set the value of the PolicyBundle attribute on the Document instance to reference the PolicyPropertyBundle. To disassociate a PolicyPropertyBundle from a content type or instance, you set the PolicyBundle attribute to NULL.
Oracle 9iFS allows you to use either XML configuration files or the Java API to apply PolicyPropertyBundles to content types and instances.
You can use XML configuration files to apply PolicyPropertyBundles to content types and instances at any time:
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>Image</NAME> <SUPERCLASS RefType = "Name">Document</SUPERCLASS> <POLICYBUNDLE> <NAME>Delivery Policies PolicyPropertyBundle</NAME> <POLICIES> <PROPERTY> <NAME>Fax</NAME> <VALUE Datatype="SystemObject" ClassName="Policy"> <NAME>FaxPolicy</NAME> <OPERATION>SendByFax</OPERATION> <IMPLEMENTATIONNAME> MyCompany.MyApp.DeliveryServers.FaxServer </IMPLEMENTATIONNAME> <IMPLEMENTATIONENUM>1</IMPLEMENTATIONENUM> </VALUE> </PROPERTY> <PROPERTY> <NAME>Print</NAME> <VALUE Datatype="SystemObject" ClassName="Policy"> <NAME>PrintPolicy</NAME> <OPERATION>SendByPrinter</OPERATION> <IMPLEMENTATIONNAME> MyCompany.MyApp.DeliveryServers.PrintServer </IMPLEMENTATIONNAME> <IMPLEMENTATIONENUM>2</IMPLEMENTATIONENUM> </VALUE> </PROPERTY> </POLICIES> </POLICYBUNDLE> <ATTRIBUTES> <ATTRIBUTE> <NAME>Artists</NAME> <DATATYPE>DirectoryObject_Array</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>Image</NAME> <SUPERCLASS RefType = "Name">Document</SUPERCLASS> <POLICYBUNDLE RefType = "ValueDefault"> DeliveryPoliciesValueDefault </POLICYBUNDLE> <ATTRIBUTES> <ATTRIBUTE> <NAME>Artists</NAME> <DATATYPE>DirectoryObject_Array</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <UPDATE RefType = "Name">IMAGE</UPDATE> <POLICYBUNDLE RefType = "ValueDefault"> DeliveryPoliciesValueDefault </POLICYBUNDLE> </CLASSOBJECT>
The Java API gives you greater control over how PolicyPropertyBundles are applied to content types and instances. For example, you might want to programmatically apply a PolicyPropertyBundle if the instance meets certain criteria. Or, you might want to create a PolicyPropertyBundle and PublicObject in a single transaction, to ensure that neither are created if either cannot.
|
NOTE: For instructions on managing transactions in Oracle 9iFS, see Chapter 16, "Managing Sessions and Transactions". |
PolicyDefinition poldef = new PolicyDefinition(session); poldef.setAttributeByUpperCaseName(Policy.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("FaxPolicy")); poldef.setAttributeByUpperCaseName(Policy.OPERATION_ATTRIBUTE, AttributeValue.newAttributeValue("SendByFax")); poldef.setAttributeByUpperCaseName(Policy.IMPLEMENTATIONNAME_ATTRIBUTE, AttributeValue.newAttributeValue( "MyCompany.MyApp.DeliveryServers.FaxServer")); Policy pol1 = (Policy) session.createSystemObject(poldef); poldef.setAttributeByUpperCaseName(Policy.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("PrintPolicy")); poldef.setAttributeByUpperCaseName(Policy.OPERATION_ATTRIBUTE, AttributeValue.newAttributeValue("SendByPrinter")); poldef.setAttributeByUpperCaseName(Policy.IMPLEMENTATIONNAME_ATTRIBUTE, AttributeValue.newAttributeValue( "MyCompany.MyApp.DeliveryServers.PrintServer")); Policy pol2 = (Policy) session.createSystemObject(poldef);
PolicyPropertyBundleDefinition ppbdef = new PolicyPropertyBundleDefinition(session); ppbdef.setAttributeByUpperCaseName(PolicyPropertyBundle.NAME_ATTRIBUTE, AttributeValue.newAttributeValue( "Delivery Policies PolicyPropertyBundle")); ppbdef.addPropertyValue("Fax", AttributeValue.newAttributeValue(pol1)); ppbdef.addPropertyValue("Print", AttributeValue.newAttributeValue(pol2));
PolicyPropertyBundle ppb = (PolicyPropertyBundle) session.createPublicObject(ppbdef);
ClassObjectDefinition codef = new ClassObjectDefinition(session); codef.setAttributeByUpperCaseName(ClassObject.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("IMAGE")); ClassObject superClass = session.getClassObjectByName("DOCUMENT"); codef.setSuperclass(superClass);
codef.setAttributeByUpperCaseName(ClassObject.POLICYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(ppb)); ClassObject classObj = (ClassObject) session.createSchemaObject(codef);
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("DeliveryPoliciesValueDefault"); AttributeValue av = vd.getPropertyValue(); PolicyPropertyBundle ppb = (PolicyPropertyBundle) av.getPublicObject(session);
ClassObject co = session.getClassObjectByName("IMAGE");
session.setAdministrationMode(true); co.setAttribute(ClassObject.POLICYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(ppb));
Collection vdColl = session.getValueDefaultCollection(); ValueDefault vd = (ValueDefault) vdColl.getItems("DeliveryPoliciesValueDefault"); AttributeValue av = vd.getPropertyValue(); PolicyPropertyBundle ppb = (PolicyPropertyBundle) av.getPublicObject(session); FolderDefinition fd = new FolderDefinition(session); fd.setAttributeByUpperCaseName(Folder.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("Collateral")); fd.setAttributeByUpperCaseName(Folder.POLICYBUNDLE_ATTRIBUTE, AttributeValue.newAttributeValue(ppb)); Folder f = (Folder) session.createPublicObject(fd);
Oracle 9iFS not only allows you to manage documents, folders, and other types of information, it allows you to manage the associations between them. Oracle 9iFS provides three methods for associating objects:
See Chapter 5, "Extending Content Types and Attributes" to learn more about defining working with Attributes.
NOTE:
See "PropertyBundles" to learn more about working with PropertyBundles.
NOTE:
You can use Relationships to model complex types of information, such as compound documents. Compound documents are comprised of multiple components, which can be reused in multiple compound documents. Different types of compound documents can use different methods for managing the relationships between the components, including OLE, Hurls, and proprietary definition files (i.e., FrameMaker .bk files). You can define custom types of relationships that possess the attributes and methods required to manage different types of compound documents.
Defining new types of relationships entails the same steps required for defining any custom content type. As for any other content type, you create a set of SchemaObject instances to represent the relationship type. You can also define custom behavior for the relationship type by implementing Java classes. However, implementing custom Java classes is not required to define a new relationship type. Afterward, you can modify and delete the relationship type by editing or deleting its SchemaObjects. These development tasks can be done with the Java API, XML files, or Oracle 9iFS Manager.
|
NOTE: For detailed instructions on creating, modifying, and deleting custom content types, see Chapter 5, "Extending Content Types and Attributes" and Chapter 17, "Customizing Content Type Behavior". If you have already read these chapters, this section provides quick review how to create, modify, and delete relationship types with Java and XML. |
To create a new type of relationship, you create a new content type that extends Relationship and adds attributes and methods that are required for managing that type of association. For example, you could create a new relationship, BookRelationship, that extends Relationship and includes the extended attribute ComponentLabel.
To define the new relationship type, follow these steps:
See the Chapter 17, "Customizing Content Type Behavior" to learn how to extend the relationship type's Java classes.
NOTE:
<?xml version="1.0" standalone="yes"?> <CLASSOBJECT> <NAME>BookRelationship</NAME> <SUPERCLASS RefType = "Name">Relationship</SUPERCLASS> <DESCRIPTION>Relationships between a Book and its components.</DESCRIPTION> <ATTRIBUTES> <ATTRIBUTE> <NAME>ComponentLabel</NAME> <DATATYPE>String</DATATYPE> </ATTRIBUTE> </ATTRIBUTES> </CLASSOBJECT>
|
NOTE: For a description of each element in an XML file used to create relationship types, see Chapter 5, "Extending Content Types and Attributes" |
session.setAdministrationMode(true);
ClassObjectDefinition codef = new ClassObjectDefinition(session); codef.setAttributeByUpperCaseName(ClassObject.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("BookRelationship"));
ClassObject catco = session.getClassObjectByName("RELATIONSHIP"); codef.setSuperclass(catco);
AttributeDefinition attdef1 = new AttributeDefinition(session); attdef1.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("ComponentLabel")); attdef1.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_STRING)); codef.addAttributeDefinition(attdef1); AttributeDefinition attdef2 = new AttributeDefinition(session); attdef2.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("FullPath")); attdef2.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_STRING)); codef.addAttributeDefinition(attdef2);
ClassObject co = (ClassObject) session.createSchemaObject(codef);
You can add and remove attributes on a relationship type after it has been created.
session.setAdministrationMode(true);
ClassObject relco = session.getClassObjectByName("BOOKRELATIONSHIP");
AttributeDefinition attdef1 = new AttributeDefinition(session); attdef1.setAttributeByUpperCaseName(Attribute.NAME_ATTRIBUTE, AttributeValue.newAttributeValue("RelativePath")); attdef1.setAttributeByUpperCaseName(Attribute.DATATYPE_ATTRIBUTE, AttributeValue.newAttributeValue(Attribute.ATTRIBUTEDATATYPE_STRING)); relco.addAttribute(attdef1);
Attribute att2 = catco.getEffectiveClassAttributes("FULLPATH"); relco.removeAttribute(att2);
Attribute att3 = catco.getEffectiveClassAttributes("COMPONENTLABEL"); Collection vdColl = session.getValueDomainCollection(); ValueDomain vd = vdColl.getItems("ComponentLabelValueDomain"); att3.setValueDomain(vd);
You can use the Java API or Oracle 9iFS Manager to delete relationship types. If instances exist for the relationship type, they must be removed before it can be removed.
session.setAdministrationMode(true);
ClassObject relco = session.getClassObjectByName("BOOKRELATIONSHIP");
relco.free();
Once you have created a new relationship type, you can use it to relate two PublicObjects. This section describes the following tasks:
To relate two PublicObjects, you create a new instance of your relationship type.
To relate two PublicObjects with the Java API, follow these steps:
PublicObject po1 = ..... PublicObject po2 = .....
RelationshipDefinition rdef = new RelationshipDefinition(session);
ClassObject co = session.getClassObjectByName("BOOKRELATIONSHIP"); rdef.setClassObject(co);
rdef.setAttributeByUpperCaseName(Relationship.LEFTOBJECT_ATTRIBUTE, AttributeValue.newAttributeValue(po1)); rdef.setAttributeByUpperCaseName(Relationship.RIGHTOBJECT_ATTRIBUTE, AttributeValue.newAttributeValue(po2));
rdef.setAttributeByUpperCaseName("COMPONENTLABEL", AttributeValue.newAttributeValue("Chapter 1"));
Relationship r = (Relationship) session.createSystemObject(rdef);
Administrators can also use XML to relate PublicObjects. When the XML file is imported into Oracle 9iFS, the IfsSimpleXmlParser automatically parses the file and generate an instance of the relationship type. The following are the key aspects of an XML file used to relate PublicObjects:
<?xml version="1.0" standalone="yes"?> <BOOKRELATIONSHIP> <LEFTOBJECT RefType = "Path">/home/guest/Manuals/UserGuide.bk</LEFTOBJECT> <RIGHTOBJECT RefType = "Path"> /home/guest/Manuals/UserAdmin.fm </RIGHTOBJECT> <COMPONENTLABEL>Chapter 1 : User Administration</COMPONENTLABEL> </BOOKRELATIONSHIP>
If you use an XML file to create new PublicObjects, you can relate the PublicObject in the same XML file. To do so, the element containing the new PublicObject's data must be specified first in the XML file. Then, an element containing the relationship data can follow, referencing the PublicObject instances created by the preceding elements. Oracle 9iFS creates the instances for each element sequentially, first the PublicObjects, then the relationship instance. For this reason, the element representing the relationship instance can reference the PublicObjects as if they already exist.
<?xml version="1.0" standalone="yes"?> <OBJECTLIST> <FEATURE> <NAME>Oracle 9iFS</NAME> <FOLDERPATH>/public/features</FOLDERPATH> </FEATURE> <PRODUCT> <NAME>Oracle9i Database Server</NAME> <FOLDERPATH>/public/products</FOLDERPATH> </PRODUCT> <PRODUCT> <NAME>Oracle9i Application Server</NAME> <FOLDERPATH>/public/products</FOLDERPATH> </PRODUCT> <PRODUCTFEATURERELATIONSHIP> <LEFTOBJECT RefType = "Path">/public/products/Oracle9i Application Server </LEFTOBJECT> <RIGHTOBJECT RefType = "Path">/public/features/Oracle 9iFS </RIGHTOBJECT> <PRICE>No additional charge.</PRICE> </PRODUCTFEATURERELATIONSHIP> <PRODUCTFEATURERELATIONSHIP> <LEFTOBJECT RefType = "Path">/public/products/Oracle9i Database Server </LEFTOBJECT> <RIGHTOBJECT RefType = "Path">/public/features/Oracle 9iFS </RIGHTOBJECT> <PRICE>No additional charge.</PRICE> </PRODUCTFEATURERELATIONSHIP> </OBJECTLIST>
Once you have related PublicObjects, users may need to change the relationships between objects.
You can build custom applications which allow users to modify the relationships between PublicObjects by creating new relationship and deleting the old relationship, as illustrated in "Creating Relationships between PublicObjects" and "Unrelating PublicObjects". For example, if a Book is related to version 1 of a chapter, and the chapter is revised, the user can unrelate the Book from version 1 and related it to version 2 of the chapter.
A custom application could also allow Administrators to directly modify existing relationships between objects. This section describes how Administrators can directly update relationship objects.
To update a Relationship instance, the XML configuration file must:
<?xml version="1.0" standalone="yes"?> <BOOKRELATIONSHIP> <UPDATE RefType = "ComponentLabel">Chapter 1 : User Administration</UPDATE> <LEFTOBJECT RefType = "Path">/home/guest/Manuals/AdminGuide.bk</LEFTOBJECT> </BOOKRELATIONSHIP>
You can also update relationships with the Oracle 9iFS Java API. Each extended relationship type inherits the methods getLeftObject(), getRightObject(), and getSortSequence(), which can be used to manipulate the relationship between the PublicObjects. In addition, the inherited methods getAttribute() and setAttribute() provide a generic way to manipulate any extended attribute.
You can also implement custom Java classes to provide convenience methods for getting and setting the values for the extended attributes on your custom relationship type.
|
NOTE: For instructions on implementing custom Java classes, see Chapter 17, "Customizing Content Type Behavior" |
session.setAdministrationMode(true);
Relationship r = ......
r.setAttribute("COMPONENTLABEL", AttributeValue.newAttributeValue("Chapter 2 : User Administration"));
You can remove the relationship between PublicObjects by deleting the Relationship instance that links them.
You can remove PublicObject relationships with the Oracle 9iFS Java API as you would any other object, by calling the removeRelationship() method on the PublicObject. When this method is called, Oracle 9iFS deletes the Relationship instance. Oracle 9iFS does not support XML as a method for deleting relationships, nor does the Oracle 9iFS Manager provide a user interface for deleting Relationship instances.
Relationship r = ...... PublicObject po = .....
po.removeRelationship(r);
Oracle 9iFS allows you to traverse relationships between pieces of information. You can fetch all information that has been related to a given PublicObject. Or, you can narrow your selection down to all information with a particular type of relationship to the PublicObject. For example, given a document, you could fetch all folders that contain that document. To do so, you would search for all Folders that are the LeftObject in any FolderRelationship where the document is the RightObject.
You can also search for information based on metadata about a related PublicObject. Essentially, you would construct a search that constructs a join of the PublicObject's metadata based on the Relationship object that associates them. For example, you could search for all documents that are contained in any folder that was created on June 1, 2001. To do this, you would search for all PublicObjects that are the RightObject in a FolderRelationship where the LeftObject is a Folder with the CreateDate attribute set to June 1, 2001.
The Oracle 9iFS Java API makes it easy to traverse relationships between PublicObjects. The PublicObject class includes convenience methods, such as getLeftwardRelationshipObjects() and getRightwardRelationshipObjects(), which allow you to quickly fetch all information that is related to the object.
PublicObject po = .....
Relationship[] rightwardRels = po.getRightwardRelationships("BOOKRELATIONSHIP"); Relationship[] leftwardRels = po.getLeftwardRelationships("BOOKRELATIONSHIP");
PublicObject[] rightwardObjs = po.getRightwardRelationshipObjects("BOOKRELATIONSHIP"); PublicObject[] leftwardObjs = po.getLeftwardRelationshipObjects("BOOKRELATIONSHIP");
AttributeValue av; // variable to hold value of a relationship attribute int i; PublicObject relPO; String poName; int icount = (rightwardObjs == null) ? 0 : rightwardObjs.length; for(i = 0; i < icount; i++) { relPO = rightwardObjs[i]; poName = relPO.getName(); }
The Relationship class also provides convenience methods, getLeftObject() and getRightObject(), to retrieve the related PublicObject instances from a given Relationship instance. Once you have the PublicObject, you can retrieve all of the other attributes possessed by the PublicObject and call methods to manipulate the PublicObject (e.g., getContent(), setContent()).
Relationship r = ......
PublicObject p = r.getLeftObject();
PublicObject f = r.getRightObject();
ClassObject co = p.getClassObject(); String coName = co.getName(); Attribute[] atts = co.getEffectiveClassAttributes(); AttributeValue av; int i, icount; String attName; icount = (atts == null) ? 0 : atts.length; for (i = 0; i < icount; i++) { attName = atts[i].getName(); av = p.getAttribute(attName); }
The Oracle 9iFS Java API also allows you to construct more complex queries with Selectors and Searches. With a Selector, you can fetch all PublicObjects that pertain to a particular type of relationship. Using a Search, you can query for PublicObjects based on criteria about related PublicObjects. Example 6-54 and Example 6-55 illustrate how to search based on relationship metadata.
|
NOTE: For detailed instructions on building Selectors and Searches, see Chapter 8, "Building Search Applications" |
Example 6-54 selects all books that contain a given document. To do so, the example constructs a Selector that selects all BookRelationships that reference the document as the RightObject. The example then loops through the BookRelationships to retrieve the PublicObject that is referenced as the LeftObject (i.e., the Book);
Document doc = ...
Selector s = new Selector(session); s.setSearchClassname("BOOKRELATIONSHIP"); s.setSearchSelection("RIGHTOBJECT = " + doc.getId());
LibraryObject[] rels = s.getItems(); int count = (rels == null) ? 0 : rels.length; for (i = 0; i < count; i++) Relationship br; PublicObject po; { br = (Relationship) rels[i]; po = br.getLeftObject(); }
Example 6-55 queries for all Books that contain a PublicObject whose name contains 'Work-in-progress'. To do so, the example constructs a search that selects all BookRelationships that reference a PublicObject with a name containing 'Work-in-progress' as the RightObject. The example, then loops through the resulting BookRelationships to retrieve the PublicObject that is referenced as the LeftObject (i.e., the Book).
AttributeSearchSpecification asp = new AttributeSearchSpecification();
String[] searchClasses = {"PUBLICOBJECT", "BOOKRELATIONSHIP"}; SearchClassSpecification scp = new SearchClassSpecification(searchClasses); scp.addResultClass("BOOKRELATIONSHIP"); asp.setSearchClassSpecification(scp);
JoinQualification jq = new JoinQualification(); jq.setLeftAttribute("PUBLICOBJECT", null); jq.setRightAttribute("BOOKRELATIONSHIP", "RIGHTOBJECT");
AttributeQualification aq = new AttributeQualification(); aq.setAttribute("PUBLICOBJECT", "NAME"); aq.setOperatorType(AttributeQualification.LIKE); aq.setValue("%Work-in-progress%");
SearchClause sc = new SearchClause(aq, jq, SearchClause.AND); asp.setSearchQualification(sc);
Search srch = new Search(session, asp); srch.open(); int i; LibraryObject lo; SearchResultObject sro = srch.next(); PublicObject po; Relationship r; String poName; while (sro != null) { r = (Relationship) sro.getLibraryObject(); po = r.getLeftObject(); poName = po.getName(); try { sro = srch.next(); } catch (IfsException e) { if (e.getErrorCode() == 22000) { break; } else { e.printStackTrace(); } } } srch.close();
Oracle 9iFS comes with a two sets of sample code files which you can use to get started working with the Java API.
Oracle 9iFS is installed with runnable sample code files for the examples in this chapter. The sample code files are located in the <ORACLE_HOME>/9ifs/samplecode/oracle/ifs/examples/devdoc/arbitrarymetadata directory. These sample code files are useful for testing the chapter's examples. However, they must be run in the appropriate sequence and may cause naming conflicts if run more than once.
Table 6-4 lists the sample code files and their corresponding examples.
To run the Java sample code files, follow these steps:
> cd $ORACLE_HOME/9ifs/samplecode/oracle/ifs/examples/devdoc/arbitrarymetadata > javac CreatePPB.java
> java oracle.ifs.examples.devdoc.arbitrarymetadata.CreatePPB.java Running with arguments : user = system password = manager service = IfsDefault schemapassword = ifssys -----------Results---------- Policy created : FaxPolicy for operation : SendByFax with implementation : MyCompany.MyApp.DeliveryServers.FaxServer Policy created : PrintPolicy for operation : SendByPrinter with implementation : MyCompany.MyApp.DeliveryServers.PrintServer PolicyPropertyBundle created : Delivery Policies PolicyPropertyBundle ValueDefaultPropertyBundle created : DeliveryPoliciesValueDefaultPropertyBundle Value Default created : DeliveryPoliciesValueDefault
To run the XML configuration files, follow these steps:
In addition to the example sample code files, Oracle 9iFS is installed with more advanced sample code that helps you get started working with the Java API. The API sample code is located in the <ORACLE_HOME>/9ifs/samplecode/api directory. This API sample code is easier to work with than the Documentation sample code files because you can run the samples over and over without naming conflicts.
Table 6-5 lists the API sample code that is relevant to this chapter.
| Class | Usage |
|---|---|
|
CategorySample.java |
Creates Documents with Categories. |
|
PropertyBundleSample.java |
Creates a PropertyBundle. Adds, updates, and removes Properties in the PropertyBundle. |
|
|
![]() Copyright © 2001 Oracle Corporation. All Rights Reserved. |
|