A binary file is an operating-system
file, which is represented as a Java
File object. For an ODA to generate binary-file content, its
ODA class must implement the IGeneratesBinFiles interface. Table 47 lists the methods that the ODA class must define to
implement the
IGeneratesBinFiles interface.
Table 47. Methods in the IGeneratesBinFiles interface
Method | IGeneratesBinFiles method | Description |
---|---|---|
Source-node-generation method |
None
| Generation of source nodes must be performed by the getTreeNodes() method of the IGeneratesBoDefs interface. For more information, see Using files. |
Content-generation method | generateBinFiles() | Generates the binary files, writing them to ODA memory |
Content-retrieval method | getBinFile() | Retrieves either a specified binary file or all binary files from ODA memory |
Business Object Wizard generates and retrieves content while it displays
the Generating Business Objects (Step 5) dialog box. With the
IGeneratesBinFiles interface implemented, Business Object Wizard
invokes the methods shown in Table 48 to generate and retrieve content.
Table 48. Business Object Wizard and IGeneratesBinFiles methods
Use of method | IGeneratesBinFiles method | For more information |
---|---|---|
Generate files as content | generateBinFiles() | Generating files |
Retrieve the generated files | getBinFile() | Providing access to generated files |
The following sections discuss the implementation of each of the methods in Table 48.
When an ODA that implements the IGeneratesBinFiles interface, it can support the use of operating-system files in the following contexts:
When an ODA implements the IGeneratesBinFiles interface, it supports creation of files as content. The files that the ODA creates hold the information that the ODA collects from the business-object-definition generation process and elsewhere. If the file-generation process needs the array of user-selected source nodes (which Business Object Wizard creates as a result of Step 3, Select Source), the ODA can receive this array from Business Object Wizard. For information on how to implement the method that generates the files, see Generating files.
However, the IGeneratesBinFiles interface does not define a source-node-generation method, which discovers source nodes and generates the array of tree nodes for Business Object Wizard to display in the Select Source dialog box. Instead, if the ODA supports generation of file content and this file generation requires an array of user-selected source nodes, the ODA must use the source-node-generation method in the IGeneratesBoDefs interface, getTreeNodes(). This method queries the data source for the child nodes of the specified parent node and constructs the associated tree nodes, as described in Generating source nodes.
If an ODA supports only creation of new files (file generation), it can use the getTreeNodes() method as defined in IGeneratesBoDefs. This method queries the data source for the child nodes of the specified parent node and constructs the associated tree nodes, as described in Generating source nodes.
When an ODA implements the IGeneratesBinFiles interface, it can support reading operating system files that you associate with source nodes (For information on how to associate a file with a node, see Associating an operating-system file.). The files that the ODA reads hold source data, which the ODA must search for objects that are represented as source nodes. To support the association of files with nodes, an ODA must take the following steps:
Important |
---|
An ODA must implement the IGeneratesBinFiles interface for the getClientFile() method to successfully retrieve a specified operating-system file. If the ODA implements only the IGeneratesBoDefs interface, getClientFile() throws the UnsupportedContentException exception. |
The getClientFile() method expects as an argument the source-node path of the file to retrieve. This source-node path has the following format:
fileNodePath:filePath
where fileNodePath is the node path (node names separated by colon (:)) of the node that has an associated file and filePath is the operating-system path of the associated file. When users expand or select a node that is an associated file, Business Object Wizard creates this path for the node.
For example, the ArmyAgent5 class of the sample Roman Army ODA supports both the IGeneratesBinFiles interface and the association of files with nodes. Suppose you associate the Flavius.xml file (in the directory C:\IBM\XMLFiles) to the Vulso source node, as shown in Figure 51.. If you select the Flavius.xml node (see Figure 52) from the source-node hierarchy, Business Object Wizard puts the following node path into the array of source nodes:
Apollo:Vulso:Flavius.xml:C:\IBM\XMLFiles\Flavius.xml
This ODA provides the findSon() method to parse a source-node path and locate the associated object that the source node represents. The version of findSon() in the ArmyAgent3 class queries only the ODA's data source (an XML file called RomanArmy.xml) for the object associated with the specified source node. A revised version in the ArmyAgent4 class adds the ability to query an associated file by providing the remoteSon() method, which uses getClientFile() to obtain the contents of the specified file and return this content as a Son object.
If a source node can have a file associated with it, then the ability to interpret the file's source-node path and to read the contents of this file is needed during content generation, the method that generates content must be able to access information in nodes that are in a file. Implement the method that generates content so that it uses getClientFile() to retrieve an operating-system file that is associated with a node. The method that provides this support is as follows:
For more information on how to generate file content, see Generating files.
After users have selected the source nodes in the Select Nodes dialog box, the ODA is ready to begin content generation. The goal of the file generation process is to create a file (or files) that the ODA or other process requires. The step that initiates the generation of files depends on the content protocol associated with the file content type (ContentType.BinaryFile), as follows:
This section describes the following steps that the generateBinFiles() method should take to generate files:
The generateBinFiles() method is defined in the IGeneratesBinFiles interface. Therefore, your ODA class (derived from ODKAgentBase2) must implement this method when it implements the IGeneratesBinFiles interface. The purpose of the generateBinFiles() method depends on the content protocol that the ODA uses for generation of file ( ContentType.BinaryFile) content, as follows:
If the ODA generates files "on request", Business Object Wizard explicitly calls the generateBinFiles() method to initiate generation of the files. Therefore, you must implement generateBinFiles() so that it handles generating the file objects, storing them in the generated-content structure, and returning of content metadata to Business Object Wizard.
While the generateBinFiles() method runs, Business Object Wizard displays its Generating Business Objects screen (Step 5). As its last step, generateBinFiles() returns a content-metadata (ContentMetaData) object, which describes the generated files it has generated (though it does not contain the actual generated files).
If the ODA generates files through callbacks, Business Object Wizard never explicitly calls the generateBinFiles() method. Instead, the ODA uses some other way to "spontaneously" generate the files. You must develop a method to handle generating the files, storing them in the generated-content structure, and notifying Business Object Wizard that content generation is complete. However, the IGeneratesBinFiles interface requires that you define the generateBinFiles() method. Therefore, you must implement generateBinFiles() so that it warns the caller that it should never be called.
The sample Roman Army ODA supports the callback content protocol for the generation of files (see Figure 60). It defines the generateBinDefs() method in the ArmyAgent5 class. This implementation of the method includes the code in Figure 71, which defines the generateBinFiles() method so that it throws an exception if it is ever called.
Figure 71. Defining the generateBinFiles() method
public ContentMetaData generateBinFiles(String[] nodes) throws ODKException { throw new ODKException( "Files are produced as callbacks. Do not call for file generation."); }
As an alternative to throwing an exception, the generateBinFiles() method can use the contentUnavailable() method (defined in ContentMetaData) to return its content metadata to Business Object Wizard, as follows:
return (ContentMetaData.contentUnavailable(ContentType.BinaryFile));
If, during the process of generating the files, the ODA requires additional information, it opens the BO Properties dialog box where users can provide values for business-object properties. Even though these properties are called business-object properties, you can use the getBOSpecificProps() method to display information that the file-generation process might require. For more information on how to use the BO Properties dialog box, see Requesting business-object properties.
The ODK API does not provide a special class to represent a binary file because Java already provides the File class in its java.io package. This package contains many input/output classes that can be useful in the generation and access of files. For each file that the ODA generates, it must take the following steps:
The actual file generation that your ODA performs depends on the design of the ODA. Implement the file generation as best fits the requirements of your ODA and any components that require the files.
The ArmyAgent5 class of the sample Roman Army ODA defines a separate class, FileCreator, to handle the actual generation of the files. To simulate "spontaneous" file generation, the sample calls the FileCreator() constructor from the generateBoDefs() method, as the following code fragment shows:
public ContentMetaData generateBoDefs(String[] nodes) throws ODKException { ContentMetaData cmd = super.generateBoDefs(nodes);
new FileCreator(this, nodes).start();
return cmd; }
The FileCreator() constructor spawns a thread to generate the files. It receives as an argument a reference to the current ODA object (this) and the array with the node paths of the selected source nodes. It then creates the following files:
As discussed in Providing generated content, the ODA must return the generated content to Business Object Wizard in two parts. Therefore, if the ODA generates files as content, it must return the following:
The method that provides this information depends on the content protocol that the ODA uses to generate files, as follows:
If the ODA generates files "on request", Business Object Wizard invokes the generateBinFiles() method to handle file generation. Therefore, generateBinFiles() provides the generated content as follows:
Once Business Object Wizard receives this content-metadata object, it can access the generated files (within the generated-content structure) as needed with the getBinFile() method.
For more information on getBinFile() , see Providing access to generated files.
If the ODA generates files through callbacks, Business Object Wizard does not invoke the generateBinFiles() method to handle file generation. Instead, the ODA uses some user-defined method to "spontaneously" generate files. This method could be part of the ODA class or in a class within the ODA's package. However, it must provide the generated content as follows:
The user-defined method that generates files cannot return the content metadata directly to Business Object Wizard because Business Object Wizard has not invoked this method. Instead, the method must send a "content generation is complete" signal to Business Object Wizard by calling the contentComplete() method (defined in the ODKUtility class). This method accepts a content-metadata object as an argument. See Table 49 for the information that this content-metadata object should contain. It sends this content metadata to Business Object Wizard. Once Business Object Wizard receives the content-metadata object, it can use the getBinFile() method to access the generated files (within the generated-content structure).
In the ArmyAgent5 class of the sample Roman Army ODA, the generated-content structure is defined an array of File objects called m_files, as follows:
File[] m_files = null;
The code fragment in Figure 72 shows the last part of the FileCreator.run() method (defined in the ArmyAgent5.java file):
Figure 72. Providing file content
for (int i=0; i<fileV.size(); i++) m_agent.m_files[i] = (File) fileV.get(i); }
ODKUtility.getODKUtility.contentComplete( new ContentMetaData(ContentType.BinaryFile, 0, m_agent.m_files.length); } // end of run() in FileCreator class
Figure 72 handles the generated content as follows:
The Roman Army sample ODA uses the m_files array as its generated-content structure. To save the files it has generated, run() saves them in this m_files array. This step occurs after run() has generated all files. Business Object Wizard can access the m_files array through a call to the content-retrieval method, getBinFile().
The run() method calls the contentComplete() method,
passing it a new ContentMetaData object. Into this
ContentMetaData() constructor, run() passes the
information shown in Table 49.
Table 49. Initializing the content metadata for file generation
ContentMetaData information | Code | Description |
---|---|---|
Content type | ContentType.BinaryFile |
Indicates that the content type is files
|
Size of the generated content | 0 |
Indicates that total size is not required. The length
value is not needed in the current implementation of a
ContentMetaData object.
|
Count of the generated content | m_files.length |
The length member variable contains the number of elements
currently in the array.
|
The generateBinFiles() method does not return the actual generated business object definitions. For Business Object Wizard to be able to access the generated content, the ODA class must implement the content-retrieval method for files. Business Object Wizard uses the information in the content-metadata object (which generateBinFiles() does return) to determine which content-retrieval method to call. For file content, Business Object Wizard calls the getBinFile() method to retrieve the generated business object definitions.
Regardless of the content protocol your ODA supports for generation of
files, the ODA class must implement the getBinFile() method.
This method is defined as part of the
IGeneratesBinFiles interface. The method accepts as an argument
an index, which identifies the number of files to return. It accesses
these files in the generated-content structure and returns an array of the
retrieved file (File) objects. The number of files in this
array depends on the value of the index argument, as Table 50 shows.
For the sample Roman Army ODA, the FileCreator.run() method (defined in the ArmyAgent5 class) populates the m_files array with the generated files. Therefore, the getBinFile() method (also defined in ArmyAgent5) retrieves the specified number of files from this array. The following code shows the getBinFile() method for the sample Roman Army ODA:
public File[] getBinFile(long index) throws ODKException { if (index == ODKConstant.GET_ALL_OBJECTS) return m_files; else return new File[] {m_files[(int)index]}; }