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

# 4
Creating Custom Classes

This chapter covers the following topics:

- Overview of Creating Custom Classes

- Creating a Type Definition File

- Using Compound Attributes

- Load a Custom Type Definition

- Creating an Instance Class Bean

- Creating Document Instances

## Overview of Creating Custom Classes

The most frequent customization within Oracle iFS involves adding custom attributes to the existing Document class. If an application requires only such basic customization, you can use XML to define a custom type. Creating a type definition file in XML corresponds roughly to subclassing the Document class in Java. Because creating "custom classes" is a familiar concept, we have used that term as well as the less familiar "custom types." (Note this slight distinction: in XML, the Superclass reference is to "Document", while in Java, the instance Bean extends "TieDocument." For more information, see "Tie Classes" in Chapter 2, "API Overview".)

Creating a custom class is the most basic Oracle iFS customization. Other ways to customize Oracle iFS include writing custom parsers, renderers, JSPs, and agents.

In Oracle iFS, custom classes (custom types) work as follows:

1. The developer creates a custom class and loads it into Oracle iFS.

   The custom class must be loaded before any document instances can be created.

2. Users create and load instances of the newly defined class into Oracle iFS.

3. Oracle iFS automatically parses the instances of the custom class and stores their elements as attributes.

   Once instances are stored in the repository, end users can execute queries on the attributes.

## Creating a Type Definition File

If you have a group of documents with custom attributes that you want Oracle iFS to recognize and manipulate, you need to be able to describe these documents to Oracle iFS. To describe a custom document to Oracle iFS, use XML to create a type definition file.

### How Do Type Definitions Work?

A type definition is based on a simple inheritance model in which a new type (class) inherits the attributes and behavior associated with its superclass. The Oracle iFS class hierarchy is based on a single inheritance tree:

    LibraryObject      //The root class for all of iFS.

    PublicObject   //The root class for all user-related classes.

    Document   //The subclass of PublicObject that includes content.

Because the Document class is used for all objects that include content, Document is the most frequently used superclass. For a complete listing of the Oracle iFS API class hierarchy, see the Oracle Internet File System Setup and Administration Guide.

You can think of a type definition as consisting of two logical parts:

- Description: The first section describes the new content type, specifying its name and superclass.

- Attributes: The second section lists the attributes of the new content type, including one entry for each attribute defined. Each entry specifies the attribute label and data type.

### The Type Definition File: Description Section

The Description section of the type definition includes six tags:

- The <ClassObject> Tag

- The <Name> Tag

- The <Description> Tag

- The <Superclass> Tag

- The <BeanClassPath> Tag

- The <ServerClassPath> Tag

This code fragment consists of a Description section, followed by information about each tag:

    <ClassObject>
      <Name>InsuranceForm</Name>
      <Description>Claim Form</Description>
      <Superclass Reftype ="name">Document</Superclass>
     .
     .
     .
     </ClassObject>

#### The <ClassObject> Tag

The first tag in a type definition file must be <ClassObject>. The <ClassObject> and </ClassObject> tags encapsulate the type definition and specify to Oracle iFS that you are creating a new repository object of the ClassObject class. The ClassObject class contains a registration entry for each class in the Oracle iFS API. For example, there are ClassObject objects defined for the Document class and the Folder class. The ClassObject is used internally to manage instances of the class. Thus, for each custom type definition, a new ClassObject entry is created.

#### The <Name> Tag

When you insert the type definition into the repository, Oracle iFS uses the data you provide to define a table in the repository to store information about documents of the custom type. The value of the <Name> tag is used to construct the table name, so it must not include spaces.

#### The <Description> Tag

Optional. The <Description> tag provides a multi-word description of the custom type.

#### The <Superclass> Tag

A type definition file creates a new class in the repository by subclassing an existing class, usually the Document class. Use the <Superclass> tag to specify the name of the superclass.

The <Superclass> tag requires a RefType parameter to specify that you are going to provide the name of the superclass, rather than referencing it in any other way, such as by using an object ID. Here is an example of the <Superclass> tag in use:

    <Superclass RefType='name'>Document</Superclass>

#### The <BeanClassPath> Tag

Optional. The <BeanClassPath> tag specifies the fully qualified path to the instance class Bean. Required only if a custom instance Bean is written.

#### The <ServerClassPath> Tag

Optional. The <ServerClassPath> tag specifies the fully qualified path to the server class Bean, which by convention is an S_ class. Required only if a custom server-side override is written.

