Oracle Internet File System Developer's Guide Release 1.1 A75172-04 |
|  |  | Index

# 9
Using Overrides

This chapter covers the following topics:

- What Is an Override?

- Before You Begin Working with Overrides

- Override Methods

- Writing an Override

- Sample Code: A PreInsert Override

## What Is an Override?

Overrides belong to the category of Oracle Internet File System customization, which includes:

- Creating custom classes (types)

- Parsers and renderers

- Agents

- Overrides

Of these four types of customization, overrides present a significant leap in complexity. Except for renderers, the other types of customization take place on the client, or "bean-side." These more common types of customization use the extensive classes found in the `oracle.ifs.beans` package. With overrides, we tackle "server-side" processing, using a more limited published API.

An override is a method that allows an application program to intervene in a predefined way with the standard repository operations:

- Insert

- Update

- Free

Note: For the 1.1 release of Oracle iFS, overrides are applicable only to Insert, Update, and Free operations. No overrides are available for other database operations, such as copy, add item to folder, or remove item from folder. This functionality is planned for future releases of the product.

### How Pre- Overrides Work

The Pre- overrides work by allowing you to interrupt the standard flow of processing on the server side at certain predefined points. At these points, you can specify custom processing to occur before one or more of the standard database operations takes place. For example, your custom validation routine might be incorporated into both PreInsert and PreUpdate overrides.

### Using Pre- Overrides

The behavior of the actual Insert, Update, and Free operations is complex, and to override the actual operations risks producing unintended and unwanted results.

However, in almost every circumstance, application requirements can be met quite safely by using Pre- methods to interact with the repository immediately before the specified operation. Because the Pre- overrides are the most frequently used, the balance of this chapter focuses on Pre- overrides.

The following table presents an example of how each override method might be used.

Operation | Override Method | Usage Example
--- | --- | ---
Insert | extendedPreInsert() | To add a certain attribute with a specified value to every new instance of a custom document class.
Update | extendedPreUpdate() | Same as for Insert, to extend this processing to Update operations. Or to provide special validation on Update.
Free | extendedPreFree() | To write a copy to a Deletions log file.

## Before You Begin Working with Overrides

Because working with overrides is a complex task, we recommend that you postpone tackling overrides until you have had considerable experience with Oracle iFS and its Java API. Specifically, we suggest that your background should include knowledge and hands-on experience in the following areas:

- Sufficient familiarity with the bean-side API to know how Oracle iFS objects work:

  - How objects are created.

  - How object attributes are set.

  - How related objects, such as Documents and Folders, work together.

- Sufficient familiarity with attribute values and the definition classes to know how they work together:

  - How to use the AttributeValue class, the Oracle iFS data structure that holds attribute values in a definition object.

  - How to set and get bean-side attribute values.

  - How to set and get server-side attribute values.

  - How to work with sets of attribute values.

  - How to use basic datatypes to define attribute values.

  - How to use value defaults.

  - How to use value domains.

- Familiarity with the Oracle iFS transaction model.

Providing this range of information is beyond the scope of this Guide. To gain the experience required to tackle overrides, we suggest beginning with several less-complex Oracle iFS applications. This hands-on experience, combined with attendance at Oracle iFS training, will provide the needed familiarity with the Oracle iFS objects and the way they work together.

### Review of Attributes

If you have created Oracle iFS objects using the classes of the Oracle iFS API, you will recall the two-phase method of object creation:

1. Create a Definition object.

2. Pass the Definition object to the method that actually creates the object.

For example, for a document, you would first create a DocumentDefinition object, then pass that object as an argument to the LibrarySession.createPublicObject() method. For more information, see "Creating a New Document" in Chapter 3, "Working with Documents".

#### Attributes and Server-Side Classes

In the Oracle iFS Java class hierarchy each Oracle iFS object has two representations:

- The bean-side representation, known by the object name, such as Document.

- The server-side representation, known by the object name preceded with "S_", such as S_Document.

When you work with overrides, you are working with objects in the Oracle iFS repository. In this context, you use the S_ classes, such as S_Document, rather than the familiar bean-side classes, such as Document.

#### Attributes and Special Options

The function of the Definition object is to specify the object's attributes. When you create a DocumentDefinition object, you set two types of information:

- Document attributes:

  - Document attributes, such as Name and Description, are the metadata about the document that can be easily searched.

  - To set an attribute, use the generic setAttribute() method defined in the LibraryObjectDefinition class.

- Special options:

  - Special options, such as AddToFolderOption, specify detailed information about the document but do not provide attribute values.

  - To set special options, use the specific method provided in the Definition class, such as the oracle.ifs.beans.PublicObjectDefinition.
    setAddToFolderOption().

  - Although special options are set on the bean-side, they are handled on the server side, using the S_LibraryObjectDefinition object.

#### User-set Attributes and Derived Attributes

Attributes can also be divided into two categories based on their origin:

- User-set attributes

  User-set attributes are attributes that are set by and can be updated by the user, such as the object Name and Description.

  You can set all the user-set attributes using the bean-side Definition object.

- Derived attributes

  Derived attributes are attributes that are set by and can only be updated by the system, such as Creator. These attributes are derived from a source other than the user. For example, Creator is derived from the current logon ID.

  To handle the derived attributes, you must use the server-side class,
  S_DocumentDefinition.

## Override Methods

The override methods provide pre-processing for the standard database operations:

- Insert

- Update

- Free (for override purposes, use the methods related to Free rather than Delete)

Because overrides by their nature take place on the server-side, all the override methods are located in the S_LibraryObject class and its subclasses. Just as oracle.ifs.beans.LibraryObject provides a bean-side Java representation for all the objects that end users manipulate directly (such as documents and folders), oracle.ifs.server.S_LibraryObject provides the server-side Java representation for these same objects.

