/* 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(" it must be in EDIT Mode 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 }