### The Type Definition File: Attributes Section

The second section of the type definition is the Attributes section, enclosed by a pair of <Attributes> </Attributes> tags. The Attributes section consists of custom attribute definition entries. The Attributes section contains one element for each attribute that is unique to this type. Each attribute definition entry is enclosed by a pair of <Attribute> </Attribute> tags, and may include three tags:

- The Attribute <Name> Tag

- The <DataType> Tag

- The <DataLength> Tag

- The <ClassDomain> Tag

Here is an attribute definition entry for the ClaimNumber attribute:

    <Attribute>
      <Name>ClaimNumber</Name>
      <DataType>Long</DataType>
    </Attribute>

#### The Attribute <Name> Tag

The attribute <Name> tag specifies the name of the attribute being defined. This is the name of the variable that will be used in the getter and setter methods in the corresponding instance class Bean. Internally, Oracle iFS converts all attribute names to uppercase, so you can use any combination of case that you choose, but you cannot have two names that differentiate only by case. Thus, `FullName`, `FULLNAME`, `fullname`, and `fullName` are all legal, but having two attributes called `FullName` and `FULLNAME` is not.

#### The <DataType> Tag

The <DataType> tag specifies the type of data stored in the attribute. For example, "String" and "integer" are common datatypes.

#### The <DataLength> Tag

Optional, used for String values only. The <DataLength> tag specifies the maximum length in bytes for String attributes. Values greater than this number will result in an error message.

#### The <ClassDomain> Tag

The <ClassDomain> tag is used to restrict the types of objects that can be stored in an attribute whose datatype is PublicObject. For more information, see "Sample Code: ClassDomain Definition".

### Sample Code: Create a Type Definition

The completed type definition looks like this:

    <?xml version = '1.0' standalone = 'yes'?>
    <!-- CreateInsuranceForm.xml -->
    <ClassObject>
       <Name>InsuranceForm</Name>
       <Description>Claim Form</Description>
       <Superclass Reftype ="name">Document</Superclass>
       <Attributes>
          <Attribute>
              <Name>ClaimNumber</Name>
              <DataType>Long</DataType>
          </Attribute>

          <Attribute>
              <Name>ClaimType</Name>
              <DataType>String</DataType>
              <DataLength>50</DataLength>
          </Attribute>

          <Attribute>
              <Name>InsuranceFormStreetAddress</NAME>
              <DataType>PublicObject</DataType>
             <ClassDomain RefType="Name">InsuranceFormStreetAddressDomain

              </ClassDomain>
        </Attributes>
    </ClassObject>

In this example, the attribute, InsuranceFormStreetAddress, is an embedded attribute defined as datatype PublicObject and restricted to containing objects of the class InsuranceFormStreetAddressDomain.

## Using Compound Attributes

An attribute in an XML file can be:

- A simple value, such as a person's name.

- A compound value, such as an address, with its elements of Street, City, and State, which is derived from another object and embedded in the parent object as a component.

To handle simple values, use the database datatypes, such as String, Integer, Long, Date.

To handle compound values, follow these steps:

1. Create a separate type definition for each compound attribute. For example, you could create an Address object that defined attributes for Street, City, State, Zip, and Country. Typically, you would subclass the ApplicationObject class, which inherits from PublicObject. See "Sample Code: Embedded Attribute Type Definition".

2. Define a ClassDomain object based on the type that was just created. See "Sample Code: ClassDomain Definition".

3. In the parent type definition, define the compound attribute as datatype PublicObject and use the ClassDomain object to restrict the kind of PublicObjects this attribute can contain to instances of the InsuranceFormStreetAddress class. See "Sample Code: Create a Type Definition".

### Sample Code: Embedded Attribute Type Definition