Operation | Method | Purpose
--- | --- | ---
Insert |  |
| extendedPreInsert | Performs designated operations before inserting an iFS object into the database. For example, used to modify any attributes after the Definition object has been created but before the Insert takes place.
Update |  |
| extendedPreUpdate | Performs designated operations before updating an iFS object in the database.
Free |  |
| extendedPreFree | Performs designated operations before freeing a database object. Note that this method is overridden by classes that need to perform operations before successfully deleting the rows for the freed instance.

## Writing an Override

To plan an override, first decide which operation or operations you want to override (Insert, Update, or Free).

To write an override, follow these steps:

1. Declare the Server-side Class.

2. Create the Constructor.

3. Implement the Override Method.

### Declare the Server-side Class

Assume you have already created a bean-side custom class called PurchaseOrder that extends the Document class. Now you decide you want to add some special validation checks via a PreInsert override.

First you create a server-side Java class, S_PurchaseOrder, to represent your custom class in the server. S_PurchaseOrder extends S_TieDocument. Tie classes allow you to "tie" into the class hierarchy at any level, letting you customize without changing the way the class hierarchy is structured. For more information, see "Tie Classes" in Chapter 2, "API Overview".

Put this class into a new custom package, such as `MyCompany.MyApp.server.`
(Do not add this class to the `oracle.ifs.server` package).

#### Sample Code: Declare the Class

    public class S_PurchaseOrder extends S_TieDocument

### Create the Constructor

Every override class must implement two constructors:

- One used for an object that currently exists in the database.

- One used for an object that has not yet been created in the database.

#### Sample Code: Constructor

    public S_PurchaseOrder(S_LibrarySession session, S_LibraryObjectData data)

          throws IfsException

Parameters | Datatype | Description
--- | --- | ---
`session` | S_LibrarySession | Current LibrarySession.
`data` | S_LibraryObjectData | Data component

#### Sample Code: Constructor

    public S_PurchaseOrder(S_LibrarySession session, java.lang.Long classID)

          throws IfsException

Parameters | Datatype | Description
--- | --- | ---
`session` | S_LibrarySession | Current LibrarySession.
`classID` | Long | Class ID for the object that is in the process of being created.

### Implement the Override Method

The S_PublicObject class provides Pre- methods for the standard database operations. For a complete list, see "Override Methods".

The following table describes the parameters of the Override methods.

Parameter | Datatype | Description
--- | --- | ---
`opState` | OperationState | Used by the system to track the current state of operations.
`def` | S_LibraryObjectDefinition | Current object definition to be updated with system attributes.

#### Sample Code: Implement the Override Method

    public void extendedPreInsert(OperationState opState,

              S_LibraryObjectDefinition def) throws IfsException

    {
         super.extendedPreInsert(opState, def);
         //Add your validation code here.
    }

The first call after the method begins should be to "super." This call implements processing from the superclass of this object. In this case, it allows both the
S_Document class and the S_PublicObject class to perform processing.

After that, add any specific validation code that your application requires. For example, in the custom bean-side class for Purchase Order, you may have added a setApprover() method. Before you insert the PurchaseOrder object into the database, you may want to check the value of that Approver, and perform one of the following actions:

- Validate that the Approver is correct.

- Add a default Approver if the current value is null.

- Change one Approver name to another based on some custom logic.

## Sample Code: A PreInsert Override

The following sample code provides a brief example of using a PreInsert override to add server-side validation. Note the following three lines shown in bold, where placeholders are used that must be replaced with appropriate code for your application:

- mypackage

- <valid>

- <your custom error code>

      // S_PurchaseOrder.java

      package mypackage;

      import oracle.ifs.common.AttributeValue;
      import oracle.ifs.common.IfsException;

      import oracle.ifs.server.S_DirectoryUser;
      import oracle.ifs.server.S_LibraryObjectData;
      import oracle.ifs.server.S_LibraryObjectDefinition;
      import oracle.ifs.server.S_LibrarySession;
      import oracle.ifs.server.OperationState;
      import oracle.ifs.server.S_TieDocument;

      // server side PurchaseOrder class example
      public class S_PurchaseOrder extends S_TieDocument
      {
           // constructors
           public S_PurchaseOrder(S_LibrarySession session, S_LibraryObjectData data)
               throws IfsException
           {
               super(session, data);
           }
           public S_PurchaseOrder(S_LibrarySession session, Long classId)
               throws IfsException
           {
               super(session, classId);
           }

           // override Pre Insert Operation
           public void extendedPreInsert(S_LibraryObjectDefinition def,
                                         OperationState opState) throws IfsException
           {
               // ALWAYS call super
               super.extendedPreInsert(opState, def);

               // get our session
               S_LibrarySession session = getSession();

               // get the approver attribute so we can check it
               AttributeValue av1 = def.getAttribute("APPROVER");
               S_DirectoryUser approver = (av1 == null) ? null:
                   (S_DirectoryUser) av1.getDirectoryObject(session);

               //validate the approver
               if (! <valid> )
               {
                    // this will rollback the operation
                    throw new IfsException( <your custom error code>, this );
               }

               // otherwise, set the APPROVED bit to true.
               // the APPROVED bit is not settable or updateable
               // by users, but the server can set it thusly
               AttributeValue av2 = AttributeValue.newAttributeValue(true);
               def.setSystemSetAttribute("APPROVED", av2);
          }
      }

| Copyright © 2000 Oracle Corporation. All Rights Reserved. |
|  |  | Index