/* UpdatableList.java
* Authors: Jocelyn Becker and Sagar
* Last modified Sep 5 2000
*
* This data field displays itself as a SELECT list.
* It reads the menu options from an XML file.
* The data field creates a new instance of myObject to hold
* the selected value. Then it saves the object to a file
* in the application directory.
* The selected option is read back from the object
* when the data field is displayed again.
*/
/* The class definition of myObject is:
import java.io.*;
public class myObject implements Serializable {
String value;
//String var2;
//String var3;
public myObject () {
}
}
*/
package customer.fields;
import com.netscape.pm.model.*;
import com.netscape.pm.fields.*;
import com.netscape.pm.htmlFE.*;
import java.io.*;
import java.util.*;
public class UpdatableList extends BasicCustomField implements IPresentationElement ,IDataElement{
// The name of the file that stores the menu options
// This is global across all process instances
public String myFileName;
public UpdatableList(){
super();
}
// Method from BasicCustomeField that loads
// properties that were set in the Builder
protected void loadDataElementProperties(Hashtable entry ) throws Exception {
// Get the XML File name from the Builder properties
myFileName = (String)entry.get("xmlfile");
}
/* The display() method for a work item
* displays the data field in a form in the
* work item as a SELECT menu whose name is the same as the datafield name.
* If there is no initial selection, the default selection is "Choose now"
* If a value has previously been selected, this value
* is retrieved by calling getData() which in turn invokes load()
* to load the value from the external store.
*/
public void display(IProcessInstance pi, IHTMLPage html, int displayMode, String displayFormat ) throws Exception {
System.out.println("Entering display in work item");
StringBuffer buffer = new StringBuffer();
String selectedOption = null;
// Get the value of the data field
// If the value is not loaded, getData invokes load()
myObject myobj = (myObject) pi.getData(getName());
// If an object is found, set the selected option
// to the value of the object's myvalue variable.
if (myobj != null) {
selectedOption = myobj.myvalue;
}
switch(displayMode){
// In edit mode, display the data field as a SELECT menu
// The menu options are stored in an xml file
case MODE_EDIT:
// Get the option names from the xml file and store
// them in the vector optionNames.
Vector optionNames = fetchDataFromXML();
buffer.append("");
break;
case MODE_VIEW:
// In View mode, display the selected option as a string
// The user cannot change the value in View mode
buffer.append(" "+ selectedOption);
break;
}
// Write the contents to the HTML page
html.write(buffer.toString());
}
/* The display method for an entry point
* displays the data field in an entrypoint form
* as a SELECT menu whose name is the same as the data field name.
* In this case, there will be no previously selected value in edit mode.
* The data field should not be displayed in view mode.
*/
public void display(IHTMLPage html, int displayMode, String displayFormat ) throws Exception {
StringBuffer buffer = new StringBuffer();
switch(displayMode){
case MODE_EDIT:
// Get the option names from the xml file and store
// them in the vector optionNames.
Vector optionNames = fetchDataFromXML();
//The selected option is "Choose now"
buffer.append("");
break;
// Display a warning in view mode.
// We hope that the developer will see this during testing.
case MODE_VIEW:
buffer.append("Incorrect use of this datafield,");
buffer.append(" in an Entry Point!!!");
break;
}
// Write the contents to the HTML page
html.write(buffer.toString());
}
// The update() method parses the form parameters when
// the HTML form is submitted.
// In this case, it creates a new instance of myObject
// whose "myvalue" variable is set to the value of the form element
// that has the same name as this data field.
// The new object is put into the process instance
public void update(IProcessInstance pi, IPMRequest rq ) throws Exception {
// Create a new myObject to hold the results
myObject obj1 = new myObject();
try {
obj1.myvalue = (String) rq.getParameter(getName());
// put the object into the pi
pi.setData(getName(), obj1);
}
catch (Exception e) {
System.out.println("Problem translating the form values: " + e);
}
}
// The load() method generates and sets the value of the data field.
// This method is called if getData() is invoked when the
// data field value is not already loaded.
// In this case, read the object from the file
// and get its "myvalue" variable
public void load(IProcessInstance pi) throws Exception
{
// Get the name of the file. It is stored as the entity key.
// An example is thisfield123.txt
String thisFileName = (String) pi.getEntityKey(getName());
if (thisFileName != null)
{
try {
// Get a handle to the file at the location
// in the application directory
// eg rootdir/Applications/myApplication/thisfield123.html
String myPath = getMyApplicationsPath();
thisFileName = myPath + "\\" + thisFileName;
// Get a file reader and read in the object
FileInputStream fis = new FileInputStream(thisFileName);
ObjectInputStream ois = new ObjectInputStream(fis);
myObject newobj = (myObject) ois.readObject();
// Put the object in the data field in the process instance
pi.setData(getName(), newobj);
}
catch (Exception e)
{
System.out.println("Error while reading value from file: " + e);
}
}
else {
pi.setData(getName(), null);
}
}
// The store method stores the value of the data field in
// external storage to make it persistent.
// In this case, we store the value as an object in a file whose
// name is dataFieldNamePID.html, for example thisDataField123.txt
public void store(IProcessInstance pi) throws Exception{
// Get the data field name
String thisID = getName();
// Get the process instance ID
long procID = pi.getInstanceId();
// Concatenate the data field name with the PID
// to keep the name unique across all process instances
thisID = thisID + procID;
String thisFileName = thisID + ".txt";
// Store the file name as the entity key
pi.setEntityKey(getName(), thisFileName);
// Get the application directory
String appdir = getMyApplicationsPath();
// Generate the file name where the value will be stored
thisFileName = appdir + "\\" + thisFileName;
// Get the value of the data field from the pi,
// which should be an instance of myObject
myObject myobj = (myObject) pi.getData(getName());
// Write the object to a file
try {
FileOutputStream fos = new FileOutputStream(thisFileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(myobj);
}
catch (Exception e)
{System.out.println("Error while storing data field value to file:" + e);
}
// end store method
}
public void create(IProcessInstance pi) throws Exception {
// no default value
System.out.println("entering create method but doing nothing here");
}
// Fetch the set of menu options from the XML file
public Vector fetchDataFromXML(){
Vector optionNames = new Vector();
try
{
int MAX_LENGTH = 2000;
char xml[] = new char[MAX_LENGTH];
// Get the path for the xml file
// myFileName is a global variable --
// it is the same for all process instances
String Path = getMyApplicationsPath();
Path = Path + "\\" + myFileName;
// Get a file reader
java.io.File f = new java.io.File(Path);
FileReader fr = new FileReader(f);
BufferedReader in = new BufferedReader(fr);
int count =0;
// Read the entire xml file into the array xml
count = in.read(xml, count, MAX_LENGTH);
String charSet = new String(xml);
int charSetLength = charSet.length();
count = 0;
for(; count < charSetLength; count++)
{
parseForItemTag(count, charSetLength, charSet, optionNames);
}
}
catch(Exception e)
{
System.out.println("Error while fetching data from xml file : " + e);
}
// return the vector of option names
return optionNames;
}
/// This method parses an array of characters
// to extract the items embedded ini ... tags
public void parseForItemTag (int count, int charSetLength, String charSet, Vector optionNames)
{
String temp;
Object tempobj;
if(charSet.charAt(count) == '<' )
{
temp = "";
for(; charSet.charAt(count) != '>'; count++)
{
temp = temp + charSet.charAt(count);
}
temp = temp + charSet.charAt(count);
count++;
if(temp.equalsIgnoreCase(""))
{
for(temp = ""; charSet.charAt(count) != '<' ; temp = temp + charSet.charAt(count++))
// Really weird,but it won't compile for me without the following line!
temp = temp;
// Convert the string to an object and
// add the object to the vector of options
tempobj = (Object) temp;
optionNames.addElement(tempobj);
}
}
}
// Returns the path to the folder where the application is saved
String getMyApplicationsPath ()
{
String path = "";
try {
path = getPMApplication().getHomePath();
}
catch (Exception e) {
System.out.println("Exception while getting application path" + e);
}
return path;
}
// Use this function for debugging if necessary
// to read the object from the file after storing it.
public void readMyObject (String filename) {
System.out.println("Entering readMyObject");
// read the object from the file
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
myObject mo = (myObject) ois.readObject();
System.out.println ("value: " + (String) mo.myvalue);
}
catch (Exception e)
{System.out.println(e);
}
System.out.println("Exiting readMyObject");
}
// end of class
}