In this example, a new class object, InsuranceFormStreetAddress, defines the elements of a compound attribute that includes Street, City, State, Zip, and Country.

    <?xml version = '1.0' standalone = 'yes'?>
    <!-- InsuranceFormStreetAddress.xml -->
    <ClassObject>
       <Name>InsuranceFormStreetAddress</Name>
       <Description>Insurance Form Address Definition</Description>
       <Superclass Reftype ="name">ApplicationObject</Superclass>

       <Attributes>
          <Attribute>
              <Name>AddressType</Name>
              <DataType>String</DataType>
              <DataLength>64</DataLength>
          </Attribute>

          <Attribute>
              <Name>StreetLine1</Name>
              <DataType>String</DataType>
              <DataLength>64</DataLength>
          </Attribute>

          <Attribute>
              <Name>StreetLine2</Name>
              <DataType>String</DataType>
              <DataLength>64</DataLength>
          </Attribute>

          <Attribute>
              <Name>StreetLine3</Name>
              <DataType>String</DataType>
              <DataLength>64</DataLength>
          </Attribute>

          <Attribute>
              <Name>City</Name>
              <DataType>String</DataType>
              <DataLength>64</DataLength>
          </Attribute>

          <Attribute>
              <Name>State</Name>
              <DataType>String</DataType>
              <DataLength>32</DataLength>
          </Attribute>

          <Attribute>
              <Name>Zip</Name>
              <DataType>String</DataType>
              <DataLength>16</DataLength>
          </Attribute>

          <Attribute>
              <Name>Country</Name>
              <DataType>String</DataType>
              <DataLength>32</DataLength>
          </Attribute>

        </Attributes>

      </ClassObject>

### Sample Code: ClassDomain Definition

This class domain restricts entries to be the ClassObject defined in InsuranceFormStreetAddress.xml.

    <?xml version="1.0" standalone="yes"?>
    <!--InsuranceFormStreetAddressDomain.xml-->
    <ClassDomain>
      <Name>InsuranceFormStreetAddressDomain</Name>
      <DomainType>1</DomainType>
      <Classes>
        <ArrayElement reftype="name">InsuranceFormStreetAddress</ArrayElement>
      </Classes>
    </ClassDomain>

### Load a Custom Type Definition

To load a custom document type, log in as an administrator and upload the type definition file into Oracle iFS. You can load a type definition file to any appropriate folder in Oracle iFS; no special location is required.

## Creating an Instance Class Bean

Once you've created a custom type definition, (although not required) that you create a corresponding instance class Bean to implement custom behavior and convenience methods for getting and setting custom attributes.

The instance class Bean is recommended for coding convenience, as it provides the expected getter and setter methods for the custom attributes. However, it is not required unless you need to provide unique functionality for this type.

The instance class Bean should include:

- A standard constructor, consisting of a call to "super" (the superclass, Document).

- Getter and setter methods for attributes defined in the type definition file.

- Any methods needed to provide functionality unique to the type.

Note the following connections between the type definition file and the instance class Bean:

- The instance class Bean extends the implementation class of the superclass specified in the type definition file. Tie classes provide implementation classes for all Oracle iFS classes. Thus, because the CreateInsuranceForm.xml type definition file defines Document as the superclass, the CreateInsuranceForm.java instance class Bean extends TieDocument, which is the implementation class for Document.

- For more information about using Tie classes, see "Tie Classes" in Chapter 2, "API Overview".

- The name and package of the instance class Bean must match the value of the
  <BeanClassPath> attribute in the type definition file, if one is present.

### Sample Code: Create an Instance Class Bean

    /*---CreateInsuranceForm.java---*/
    package ifsdevkit.sampleapps.insurance;

    import oracle.ifs.beans.ClassObject;
    import oracle.ifs.beans.DirectoryUser;
    import oracle.ifs.beans.FolderPathResolver;
    import oracle.ifs.beans.LibrarySession;
    import oracle.ifs.beans.PublicObject;
    import oracle.ifs.common.AttributeValue;
    import oracle.ifs.common.IfsException;

    public class InsuranceBean
    {
      /**
       * The name for the claim.
       */
      protected String m_name;

      /**
       * The type of the claim.
       */
      protected String m_claimType;

      /**
       * The claim number.
       */
      protected Long   m_claimNumber;

      /**
       * Constructor
       */
      public InsuranceBean()
      {
      }

      /**
       * Initialize the bean and populate the necessary fields.
       *
       * @param session   The <code>LibrarySession</code> object.
       *
       * @param resolver  The <code>FolderPathResolver</code> object.
       *
       * @param path  The path to the insurance object.
       *
       * @exception IfsException Thrown if operation failed.
       */
      public void init(LibrarySession session, FolderPathResolver resolver, String
    path)
      throws IfsException
      {
        try
        {
          PublicObject insuranceObj = resolver.findPublicObjectByPath(path);
          ClassObject co = insuranceObj.getClassObject();

          m_name = insuranceObj.getName();
          AttributeValue av = insuranceObj.getAttribute("CLAIMTYPE");
          if (!av.isNullValue())
          {
            m_claimType = av.getString(session);
          }
          av = insuranceObj.getAttribute("CLAIMNUMBER");
          if (!av.isNullValue())
          {
            m_claimNumber = new Long(av.getLong(session));
          }
        }
        catch (IfsException e)
        {
          e.printStackTrace();
          throw e;
        }
      }

      /**
       * Return name for the claim.
       *
       * @return The claim name.
       */
      public String getName()
      {
        return m_name;
      }

      /**
       * Return the claim type.
       *
       * @return The claim type in a <code>String</code>.
       */
      public String getClaimType()
      {
        return m_claimType;
      }

      /**
       * Return the claim number.
       *
       * @return The claim number as a <code>Long</code>.
       */
      public Long getClaimNumber()
      {
        return m_claimNumber;
      }
    }

