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 58). It defines the generateBinDefs() method in the ArmyAgent5 class. This implementation of the method includes the code in Figure 69, which defines the generateBinFiles() method so that it throws an exception if it is ever called.
Figure 69. 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 47 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 70 shows the last part of the FileCreator.run() method (defined in the ArmyAgent5.java file):
Figure 70. 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 70 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 47.
Table 47. 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. |