### Deploy an Instance Class Bean

For the protocol servers and other standard Oracle iFS components to access your custom instance class Bean, the folder tree containing the class for the Bean must reside in the Oracle iFS CLASSPATH. Oracle iFS includes a special directory for this purpose. This directory, called `custom_classes`, is already in the CLASSPATH environment variable that the Oracle iFS server software uses.

To deploy an instance class Bean:

1. Compile the instance class Bean, creating a `.class` file.

2. Place the folder tree that contains the resulting `.class` file in the directory `$ORACLE_HOME/ifs/custom_classes` on the server where Oracle iFS is installed.

For example, if the compiled Bean, `InsuranceForm.class`, is stored in the package `ifs.examples`, the entire folder tree, from /`ifs` on, must be stored in the `custom_classes` directory.

Note: The compiled Java Bean must be copied to the native file system of the server, not to the Oracle iFS repository.

## Creating Document Instances

Once you have created the custom type file to define the custom class for the insurance form document and stored it in Oracle iFS, you can create document instance files to instantiate the class. These document instances can be either in a custom format or in XML.

When you upload document instance files into Oracle iFS, Oracle iFS parses the files and creates the appropriate objects, which are stored in the Oracle iFS repository. The specific parser called varies according to the way the files are loaded, as shown in the following table. For more information about using and registering parsers, see Chapter 5, "Using Parsers".

Document Instance Format | Loaded By | Parsed By
--- | --- | ---
XML | Any Oracle iFS protocol or user interface | Automatically parsed by the SimpleXmlParser.
XML | Application program | SimpleXmlParser must be explicitly called by the application.
Custom | Any means: protocol, user interface, or application program | Custom parser must be written and registered for use by protocols and user interfaces, or explicitly called by the application.

Note: Once Oracle iFS creates objects from the document instance files, the document instance files themselves are not stored in the Oracle iFS repository. If you think you may need further access to the document instance files (for example, to modify them to create new document instances), you may want to keep copies of the instance files on your local drive.

### Sample Code: Create Document Instances

These two files, `claim1.xml` and `claim2.xml`, are the document files that create two specific instances of the InsuranceForm class.

    <?xml version = '1.0' standalone = 'yes'?>
    <!-- claim1.xml -->
    <InsuranceForm>
       <Name>Juana Angeles</Name>
       <ClaimNumber>35093</ClaimNumber>
       <ClaimType>Car Accident</ClaimType>
       <FolderPath>/public/examples/insuranceApp/claims</FolderPath>
    </InsuranceForm>

    <?xml version = '1.0' standalone = 'yes'?>
    <!-- claim2.xml -->
    <InsuranceForm>
       <Name>Kevin Chu</Name>
       <ClaimNumber>41111</ClaimNumber>
       <ClaimType>Car Accident</ClaimType>
       <FolderPath>/public/examples/insuranceApp/claims</FolderPath>
    </InsuranceForm>

### Upload Document Instance Files

Use one of these options to upload document instance files:

- Use a standalone FTP product.

- In the Oracle iFS Web interface, use either:

  - `Upload via Drag and Drop` or

  - `Upload via Browse` with `Parse on Upload` selected.

### Limitations on XML Type Definition Files

If you are creating XML type definition files, you should be aware of the following limitations:

- Although you can use XML to create custom type files, you cannot use XML to delete or modify custom type files.

- Use Oracle iFS Manager to delete or modify custom type files.

For information about using Oracle iFS Manager, see the Internet File System Setup and Administration Guide.

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