/*
   Tamot --- Task Modelling Editor
   Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
   (CSIRO), Australia. All rights reserved. 

   The Software, owned by CSIRO Australia, has been developed by the CSIRO 
   Intelligent Interactive Technology group. 
   For more information, please see http://www.cmis.csiro.au/iit/.

   Redistribution in source and binary forms, with or without modification, are not permitted.

   The Software is a beta-test version for internal research and evaluation purposes 
   by the Licensee. The Software is still at a development stage. 
   It has not undergone complete testing and may have inherent errors,
   bugs or deficiencies that can affect the operation of the Software. 

   We encourage your feedback and suggestions. Any bugs / suggestions found please email to
   Shijian.Lu@cmis.csiro.au and Thomas.Lo@cmis.csiro.au. 

   After you have signed the Beta-Test Software License Agreement with the CSIRO,
   CSIRO grants you a non-exclusive, non-transferable license to use it only for your 
   personal, non-commercial and lawful end use. Implied licenses are negated. 

   Warranty Disclaimer : 

   CSIRO supplies the Software on an "as is" basis and makes no warranties that use of
   the Software by the Licensee will not infringe any third party’s 
   Intellectual Property Rights nor that the Software will be of merchantable quality,
   or suitable for a particular purpose. CSIRO excludes all terms, conditions and
   warranties implied by custom, the general law or statute in relation to the
   Software.
*/

package taskModellingTool;

import domainModel.*;
//import parser.FSParser.*;

import java.io.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.text.rtf.*;
import javax.swing.text.html.*;
import java.lang.reflect.*;

import com.icl.saxon.*;
import org.xml.sax.*;
import com.icl.saxon.output.*;
import com.icl.saxon.expr.*;


public class FileManager {

    //tape_recorder
    public static boolean guiEnableFlag = true;

    public static final String ROOT="TM_ROOT_TM";
    public static final String TASK="(Task)";
    public static final String BOOLEAN_CONNECTOR="(Boolean Connector)";
    public static final String LINK="(Sequence)";
    public static final String EXPANSION="(Expansion)";
    public static final String BEGIN_DESCRIPTION="(Description)";
    public static final String END_DESCRIPTION="(/Description)";

    //shijian 2001-3-22
    public static final String BEGIN_WARNING="(Warning)";
    public static final String END_WARNING="(/Warning)";
    public static final String BEGIN_ACTOR="(Actor)";
    public static final String END_ACTOR="(/Actor)";
    public static final String BEGIN_OTHER="(Other)";
    public static final String END_OTHER="(/Other)";
    
    public static final String BEGIN_PRECONDM="(PreconDM)";
    public static final String END_PRECONDM="(/PreconDM)";
    public static final String BEGIN_FEEDBACKDM="(FeedbackDM)";
    public static final String END_FEEDBACKDM="(/FeedbackDM)";
    public static final String BEGIN_LINKCONDM="(LinkconDM)";
    public static final String END_LINKCONDM="(/LinkconDM)";

    public static final String type="png";

    //public static final String FOLDER="save";   
    public static final String DEFAULT_FOLDER="save";  
    public static String FOLDER="save";  
    public static final String DEFAULT_FILE_NAME=MainFrame.TITLE_NEW; 
    public static String FILE_NAME=MainFrame.TITLE_NEW;
    
    public static File CURRENT=null;	//current XML / IMP / TMT file
    public static File CURRENT_EXP=null;
    //public static File CURRENT_TMT=null;
    public static File CURRENT_HTML=null;
    
    public static boolean  MODIFIED=false;     // to monitor whether the Model is changed or not
    
    public static final String INTERNAL_FILE_SUFFIX="tmt";  
    public static final String IMPORT_FILE_SUFFIX="imp";  
    public static final String XML_FILE_SUFFIX="xml";

    public static final String TAB = String.valueOf((char) 9);
    public static final String XML_VERSION="V.2.0";
    
    public static JProgressBar progressbar =null;
    public static  int pBCounter;
    
    private static XManager xDm =Manager.getXDM(); // domain model manager 
    
   // public File f;
            	
    //tape_recorder
    public FileManager(boolean guiEnableFlag) {
        this.guiEnableFlag = guiEnableFlag;
    }
    
    public static void save(File f){
    	try{
    	    ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(f));
    	    out.writeObject(Manager.skeleton);
    	    ////3-10-2001 out.writeObject(Manager.RTFDB);
    	    out.writeObject(Manager.dmManager);
    	    out.close();
    	} catch (IOException e){System.out.println("Error: "+(e.toString()));}
    }
    
    public static void open(File f){
    	try{
    		//Thomas
    		//System.out.println("Opening file "+f.getAbsolutePath()+" ...");
    	    ObjectInputStream in=new ObjectInputStream(new FileInputStream(f));
    	    
	        Manager.skeleton=(KernelTree)in.readObject();
	        ////3-10-2001 Manager.RTFDB=(RTFDataBase)in.readObject();
	        Manager.dmManager=(DomainModelManager)in.readObject();
	        in.close();
    	}
    	//Thomas
    	catch (InvalidClassException e) {
            System.out.println(System.getProperty("java.class.path","."));
    		System.out.println("InvalidClassException : "+(e.toString()));
    		System.out.println("           Class Name : "+(e.classname));
    	}
    	catch (IOException e) {
    		System.out.println("IOException : "+(e.toString()));
    	}
    	catch (ClassNotFoundException e) {
    		System.out.println("ClassNotFoundException : "+(e.toString()));
    	}
    	//catch (Exception e) {
    	//	System.out.println("Error: "+(e.toString()));
    	//}

        linkValidate();
    }
    
    public static void saveXMLOld(File f) {
        try {
            // create images to find PNG Coordinates
            findPNGCoordinates(Manager.skeleton.root,FOLDER,"ROOT",new TreeSet());

            PrintStream out = new PrintStream(new FileOutputStream(f));
            
            writeXMLHeader(out,f);
            //xDm.printXMLRootHead(xDm.getDoc(), out); 
            
            write_Task_Model_Components_InXML(out);
            write_Task_Model_Decomposition_InXML(out);
            
            // domain model part of XML --- to be modified later
            //ExportationLG.write_Domain_Model_InXML(out);
            out.println(getTABs(1)+"<Domain_Model>");
            ExportationLG.writeDomain(out);
            out.println(getTABs(1)+"</Domain_Model>");
            
            //xDm.printDOMTree(xDm.getDoc(), out); 

            
            writeXMLFooter(out);
            //xDm.printXMLFooter( xDm.getDoc(), out);
            
            out.close();
        } catch (IOException e) {
            System.out.println("Error: "+(e.toString()));
        }
    }
    
    public static void saveXML(File f) {
        try {
            // create images to find PNG Coordinates
            findPNGCoordinates(Manager.skeleton.root,FOLDER,"ROOT",new TreeSet());

            PrintStream out = new PrintStream(new FileOutputStream(f));
            
    	    //shijian 2001-3-29
           	if (Manager.systemOptions.domainModelFlag &&
           		Manager.guiEnableFlag) 
           		saveXMLTDM(out,f);
           	else
           		saveXMLTM(out,f);
           		
        } catch (IOException e) {
            System.out.println("Error: "+(e.toString()));
        }
     	//System.out.println("now copy DTD");

        // copy the specified DTD in f from cfg subdirectory into the directory of f
        copy_DTD_OK(f);
        
        // copy XSL from cfg subdirectory into the directory of f
        //copy_XSL_OK(f);
    }
    
    //shijian 2001-3-29
    //save both task and domain model contents
    public static void saveXMLTDM(PrintStream out,File f) {
        xDm.updateDoc();
        xDm.printXMLRootHead(xDm.getDoc(), out); 
             
        write_Task_Model_Components_InXML(out);
        write_Task_Model_Decomposition_InXML(out);
        xDm.printDOMTree(xDm.getDoc(),null, out); 

        xDm.printXMLFooter( xDm.getDoc(), out);
        
        out.close();
        return;
    	
    }
    
    //shijian 2001-3-29
    //save only task model contents
    public static void saveXMLTM(PrintStream out, File f) {   	
        writeXMLHeader(out,f);
        write_Task_Model_Components_InXML(out);
        write_Task_Model_Decomposition_InXML(out);
        writeXMLFooter(out);
        out.close();
        return;
    	
    	
    }

    public static void saveASCII(File f) {
    	try {
    	    PrintStream out=new PrintStream(new FileOutputStream(f));
    	    writeComponents(out);
    	    writeExpansions(out);
    	    
    	    //ExportationLG.writeDomain(out);
    	    	
    	    out.close();
    	} catch (IOException e) {
    		System.out.println("Error: "+(e.toString()));
    	}
    }
    
    public static void openASCII(File f) {
        try {
//            System.out.println("Are we openning3");
            BufferedReader in=new BufferedReader(new FileReader(f));
            pBCounter = pBCounter +2;
            Manager.progressBarValue= pBCounter;

            Manager.skeleton=new KernelTree(Manager.ROOT_STRING);
            pBCounter = pBCounter +2; 
            Manager.progressBarValue= pBCounter;
            
            //shijian 2001-10-2
            //Manager.RTFDB=new RTFDataBase();
            Manager.RTFDBM=new RTFManager();

            pBCounter = pBCounter +2; 
            Manager.progressBarValue= pBCounter;
            
            setSkeleton(in);
            pBCounter = pBCounter +2; 
            Manager.progressBarValue= pBCounter;
            
            in.close();
        } catch (Exception e) {
            System.out.println("Error: "+(e.toString()));
        }

         //ExportationLG.importDomain(f);
             
        Toolkit.getDefaultToolkit().beep();
        pBCounter = pBCounter +2; 
        Manager.progressBarValue= pBCounter;                                    
    }
    
    private static String findDTDinFile(File f) {
        String result = null;
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(f));

            String ss1, ss2;
            while ((ss1 = in.readLine()) != null) {
                if (stringContains(ss1,DOCTYPE_XML)) {
                    ss2 = getAttributeXML2(ss1,"SYSTEM");
                    //System.out.println("findDTDinFile ss2="+ss2);
                    
                    if (ss2 != null) {
                        File tmpFile = new File("cfg"+File.separator+ss2);
                        result = tmpFile.getAbsolutePath();
                        //System.out.println("findDTDinFile result="+result);
                    }
                    
                    break;
                }
            }
            
            in.close();
        } catch (Exception e) {
            System.out.println("Error in findDTDinFile : "+(e.toString()));
        }
        
        return result;
    }
    
    public static void displayErrorMessage(String title,String message) {
        String [] options={"OK"};
        int choice = JOptionPane.showOptionDialog(MainFrame.mainFrame,message,title,
            JOptionPane.DEFAULT_OPTION,JOptionPane.ERROR_MESSAGE,null,options,options[0]);
    }
    
    public static boolean copyFile(String sourceFileName, String destFileName) {
        if (destFileName.equals(sourceFileName)) return true;
        
        int CBUF_LENGTH = 3000;  
        try {
            BufferedReader in = new BufferedReader(new FileReader(sourceFileName));
            BufferedWriter out = new BufferedWriter(new FileWriter(destFileName));

            char[] cbuf = new char[CBUF_LENGTH];
            
            int iReadLength;
            while ((iReadLength = in.read(cbuf,0,CBUF_LENGTH)) >= 0) {
                out.write(cbuf,0,iReadLength);
            }
            
            out.close();
            in.close();
            
            return true;
        }
        catch (Exception e) {
            System.out.println("Error in copying file : "+(e.toString()));
            
            return false;
        }
    }
    
    private static boolean copy_DTD_OK(File f) {
        String sourceDTDFileName = findDTDinFile(f);
        if (sourceDTDFileName == null) {
            // give error message
            pBCounter = pBCounter +10;
            Manager.progressBarValue = pBCounter;

            displayErrorMessage("Error in opening the XML file",
                "Error : \nThere is no DTD specified in the XML file.");
            return false;
        }
        
        //System.out.println("Source DTD = "+sourceDTDFileName);
        
        // check if the DTD file exists
        File dtdFile = new File(sourceDTDFileName);
        if (!dtdFile.exists()) {
            pBCounter = pBCounter +10;
            Manager.progressBarValue = pBCounter;

            displayErrorMessage("Error in opening the XML file",
                "Error : \nThe DTD specified in the XML file is not found.");
            return false;
        }

        // copy the DTD file into the directory of file f
        String destDTDFileName = f.getParent()+File.separator+dtdFile.getName();
        //System.out.println("Destination DTD = "+destDTDFileName);

        if (!copyFile(sourceDTDFileName,destDTDFileName)) {
            pBCounter = pBCounter +10;
            Manager.progressBarValue = pBCounter;

            displayErrorMessage("Error in opening the XML file",
                "Error in copying DTD file.");
            return false;
        }
        
        return true;
    }
    
    private static boolean copy_XSL_OK(File f) {
        File xslFile = new File("cfg"+File.separator+"Task_Model.xsl");
        String sourceXSLFileName = xslFile.getAbsolutePath();

        //System.out.println("Source XSL = "+sourceXSLFileName);
        
        // check if the XSL file exists
        if (!xslFile.exists()) {
            pBCounter = pBCounter +10;
            Manager.progressBarValue = pBCounter;

            displayErrorMessage("Error in opening the XML file",
                "Error : \nThe XSL file is not found.");
            return false;
        }

        // copy the XSL file into the directory of file f
        String destXSLFileName = f.getParent()+File.separator+xslFile.getName();
        //System.out.println("Destination XSL = "+destXSLFileName);

        if (!copyFile(sourceXSLFileName,destXSLFileName)) {
            pBCounter = pBCounter +10;
            Manager.progressBarValue = pBCounter;

            displayErrorMessage("Error in opening the XML file",
                "Error in copying XSL file.");
            return false;
        }
        
        return true;
    }
    
    public static boolean openXML(File f,JProgressBarDia jpbarDia) {
        jpbarDia.setTitle("Opening file: " + f.getAbsolutePath());
        jpbarDia.show();
        jpbarDia.timer.start();
        pBCounter = 0;

        // copy the specified DTD in f from cfg subdirectory into the directory of f
        if (!copy_DTD_OK(f)) {
            Manager.progressBarValue = 2*5;
            return false;
        }
        
        // copy XSL from cfg subdirectory into the directory of f
        //if (!copy_XSL_OK(f)) return false;
        
        if (!XMLUtility.checkXmlFileValidation(f)) {
            System.out.println("openXML : XML file validation failed --- "+f.getAbsolutePath());
            Manager.progressBarValue = 2*5;
            return false;
        }
        
        System.out.println("openXML : XML file validation OK --- "+f.getAbsolutePath());
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(f));
            pBCounter = pBCounter + 2;
            Manager.progressBarValue = pBCounter;

            Manager.skeleton = new KernelTree(Manager.ROOT_STRING);
            pBCounter = pBCounter +2; 
            Manager.progressBarValue = pBCounter;
            
            //shijian 2001-10-2
            //Manager.RTFDB=new RTFDataBase(); 
            Manager.RTFDBM=new RTFManager();

            pBCounter = pBCounter +2; 
            Manager.progressBarValue = pBCounter;
            
            if (!setSkeletonFromXML(in)) {
                Manager.progressBarValue = 2*5;
                return false;
            };
            pBCounter = pBCounter +2; 
            Manager.progressBarValue = pBCounter;
            
            in.close();
             
            Toolkit.getDefaultToolkit().beep();
            pBCounter = pBCounter +2; 
            Manager.progressBarValue= pBCounter;    
        } catch (Exception e) {
            System.out.println("Error: "+(e.toString()));
        }

        //ExportationLG.importDomain(f);
        //xDm.parse(f);	// parse domain model XML doc
        //20-2-2002
        if (Manager.getSysOption().getDomainF())
        		xDm.open(f); 

        return true;
    }
    
    public static boolean openXML(File f) {
        // copy the specified DTD in f from cfg subdirectory into the directory of f
        if (!copy_DTD_OK(f)) return false;
        
        if (!XMLUtility.checkXmlFileValidation(f)) return false;
        
        // copy XSL from cfg subdirectory into the directory of f
        //if (!copy_XSL_OK(f)) return false;
        
        try {
            BufferedReader in = new BufferedReader(new FileReader(f));
            //pBCounter = pBCounter +2;
            //Manager.progressBarValue = pBCounter;

            Manager.skeleton = new KernelTree(Manager.ROOT_STRING);
            //pBCounter = pBCounter +2; 
            //Manager.progressBarValue = pBCounter;
            
            //shijian 2001-10-2
            //Manager.RTFDB=new RTFDataBase();
            Manager.RTFDBM=new RTFManager();

            //pBCounter = pBCounter +2; 
            //Manager.progressBarValue = pBCounter;
            
            if (!setSkeletonFromXML(in)) return false;
            //pBCounter = pBCounter +2; 
            //Manager.progressBarValue= pBCounter;
            
            in.close();
        } catch (Exception e) {
            System.out.println("Error: "+(e.toString()));
        }

        //ExportationLG.importDomain(f);
        //xDm.parse(f);    // parse domain model XML doc
        xDm.open(f); 
        
        Toolkit.getDefaultToolkit().beep();
        //pBCounter = pBCounter +2; 
        //Manager.progressBarValue= pBCounter;
        
        return true;
    }
    
    //JProgressBarDia jpbarDia
    public static void openASCII(File f,JProgressBarDia jpbarDia) {
    	jpbarDia.setTitle("Opening file: " + f.getAbsolutePath());
    	jpbarDia.show();
    	jpbarDia.timer.start();
    	pBCounter=0;
    	    		
    	try {
//			System.out.println("Are we openning3");
			BufferedReader in=new BufferedReader(new FileReader(f));
			pBCounter = pBCounter +2;
			Manager.progressBarValue= pBCounter;

			Manager.skeleton=new KernelTree(Manager.ROOT_STRING);
			pBCounter = pBCounter +2; 
			Manager.progressBarValue= pBCounter;
			
            //shijian 2001-10-2
            //Manager.RTFDB=new RTFDataBase();
            Manager.RTFDBM=new RTFManager();

			pBCounter = pBCounter +2; 
			Manager.progressBarValue= pBCounter;
			
			setSkeleton(in);
			pBCounter = pBCounter +2; 
			Manager.progressBarValue= pBCounter;
			
			in.close();
			 
			Toolkit.getDefaultToolkit().beep();
			pBCounter = pBCounter +2; 
			Manager.progressBarValue= pBCounter;	
    	} catch (Exception e) {
    		System.out.println("Error: "+(e.toString()));
    	}

 		ExportationLG.importDomain(f);
    }
    
    public static void saveLG(File f) {
    	ExportationLG.export(f);
    }

    public static void saveHTMLfromXSL(File f) {
        // get Style Sheet File
        File curDirectory = new File(getFolder());
        //File styleSheetFile = new File(curDirectory.getAbsolutePath()+File.separator+"Task_Model.xsl");
        File styleSheetFile = new File("cfg"+File.separator+"Task_Model.xsl");
        //System.out.println("Absolute : "+styleSheetFile.getAbsolutePath());
        
        try {
            MainFrame.mainFrame.setCursor(Manager.waitCursor);

            // prepare Style Sheet
            PreparedStyleSheet sheet = new PreparedStyleSheet();
            sheet.prepare(new ExtendedInputSource(styleSheetFile));
            
            // make Style Sheet instance
            StyleSheetInstance instance = sheet.makeStyleSheetInstance();

            // set Output Details
            OutputDetails details = new OutputDetails();
            details.setOutputStream(new FileOutputStream(f));
            instance.setOutputDetails(details);
            
            // set parameter set
            ParameterSet params = new ParameterSet();
            addParameterSet(params);
            instance.setParams(params);
            
            // generate HTML document from the style sheet
            instance.renderSource(new ExtendedInputSource(CURRENT));

            // create images
            imagesCreation(Manager.skeleton.root,FOLDER,"ROOT",new TreeSet());
        }
        catch (SAXException err1) {
            System.out.println("Error applying stylesheet: " + err1.getMessage());         
        }
        catch (Exception err2) {
            System.out.println("Error applying stylesheet: " + err2.getMessage());         
        }
        finally {
            MainFrame.mainFrame.setCursor(Manager.normalCursor);
            Toolkit.getDefaultToolkit().beep();
        }
    }
    
    private static void addParameterSet(ParameterSet params) {
        String fieldName;
        
        for (Iterator it = Manager.filedsKeyForHTML.keySet().iterator();it.hasNext();) {
            fieldName = (String)it.next();
            
            if (fieldName.equals("minCard")) fieldName = "cardinality";
            if (fieldName.equals("maxCard")) fieldName = "cardinality";
            
            params.put(fieldName.intern(),new StringValue("y"));
        }
    }
////3-10-2001 
    
    public static void saveHTML_old(File f) {
    	final String BEGIN_BODY="<body>";
    	final String END_BODY="</body>";
    	
    	final String BEGIN_COMPONENT=" <HR size=\"1\">    <TABLE BORDER=\"0.5\" CELLPADDING=\"3\" CELLSPACING=\"0\" WIDTH=\"100%\"><TR BGCOLOR=\"#F2E8D3\" ID=\"TableHeadingColor\"><TD COLSPAN=2><FONT SIZE=\"+1\"><CENTER><B>";
    	final String END_COMPONENT="    </B></CENTER></FONT></TD></TR></TABLE>";
    	
    	final int lbb=BEGIN_BODY.length();
    	final int leb=END_BODY.length();
    	try {
    		PrintWriter out=new PrintWriter(new FileWriter(f));
    		CharArrayWriter tempOut;
    		BufferedReader tempIn;
    		
    		//Thomas
    		//HTMLEditorKit kit;
			MinimalHTMLWriter2 w;   // modify MinimalHTMLWriter in order to fix its bug

    		String name;
    		String s;
    		boolean body;
    		DefaultStyledDocument doc;
    		//shijian 2001-10-2
    		//Set keys = Manager.RTFDB.keySet();
  			Set keys=Manager.skeleton.nodeRegister.keySet();
    	
    		//out.println("<HR>");
    		out.println("<html>");
    		out.println("  <body>");

    		out.println(BEGIN_COMPONENT);
    		out.println("      "+"Root");
    		out.println(END_COMPONENT);
    		out.println("    <IMG SRC=\""+"Root"+"."+type+"\">");

    		//Thomas
        	addDetailsForSubtasks("/",out);
    	
    		for (Iterator i=keys.iterator();i.hasNext();) {
    	    	name = (String)i.next();
    	    	GenericComponent gc=Manager.skeleton.stringToFirstGenericComponent(name);
    	    	if ((gc instanceof Task)||(Manager.RTFDB.containsKey(name))) {
    	      		doc = Manager.RTFDB.getDocument(name);
    	      		if ((gc instanceof Task)||(doc.getLength()>0)) {
    	        		//Thomas
        	        	//kit=new HTMLEditorKit();
    	      			tempOut = new CharArrayWriter();
	    				w = new MinimalHTMLWriter2(tempOut,doc,0,doc.getLength());
	    				w.write();
    	    		    
    	        		tempOut.close();
    	        		tempIn = new BufferedReader(new CharArrayReader(tempOut.toCharArray()));
    	        		body = false;
    	        		boolean stop=false;
    	        		boolean first=false;
    	        		int l;
    	        		while ((s=tempIn.readLine())!=null) {
  	    	    		    //System.out.println("comment text = "+s);           //Thomas
    	    	    		l=s.length()-lbb;
    	    	    		for (int j=0;j<=l;j++) {
    	    	        		if (s.substring(j,j+lbb).equals(BEGIN_BODY)) {
    	    	    	    		s=tempIn.readLine();
    	    	    	    		body=true;
    	    	    	    		first=true;
    	    	    	    		break;
    	    	        		}
    	    	    		}
    	    	    		l=s.length()-leb;
    	    	    		for (int j=0;j<=l;j++) {
    	    	        		if (s.substring(j,j+leb).equals(END_BODY)) {
    	    	    	    		stop=true;
    	    	    	    		break;
	    	    	        	}
    		    	    	}
    		    	    	if (stop) break;
    	    		    	if (first) {
    	    		    		// <HR color="#0000ff" noshade size="5">
	                	        // out.println("<HR>");
    		    	    	    out.println(BEGIN_COMPONENT);
    		    	        	out.println("      "+name);
	    	    		        out.println(END_COMPONENT);
                        
    		    		        if (gc instanceof Task) {
    		    	    	    	Task t=(Task)gc;

		                            selectTaskAttributes(t,out);

    		    		            if (Manager.skeleton.hasChildNode(name)) {
    		    	    		        out.println(" <P>   <IMG SRC=\""+name+"."+type+"\"> </P>");
    	    	    	        
    	    		    		        //Thomas
    	    		    	    	    addDetailsForSubtasks(name,out);
	    	    	    	        }
    		    	        	}

	    	                    if (body) {
    			    	            String comment = "   <FONT SIZE=\"-1\" align=\"left\"><I><B> comment: </B></I></FONT>";  
        	    	                out.print(comment);
    	    			        }
    	    		    	    first=false;
	    	    	    	}
		    	    	    if (body) {
                      			out.println(s);
		                    }
    			        }
    			        tempIn.close();
    	    		}
	    	    }
    		}
    
    		out.println("  </body>");
    		out.println("</html>");

    		out.close();
    	
	     	MainFrame.mainFrame.setCursor(Manager.waitCursor);

    		imagesCreation(Manager.skeleton.root,FOLDER,"ROOT",new TreeSet());//"save/","ROOT",new TreeSet());

    	    MainFrame.mainFrame.setCursor(Manager.normalCursor);
	   		Toolkit.getDefaultToolkit().beep();

   			System.out.println("folder name : " +  FOLDER);
    	}
    	catch (Exception e) {
    		System.out.println("Error: "+(e.toString()));
    	}
    }
    
    
    //Thomas - add full text for feedback & precondition of subtasks
    private static void addDetailsForSubtasks(String name, PrintWriter out) {
        boolean feedbackFlag = false;
        boolean preconditionFlag = false;
        for (Iterator it = Manager.filedsKeyForHTML.keySet().iterator(); it.hasNext();)
        {
            String key = (String)it.next();
            if (key.equals("feedback")) feedbackFlag = true;
            if (key.equals("precondition")) preconditionFlag = true;
        }
        
        if ((!feedbackFlag) && (!preconditionFlag)) return;

    	Node node = Manager.skeleton.toChildNode(name);
        Set set = node.keySet();
        int i = 0;
        for (Iterator it = set.iterator(); it.hasNext();) {
            GenericComponent gc = node.getComponent((String)it.next());
            
            if (gc instanceof Task) {
            	Task task = (Task) gc;

            	boolean prtFeedbackFlag = false;
            	if ((feedbackFlag) && (!task.feedback.equals(""))) prtFeedbackFlag = true;
            	
            	boolean prtPreconditionFlag = false;
            	if ((preconditionFlag) && (!task.precondition.equals(""))) prtPreconditionFlag = true;
            	
            	if (prtFeedbackFlag || prtPreconditionFlag) {
          			out.println("<ul>");
            		if (prtFeedbackFlag) {
            			String s = "<li><FONT SIZE=\"-1\"><I><B>feedback for \""+task.name+"\"</B></I></FONT>";
            			out.print(s);
                    	out.println(" : "+task.feedback+ "<BR></li>");
            		}
            	
            		if (prtPreconditionFlag) {
            			String s = "<li><FONT SIZE=\"-1\"><I><B>precondition for \""+task.name+"\"</B></I></FONT>";
            			out.print(s);
                    	out.println(" : "+task.precondition+ "<BR></li>");
            		}
           			out.println("</ul>");
            	}
            }
            i++;
        }
    }
   

    private static void imagesCreation(Node node,String prefix,String name,Set already) {
    	if (!already.contains(name)) {
	     	already.add(name);
            
    	    if (type.equals("png")) ImageGenerator.createPNG(node,prefix+File.separator+name+"."+type);
    	    else if (type.equals("jpg")) ImageGenerator.createJPEG(node,prefix+ File.separator+name+"."+type);
            
            Set set = node.keySet();
            GenericComponent gc;
            String childName;
            for (Iterator i = set.iterator();i.hasNext();) {
            	childName = (String)i.next();
            	if (node.hasBranch(childName)) 
                    imagesCreation(node.getChild(childName),prefix,childName,already); 
            }
        }
    }

    private static void findPNGCoordinates(Node node,String prefix,String name,Set already) {
        if (!already.contains(name)) {
             already.add(name);
            
            if (type.equals("png")) ImageGenerator.findPNGCoordinates(node,prefix+File.separator+name+"."+type);
            
            Set set = node.keySet();
            GenericComponent gc;
            String childName;
            for (Iterator i = set.iterator();i.hasNext();) {
                childName = (String)i.next();
                if (node.hasBranch(childName)) 
                    findPNGCoordinates(node.getChild(childName),prefix,childName,already); 
            }
        }
    }
    
    public static void importDomain(){
    	ExportationLG.importDomainChooser();
    }

    
    public static boolean exportHTML(){
    	final JFileChooser fc = new JFileChooser(getFolder());
    	fc.addChoosableFileFilter(new HTMLFilter());
        fc.setFileView(new HTMLFileView());
        
        // showDialog(Component parent, String approveButtonText)
        if (CURRENT_HTML != null) fc.setSelectedFile(CURRENT_HTML);
        
        String approveButtonText="Generate HTML";
        int returnVal=fc.showDialog(MainFrame.mainFrame,approveButtonText);
									   //showSaveDialog(MainFrame.mainFrame);
        
        //fc.setApproveButtonText(approveButtonText);

        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f=fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();
            CURRENT_HTML =f;
            
            javax.swing.filechooser.FileFilter ff = fc.getFileFilter();
            if (ff instanceof HTMLFilter) saveHTML(addExtensionIfNecessary(f,FileTypes.html));
        }
        return (returnVal==JFileChooser.APPROVE_OPTION);
    }

    public static boolean exportHTMLfromXSL() {
        final JFileChooser fc = new JFileChooser(getFolder());
        fc.addChoosableFileFilter(new HTMLFilter());
        fc.setFileView(new HTMLFileView());
        
        if (CURRENT_HTML != null) fc.setSelectedFile(CURRENT_HTML);
        
        String approveButtonText="Generate HTML from XSL";
        int returnVal = fc.showDialog(MainFrame.mainFrame,approveButtonText);
        
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File f = fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();
            CURRENT_HTML = f;
            
            javax.swing.filechooser.FileFilter ff = fc.getFileFilter();
            if (ff instanceof HTMLFilter) saveHTMLfromXSL(addExtensionIfNecessary(f,FileTypes.html));
        }
        
        return (returnVal == JFileChooser.APPROVE_OPTION);
    }

    public static boolean exportLG(){
    	final JFileChooser fc=new JFileChooser(getFolder());
    	fc.addChoosableFileFilter(new LGFilter());
        fc.setFileView(new LGFileView());
        if (CURRENT_EXP != null) fc.setSelectedFile(CURRENT_EXP);
        String approveButtonText="Export LISP";
        int returnVal=fc.showDialog(MainFrame.mainFrame,approveButtonText);
						//MainFrame.mainFrame);
        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f=fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();  
            CURRENT_EXP =f;          
            
            javax.swing.filechooser.FileFilter ff=fc.getFileFilter();
            if (ff instanceof LGFilter) saveLG(addExtensionIfNecessary(f,FileTypes.exp));
        }
        return (returnVal==JFileChooser.APPROVE_OPTION);
    }
    
    
    public static boolean exportGenerateLG(){
    	final JFileChooser fc=new JFileChooser(getFolder());
    	fc.addChoosableFileFilter(new LGFilter());
        fc.setFileView(new LGFileView());
        if (CURRENT_EXP != null) fc.setSelectedFile(CURRENT_EXP);
        String approveButtonText="Export and Generate";
        int returnVal=fc.showDialog(MainFrame.mainFrame,approveButtonText);
						//MainFrame.mainFrame);
        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f=fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();  
            CURRENT_EXP =f;          
            
            javax.swing.filechooser.FileFilter ff=fc.getFileFilter();
            if (ff instanceof LGFilter) saveLG(addExtensionIfNecessary(f,FileTypes.exp));
        }
        return (returnVal==JFileChooser.APPROVE_OPTION);
    }

    
    public static boolean save() {
        if (CURRENT != null && CURRENT.isFile()) {
            if (CURRENT.getName().endsWith(INTERNAL_FILE_SUFFIX)) {								
            	save(CURRENT);
            	return true;
            }
            else if (CURRENT.getName().endsWith(IMPORT_FILE_SUFFIX)) {
                saveASCII(CURRENT);
                return true;
            }                
            else {
                //return saveAs();
                saveXML(CURRENT);
                
                // save IMP file as backup in case XML file has validation errors
                saveImpBackup(CURRENT);

                if (!checkXMLFile(CURRENT)) return false;
                
                return true;
            }
        }
        else {
        	//Thomas
         	return saveAs();
	 		//return true;
        }
    }         
            
    private static boolean checkXMLFile(File f) {
        if (!XMLUtility.checkXmlFileValidation(f)) {
            return false;
        }

        System.out.println("XML file validation OK");
        
        return true;
    }
    
    //tape_recorder
    public static boolean saveAs(String fileName) {
        File fTemp = new File(fileName);
        
        fTemp = addExtensionIfNecessary(fTemp,FileTypes.xml);

        saveXML(fTemp);
        //saveXMLOld(fTemp);
        
        FOLDER = fTemp.getParent();
        FILE_NAME = fTemp.getName();
        CURRENT = fTemp;

        if (guiEnableFlag) {
            MainFrame.TITLE_VARIABLE = fTemp.getAbsolutePath();
        }
        
        if (!checkXMLFile(fTemp)) return false;
        
        return true;
    }
            
    //tape_recorder
    public static boolean readXML(String fileName) {
        File f = new File(fileName);

        FOLDER = f.getParent();
        FILE_NAME = f.getName();
        CURRENT = f;

        if (guiEnableFlag) {
            MainFrame.TITLE_VARIABLE = f.getAbsolutePath();
        }
        
        return (openXML(f));
    }
    
    public static boolean saveAs(){
    	final JFileChooser fc = new JFileChooser(getFolder());
    	
        if (CURRENT != null) {
            String fileName = CURRENT.getName();
            
        	if (fileName.endsWith(INTERNAL_FILE_SUFFIX)) {								
     			fc.addChoosableFileFilter(new IMPFilter());	
                fc.addChoosableFileFilter(new XMLFilter());
                fc.addChoosableFileFilter(new TMTFilter()); // show .TMP first
            }
            else if (fileName.endsWith(XML_FILE_SUFFIX)) {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new IMPFilter());
                fc.addChoosableFileFilter(new XMLFilter()); // show .xml first
            }
            else {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new XMLFilter());
     			fc.addChoosableFileFilter(new IMPFilter());	// show .imp first
            }                

        	fc.setSelectedFile(CURRENT);        	
        } else {
        	fc.addChoosableFileFilter(new TMTFilter());
    		fc.addChoosableFileFilter(new IMPFilter());
            fc.addChoosableFileFilter(new XMLFilter());
        }
        
        fc.setFileView(new TMTFileView());

        
        //Thomas : allow to navigate to sub-directories
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        
    	int returnVal;
    	do {
	        //int returnVal=fc.showSaveDialog(MainFrame.mainFrame);
    		returnVal=fc.showSaveDialog(MainFrame.mainFrame);  //showSaveDialog(fc.getParent());
    		if (returnVal == JFileChooser.CANCEL_OPTION) break;

    		File tmpFile = fc.getSelectedFile();
   			if (tmpFile.isDirectory()) 
	    		fc.setCurrentDirectory(tmpFile);
   			else
   				break;
    	} while (true);
        
        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f = fc.getSelectedFile();
            
            while (!fileOverWrite(f)) {
            	returnVal = fc.showSaveDialog(MainFrame.mainFrame);
                
            	if (returnVal==JFileChooser.APPROVE_OPTION) 
            		f=fc.getSelectedFile();
            	else return false;
            }
            
            File fTemp = f;
            javax.swing.filechooser.FileFilter ff = fc.getFileFilter();
            if (ff instanceof TMTFilter) {
            	fTemp = addExtensionIfNecessary(f,FileTypes.tmt);
            	save(fTemp);
            }
            else if (ff instanceof XMLFilter) {
                fTemp = addExtensionIfNecessary(f,FileTypes.xml);
                saveXML(fTemp);
                
                // save IMP file as backup in case XML file has validation errors
                saveImpBackup(fTemp);

                if (!checkXMLFile(fTemp)) return false;
            }
            else {//if (ff instanceof IMPFilter) {
            	fTemp = addExtensionIfNecessary(f,FileTypes.imp);
            	saveASCII(fTemp);
            }
            //else System.out.println("no filefilter");
            
            FOLDER = fTemp.getParent();
            FILE_NAME = fTemp.getName();
            CURRENT =fTemp;
            MainFrame.TITLE_VARIABLE = fTemp.getAbsolutePath();
        }
        
        return (returnVal==JFileChooser.APPROVE_OPTION);
    }

    private static void saveImpBackup(File f) {
        File fTemp = f;
        
        // remove .xml extension in fTemp
        String fileName = fTemp.toString();
        int index = fileName.indexOf(".xml");
        if (index >= 0) {
            fileName = fileName.substring(0,index);
            fTemp = new File(fileName);
        }
        
        //System.out.println("saveImpBackup : fTemp1 = "+fTemp.toString());
        
        fTemp = addExtensionIfNecessary(fTemp,FileTypes.imp);
        
        //System.out.println("saveImpBackup : fTemp2 = "+fTemp.toString());
        
        saveASCII(fTemp);
    }

    public static boolean open(){
    	final JFileChooser fc = new JFileChooser(getFolder());
    
    /*	fc.addChoosableFileFilter(new TMTFilter());
    	fc.addChoosableFileFilter(new IMPFilter());
    	
        fc.setFileView(new TMTFileView());
        if (CURRENT != null) fc.setSelectedFile(CURRENT);
     */
     
        if (CURRENT != null) {
        	if (CURRENT.getName().endsWith(INTERNAL_FILE_SUFFIX)) {								
     			fc.addChoosableFileFilter(new IMPFilter());	
                fc.addChoosableFileFilter(new XMLFilter());    
                fc.addChoosableFileFilter(new TMTFilter()); // show .TMP first
            }
            else if (CURRENT.getName().endsWith(IMPORT_FILE_SUFFIX)) {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new XMLFilter());    
     			fc.addChoosableFileFilter(new IMPFilter());	// show .imp first
            }                
            else {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new IMPFilter());
                fc.addChoosableFileFilter(new XMLFilter()); // show .xml first    
            }

        	fc.setSelectedFile(CURRENT);        	
        } else {
        	fc.addChoosableFileFilter(new TMTFilter());
    		fc.addChoosableFileFilter(new IMPFilter());
            fc.addChoosableFileFilter(new XMLFilter());    
        }
        
        fc.setFileView(new TMTFileView());
     
    	int returnVal=fc.showOpenDialog(MainFrame.mainFrame);
        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f=fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();
            CURRENT =f;
 
            String s = fc.getTypeDescription(f);
            MainFrame.TITLE_VARIABLE = f.getAbsolutePath();
            System.out.println("getPath = " + f.getPath() );	// print file name and path
            System.out.println("getName = " + f.getName() );	
            //System.out.println("getNamecscssss" );
            javax.swing.filechooser.FileFilter ff = fc.getFileFilter();
            
            if (ff instanceof TMTFilter) open(f);
            else if (ff instanceof IMPFilter) openASCII(f);
            else if (ff instanceof XMLFilter) {
                if (!openXML(f)) return false;
            }
        }
        return (returnVal == JFileChooser.APPROVE_OPTION);
    }
    
   public static boolean open(JProgressBarDia jpbarDia) {
        File curDirectory = new File(getFolder());
        //System.out.println("Open dialog directory = "+curDirectory.getAbsolutePath());
    	final JFileChooser fc = new JFileChooser(curDirectory.getAbsolutePath());

        if (CURRENT != null) {
        	if (CURRENT.getName().endsWith(INTERNAL_FILE_SUFFIX)) {								
     			fc.addChoosableFileFilter(new IMPFilter());	
                fc.addChoosableFileFilter(new XMLFilter());    
                fc.addChoosableFileFilter(new TMTFilter()); // show .TMP first
            }
            else if (CURRENT.getName().endsWith(IMPORT_FILE_SUFFIX)) {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new XMLFilter());    
     			fc.addChoosableFileFilter(new IMPFilter());	// show .imp first
            }
            else {
                fc.addChoosableFileFilter(new TMTFilter()); 
                fc.addChoosableFileFilter(new IMPFilter());
                fc.addChoosableFileFilter(new XMLFilter()); // show .xml first    
            }

        	fc.setSelectedFile(CURRENT);        	
        } else {
        	fc.addChoosableFileFilter(new TMTFilter());
    		fc.addChoosableFileFilter(new IMPFilter());
            fc.addChoosableFileFilter(new XMLFilter());    
        }
        
        fc.setFileView(new TMTFileView());

        //allow to select a sub-directory and click 'Open' button 
        //to go into that sub-directory without closing the dialog window
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        
    	int returnVal;
    	do {
    		returnVal = fc.showOpenDialog(MainFrame.mainFrame);  //showOpenDialog(fc.getParent());
    		if (returnVal == JFileChooser.CANCEL_OPTION) break;

    		File tmpFile = fc.getSelectedFile();
   			if (tmpFile.isFile()) break;
   			
    		fc.setCurrentDirectory(tmpFile);
    	} while (true);
        
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File f = fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();
            CURRENT = f;
 
            String s = fc.getTypeDescription(f);
            MainFrame.TITLE_VARIABLE = f.getAbsolutePath();
            //System.out.println("getPath : " + f.getPath() );	// print file name and path
            try
            {
            	String sTemp = f.getCanonicalPath();
            	//System.out.println("getCanonicalPath : " + sTemp );
            }catch (IOException IOexcept){}
            	
            //System.out.println("getParent : " + f.getParent());
    
            //System.out.println("Opening file : "+f.getAbsolutePath() );	// print file name and path
            javax.swing.filechooser.FileFilter ff=fc.getFileFilter();
            
            String fileDescription = ff.getDescription();
            //System.out.println("File filter : "+fileDescription);
            
            if (fileDescription.equals("All Files (*.*)")) {
                String extension = FileTypes.getExtension(f);
                
                if (extension.equals(FileTypes.tmt)) {
                    open(f);
                }
                else if (extension.equals(FileTypes.imp)) {
                    openASCII(f,jpbarDia);
                }
                else if (extension.equals(FileTypes.xml)) {
                    if (!openXML(f,jpbarDia)) return false;
                }
            }
            else {
                if (ff instanceof TMTFilter) {
                    open(f);
                }
                else if (ff instanceof IMPFilter) {
                    openASCII(f,jpbarDia);
                }
                else if (ff instanceof XMLFilter) {
                    if (!openXML(f,jpbarDia)) return false;
                }
            }

        /*    if (s.equals("TAMOT2")) 
            	open(f);
            else if (s.equals("TAMOT2 ASCII")) {
            	openASCII( f, jpbarDia);
       	          
	    	  	OpenASCIFileThread pOpenFile =new OpenASCIFileThread(this);
	    	  	pOpenFile.start();
	    		
	    	}
        */    //MainFrame.mainFrame.setTitle(MainFrame.TITLE_FIXED + MainFrame.TITLE_VARIABLE);
        }
        return (returnVal==JFileChooser.APPROVE_OPTION);
    }
    
    private static File addExtensionIfNecessary(File f,String ext) {
        if (!f.isDirectory()) {
            String s = f.toString();
            //System.out.println("addExtensionIfNecessary : s = "+s);
            
            StringTokenizer st = new StringTokenizer(s,".");
            String temp = null;
            
            while (st.hasMoreTokens()) {
            	temp = st.nextToken();
                //System.out.println("addExtensionIfNecessary : temp = "+temp);
            }
            
            if (temp==null) return f;
            else {
            	if (temp.equals(ext)) return f;
                else return (new File(s+"."+ext));
            }
        }
        else return f;
    }
    
    //tape_recorder
    private static void writeXMLHeader(PrintStream out,File f) {
        out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        out.println();
        out.println("<!-- Task Model & Domain Model ("+f.getName()+") -->");
        out.println();
        out.println("<!-- Document type definition (external) -->");
        out.println();
        out.println("<!DOCTYPE Tamot SYSTEM \"tmDm.dtd\">");
        out.println();
        out.println("<Tamot Version=\""+XML_VERSION+"\">");
    }

    private static void writeXMLFooter(PrintStream out) {
        out.println("</Tamot>");
    }
    
    public static String getTABs(int numOfTABs) {
        StringBuffer result = new StringBuffer();
        
        for (int i=0; i<numOfTABs; i++) {
            result.append(TAB);
        }
        
        return result.toString();
    }
    
    private static void write_Task_Model_Components_InXML(PrintStream out) {
        int tabLevel = 1;
        
        out.println(getTABs(tabLevel)+"<Task_Model_Components>");

        Set compSet = new TreeSet();
        Set set = Manager.skeleton.nodeRegister.keySet();
        
        GenericComponent gc;
        String name;
        
        tabLevel++;
        
        for (Iterator i=set.iterator();i.hasNext();) {
            gc = Manager.skeleton.stringToFirstGenericComponent((String)i.next());
            name = gc.getName();
            
            if (!compSet.contains(name)) {
                compSet.add(name);
                
                //System.out.print("Writing "+name+" in XML ...");
                
                if (gc instanceof BooleanConnector) {
                    BooleanConnector bc = (BooleanConnector) gc;
                    bc.writeXML(out,tabLevel);
                }

                if (gc instanceof Link) {
                    Link link = (Link) gc;
                    link.writeXML(out,tabLevel);
                }

                if (gc instanceof Task) {
                    Task task = (Task) gc;
                    writeTaskXML(out,tabLevel,task);
                }
                
                //System.out.println("OK");
            }
        }
        
        tabLevel--;

        out.println(getTABs(tabLevel)+"</Task_Model_Components>");
    }
    
    public static void writeTaskXML(PrintStream out,int tabLevel,Task task) {
        out.println(getTABs(tabLevel)+"<Task>");
        
        writeTaskCoreXML(out,tabLevel+1,task);
        writeTaskContextXML(out,tabLevel+1,task.name);
        
        out.println(getTABs(tabLevel)+"</Task>");
    }

    public static void writeTaskContextXML(PrintStream out,int tabLevel,String name) {
        TreeMap parentTreeMap = (TreeMap)Manager.skeleton.nodeRegister.get(name);
        Set keys = parentTreeMap.keySet();

        for (Iterator it=keys.iterator();it.hasNext();) {
            String tmpParentName = (String)(it.next());
            Node tmpParentNode = (Node)parentTreeMap.get(tmpParentName);

            for (Iterator itID = tmpParentNode.getIDIterator(name);itID.hasNext();) {
                Integer currentID = (Integer)(itID.next());

                GenericComponent gc = tmpParentNode.getComponent(name,currentID);
                if (gc instanceof Task) {
                    Task task = (Task) gc;
                    writeTaskContextXML(out,tabLevel,task);
                }
            }
        }
    }

    public static void writeTaskContextXML(PrintStream out,int tabLevel,Task task) {
        out.print(getTABs(tabLevel)+"<Task_Context ");
        
        out.print("id=\"_"+task.ID+"\" ");

        String temp1 = (task.mandatory)?"Mandatory":"Optional";
        out.print("Mandatory=\""+temp1+"\" ");
        
        out.print("MinCardinal=\""+task.minCard+"\" ");
        out.print("MaxCardinal=\""+task.maxCard+"\" ");

        String temp2 = (task.terminal)?"Yes":"No";
        out.print("Terminal=\""+temp2+"\" ");
        
        temp2 = (task.dirty)?"Yes":"No";
        out.print("Dirty=\""+temp2+"\" ");
        
        //Shijian 2001-3-26
        out.print("PreconDM=\""+
        		XMLUtility.convertForEntities(task.getPreconDM())+"\" ");
        out.println("FeedbackDM=\""+
        		XMLUtility.convertForEntities(task.getFeedbackDM())+"\">");
       
        out.println(getTABs(tabLevel+1)+"<Precondition>"+
            XMLUtility.convertForEntities(task.precondition)+"</Precondition>");
        out.println(getTABs(tabLevel+1)+"<Feedback>"+
            XMLUtility.convertForEntities(task.feedback)+"</Feedback>");
        out.println(getTABs(tabLevel+1)+"<Postcondition>"+
            XMLUtility.convertForEntities(task.postcondition)+"</Postcondition>");
        
        // write context comment here
        
        out.println(getTABs(tabLevel)+"</Task_Context>");
    }
    
    public static void writeTaskCoreXML(PrintStream out,int tabLevel,Task task) {
        out.print(getTABs(tabLevel)+"<Task_Core ");
        
        out.print("Name=\""+XMLUtility.convertForEntities(task.name)+"\" ");
        out.print("Style=\""+task.style+"\" ");
        
        String temp = (task.composite)?"Composite":"Elementary";
        out.print("Composite=\""+temp+"\" ");
        
        //shijian 2001-3-22
        out.print("Warning=\""+XMLUtility.convertForEntities(task.getWarning())+"\" ");
        out.print("Actor=\""+XMLUtility.convertForEntities(task.getActor())+"\" ");
        out.println("Other=\""+XMLUtility.convertForEntities(task.getOther())+"\">");
       
        out.println(getTABs(tabLevel+1)+"<Semantics>"+
            XMLUtility.convertForEntities(task.semantics)+"</Semantics>");
        
        //writeTaskCommentXML(out,tabLevel+1,task.name);
        //shijian 26-9-2001
        Manager.RTFDBM.writeRTF_XML(task.name,out);
        Manager.RTFDBM.writeRTF_HTML(task.name,out);
            

        out.println(getTABs(tabLevel)+"</Task_Core>");
    }

    public static void writeTaskCommentXML(PrintStream out,int tabLevel,String name) {
        if (Manager.RTFDB.containsKey(name)) {
            DefaultStyledDocument doc = Manager.RTFDB.getDocument(name);
            
            if (doc.getLength() != 0) {
                // write comment in RTF
                out.print(getTABs(tabLevel)+"<Comment>");
                
                RTFEditorKit kit = (RTFEditorKit)Manager.editor.textPane.getEditorKit();
                
                try {
                    kit.write(out,doc,0,doc.getLength());
                }
                catch (Exception ex) {
                }
                
                out.println("</Comment>");
                
                // write comment in HTML
                out.println(getTABs(tabLevel)+"<Comment_HTML>");
                
                //System.out.println("writeTaskCommentXML for "+name);
                writeTaskCommentXML(out,tabLevel+1,doc);
                
                out.println(getTABs(tabLevel)+"</Comment_HTML>");
            }
        }
    }

    public static void writeTaskCommentXML(PrintStream out,int tabLevel,DefaultStyledDocument doc) {
        final String BEGIN_BODY = "<body>";
        final String END_BODY = "</body>";
        
        final int lbb = BEGIN_BODY.length();
        final int leb = END_BODY.length();
        try {
            CharArrayWriter tempOut;
            BufferedReader tempIn;
            
            MinimalHTMLWriter2 w;   // modify MinimalHTMLWriter in order to fix its bug

            tempOut = new CharArrayWriter();
            w = new MinimalHTMLWriter2(tempOut,doc,0,doc.getLength());
            w.write();

            tempOut.close();
            tempIn = new BufferedReader(new CharArrayReader(tempOut.toCharArray()));

            String s;
            boolean body = false;
            boolean stop = false;
            int l,index;
            LinkedList tags = new LinkedList();
            while ((s=tempIn.readLine())!=null) {
                //System.out.println("comment = "+s);
                
                l=s.length()-lbb;
                for (int j=0;j<=l;j++) {
                    if (s.substring(j,j+lbb).equals(BEGIN_BODY)) {
                        s=tempIn.readLine();
                        //System.out.println("comment = "+s);
                        body=true;
                        break;
                    }
                }
                l=s.length()-leb;
                for (int j=0;j<=l;j++) {
                    if (s.substring(j,j+leb).equals(END_BODY)) {
                        stop=true;
                        break;
                    }
                }
                if (stop) break;
                if (body) {
                    // replace <p class=default> with <p>
                    index = s.indexOf("<p class=default>");
                    if (index >= 0) {
                        s = s.substring(0,index)+"<p>";
                    }

                    // skip font tag due to its overlapping with <b>,<u>,<i> wrongly
                    s = skipFontTag(s);
                    s = skipSpanTag(s);
                    
                    // <b>, <u>, <i> overlap wrongly without this function
                    // this function will open & close overlapping <b>, <u>, <i> tags properly
                    s = correctOverlapping_bui_Tags(s,tags);
                    
                    out.println(getTABs(tabLevel)+s);
                }
            }
            tempIn.close();
        }
        catch (Exception e) {
            System.out.println("Error: "+(e.toString()));
        }
    }

    public static String correctOverlapping_bui_Tags(String ss,LinkedList tags) {
        StringBuffer sBuf = new StringBuffer();
        String ss1,ss2,ss3;
        
        for (int i=0; i<ss.length(); i++) {
            ss1 = ss.substring(i,i+1);
            
            if (ss1.equals("<")) {
                i++;
                ss2 = ss.substring(i,i+1);
                
                if (ss2.equals("/")) {
                    ss3 = ss.substring(i,i+3);
                    i += 3 - 1;    // -1 for increment later due to for loop
                    
                    if (ss3.equals("/b>")) sBuf.append(closeTag(tags,"b"));        // <b>
                    else if (ss3.equals("/u>")) sBuf.append(closeTag(tags,"u"));   // <u>
                    else if (ss3.equals("/i>")) sBuf.append(closeTag(tags,"i"));   // <i>
                    else
                        sBuf.append(ss1).append(ss3);
                }
                else {
                    ss3 = ss.substring(i,i+2);
                    i += 2 - 1;    // -1 for increment later due to for loop
                    
                    if (ss3.equals("b>")) tags.add("b");   // <b>
                    if (ss3.equals("u>")) tags.add("u");   // <u>
                    if (ss3.equals("i>")) tags.add("i");   // <i>
                    
                    sBuf.append(ss1).append(ss3);
                }
            }
            else
                sBuf.append(ss1);
        }
        
        return (sBuf.toString());
    }
    
    // e.g. tags = b u i, closingTag = b
    // then, the returned sBuf will be </i></u></b><u><i>
    private static String closeTag(LinkedList tags,String closingTag) {
        StringBuffer sBuf = new StringBuffer();

        String lastTag;
        LinkedList storedList = new LinkedList();
        
        while (tags.size() > 0)  {
            lastTag = (String)tags.removeLast();
            if (!lastTag.equals(closingTag)) {
                sBuf.append("</").append(lastTag).append(">");
                storedList.add(lastTag);
            }
            else {
                sBuf.append("</").append(closingTag).append(">");
                break;
            }
        }
        
        while (storedList.size() > 0)  {
            lastTag = (String)storedList.removeLast();
            sBuf.append("<").append(lastTag).append(">");
            tags.add(lastTag);
        }
        
        return (sBuf.toString());
    }
    
    public static String skipFontTag(String ss) {
        int index;
        
        String result = ss;
        
        index = ss.indexOf("<font");
        if (index >= 0) {
           result = ss.substring(0,index);
           
           index = ss.indexOf(">",index);
           if (index >= 0) result += ss.substring(index+1);
        }
        
        index = ss.indexOf("</font");
        if (index >= 0) {
           result = ss.substring(0,index);
           
           index = ss.indexOf(">",index);
           if (index >= 0) result += ss.substring(index+1);
        }
        
        return result;
    }
    
    public static String skipSpanTag(String ss) {
        int index;
        
        String result = ss;
        
        index = ss.indexOf("<span");
        if (index >= 0) {
            //TMUtility.display("skipSpanTag",ss);
            
            result = ss.substring(0,index);
           
            index = ss.indexOf(">",index);
            if (index >= 0) result += ss.substring(index+1);
        }
        
        
        index = ss.indexOf("</span");
        if (index >= 0) {
            result = ss.substring(0,index);
           
            index = ss.indexOf(">",index);
            if (index >= 0) result += ss.substring(index+1);
        }
        
        
        return result;
    }
    
    private static void writeComponents(PrintStream out) {
        Set compSet = new TreeSet();
    	Set set = Manager.skeleton.nodeRegister.keySet();
        
    	GenericComponent gc;
    	String name;
        
    	for (Iterator i=set.iterator();i.hasNext();) {
    	    gc = Manager.skeleton.stringToFirstGenericComponent((String)i.next());
    	    name = gc.getName();
            
    	    if (!compSet.contains(name)) {
    	    	compSet.add(name);
    	        //System.out.print("Writing "+name+" ...");
    	        gc.writeASCII(out);
    	        //System.out.println("OK");
    	        
    	      //shijian 26-9-2001
    	        Manager.RTFDBM.writeRTF(name,out);
    	        /*
    	        if (Manager.RTFDB.containsKey(name)) {
    	            DefaultStyledDocument doc = Manager.RTFDB.getDocument(name);
                    
    	            if (doc.getLength() != 0) {
    	                out.println(BEGIN_DESCRIPTION);
                        
    	                RTFEditorKit kit = (RTFEditorKit)Manager.editor.textPane.getEditorKit();
                        
    	                try {
    	                    kit.write(out,doc,0,doc.getLength());
    	                }
                        catch (Exception ex) {
                        }
                        
    	                out.println();	
    	                out.println(END_DESCRIPTION);	
    	                out.println();	
    	            }
    	        }
    	        
    	        */
    	    }
    	}
    }
    
    private static void write_Task_Model_Decomposition_InXML(PrintStream out) {
        int tabLevel = 1;
        
        out.println(getTABs(tabLevel)+"<Task_Model_Decomposition>");

        writeNodeXML(out,Manager.skeleton.root,ROOT,new TreeSet(),tabLevel+1);

        out.println(getTABs(tabLevel)+"</Task_Model_Decomposition>");
    }
    
    private static void writeNodeXML(PrintStream out,Node node,String name,Set expansionSet,int tabLevel) {
        //write the node
        out.print(getTABs(tabLevel)+"<Expansion ");
        out.println("Task_Name=\""+name+"\">");
        
        LinkedList list = writeComponentsXML(out,node,name,tabLevel+1);

        out.println(getTABs(tabLevel)+"</Expansion>");
        
        //write the branches of node
        Node childNode;
        String childName;
        int size = list.size() / 2;
        
        for (int i=0; i<size; i++) {
            childNode = (Node)list.removeFirst();
            childName = (String)list.removeFirst();
            
            if (!expansionSet.contains(childName)) {
                expansionSet.add(childName);
                writeNodeXML(out,childNode,childName,expansionSet,tabLevel);
            }
        }
    }

    private static LinkedList writeComponentsXML(PrintStream out,Node node,String name,int tabLevel) {
        Set keys = node.keySet();
        LinkedList list = new LinkedList();
        
        Couple couple;
        LinkableComponent lc;
        String childName;
        Integer childID;
       
        for (Iterator it=keys.iterator();it.hasNext();) {
            childName = (String)it.next();
            
            for (Iterator itID = node.getIDIterator(childName);itID.hasNext();) {
                childID = (Integer)(itID.next());
                couple = node.getCouple(childName,childID);
                
                if (couple.object instanceof LinkableComponent) {
                    lc = (LinkableComponent)couple.object;
    
                    out.print(getTABs(tabLevel)+"<Component ");

                    out.print("id=\"_"+lc.ID+"\" ");
                    
                    out.print("X=\""+lc.backupX+"\" ");
                    out.print("Y=\""+lc.backupY+"\" ");
                    
                    out.print("PNGx1=\""+lc.pngX1+"\" ");
                    out.print("PNGy1=\""+lc.pngY1+"\" ");
                    
                    out.print("PNGx2=\""+lc.pngX2+"\" ");
                    out.print("PNGy2=\""+lc.pngY2+"\">");

                    out.println("</Component>");
                    
                    if (!couple.node.isEmpty()) {
                        list.add(couple.node);
                        list.add(childName);
                    }
                }
            }
        }
        
        return list;
    }
    
    private static void writeExpansions(PrintStream out) {
        writeNode(out,Manager.skeleton.root,ROOT,new TreeSet());
    }

    private static void writeNode(PrintStream out,Node node,String name,Set expansionSet) {
    	//System.out.print("Writing expansion "+name+" ...");
        out.println("(Expansion)");
        out.println(name);
        
    	Set keys=node.keySet();
    	Couple c;
    	LinkableComponent lc;
    	String childName;
    	LinkedList list=new LinkedList();
    	int nb=0;
   	
   	    //1. print the node
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
    	    if (c.object instanceof LinkableComponent){
    	    	lc=(LinkableComponent)c.object;
    	    	out.println(childName);
    	    	out.println(lc.backupX);
    	    	out.println(lc.backupY);
                //only for a CompositeComponent
    	    	if (!c.node.isEmpty()){
    	    	    list.add(c.node);
    	    	    list.add(childName);
    	    	    nb++;
    	    	}
    	    }
    	}
    	out.println();
    	
    	//System.out.println("OK");

    	System.out.println(name+" contains "+nb+" branch(es)");
    	
    	//2. print the branches
    	Node n;
    	for (int i=0;i<nb;i++){
    	    n=(Node)list.removeFirst();
    	    childName=(String)list.removeFirst();
    	    if (!expansionSet.contains(childName)){
    	    	expansionSet.add(childName);
    	    	writeNode(out,n,childName,expansionSet);
    	    }
    	}
    	
    }

    public static final String DOCTYPE_XML = "<!DOCTYPE";
    
    public static final String TASK_XML = "<Task>";
    public static final String TASK_XML_END = "</Task>";

    public static final String TASK_CORE_XML = "<Task_Core";
    public static final String TASK_CORE_XML_END = "</Task_Core>";
    public static final String TASK_SEMANTICS_XML = "<Semantics>";
    public static final String TASK_SEMANTICS_XML_END = "</Semantics>";
    public static final String TASK_COMMENT_XML = "<Comment>";
    public static final String TASK_COMMENT_XML_END = "</Comment>";

    public static final String TASK_CONTEXT_XML = "<Task_Context";
    public static final String TASK_CONTEXT_XML_END = "</Task_Context>";
    public static final String PRECONDITION_XML = "<Precondition>";
    public static final String PRECONDITION_XML_END = "</Precondition>";
    public static final String TASK_FEEDBACK_XML = "<Feedback>";
    public static final String TASK_FEEDBACK_XML_END = "</Feedback>";
    public static final String TASK_POSTCONDITION_XML = "<Postcondition>";
    public static final String TASK_POSTCONDITION_XML_END = "</Postcondition>";
    
    public static final String BOOLEAN_CONNECTOR_XML = "<Boolean_Connector";
    public static final String BOOLEAN_CONNECTOR_XML_END = "</Boolean_Connector>";

    public static final String LINK_XML = "<Link";
    public static final String LINK_XML_END = "</Link>";

    public static final String EXPANSION_XML = "<Expansion";
    public static final String EXPANSION_XML_END = "</Expansion>";
    
    public static final String COMPONENT_XML = "<Component";
    public static final String COMPONENT_XML_END = "</Component>";

    private static void readExpansionXML(String ss,BufferedReader in,TreeMap expansions) {
        String ss1,ss2;
        int id;
        Integer ii;
        
        String name = getAttributeXML(ss,"Task_Name");

        LinkedList list = new LinkedList();
        
        try {
            while ((ss1 = in.readLine()) != null) {
                if (stringContains(ss1,COMPONENT_XML)) {
                    ss2 = getAttributeIDXML(ss1,"id");
                    id = stringToInt(ss2,"id of task ("+name+")");
                    ii = new Integer(id);
                    list.add(ii.toString());
                    
                    ss2 = getAttributeXML(ss1,"X");
                    list.add(ss2);
                    
                    ss2 = getAttributeXML(ss1,"Y");
                    list.add(ss2);
                }
                
                if (stringContains(ss1,EXPANSION_XML_END)) break;
            }
            
            if (ss1 == null) return;
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
            
        expansions.put(name,list);
        
        //System.out.println("Expansion '"+name+"' loaded");

        return;
    }
    
    private static void readLinkXML(int index,String ss,BufferedReader in,LinkedList links) {
        Link link = new Link(index);
        
        String ss1;
        
        ss1 = getAttributeIDXML(ss,"id");
        link.ID = stringToInt(ss1,"id of link ("+link.name+")");
        updateMaxUnusedID(link.ID);

        link.parentName = getAttributeXML(ss,"Parent_Task_Name");
        
        ss1 = getAttributeIDXML(ss,"id1");
        link.id1_XML = stringToInt(ss1,"id1 of link ("+link.name+")");
        
        ss1 = getAttributeIDXML(ss,"id2");
        link.id2_XML = stringToInt(ss1,"id2 of link ("+link.name+")");
        
        //shijian 2001-3-26
        if (getAttributeXML(ss,"PreconDM") != null)
        	link.setPreconDM(getAttributeXML(ss,"PreconDM"));

        try {
            while ((ss1 = in.readLine()) != null) {
                if (stringContains(ss1,PRECONDITION_XML,PRECONDITION_XML_END))
                    link.condition = getElementXML(ss1,PRECONDITION_XML,PRECONDITION_XML_END);

                if (stringContains(ss1,LINK_XML_END)) break;
            }
            
            if (ss1 == null) return;
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
        
        links.add(link);

        //System.out.println("Link : {"+link.name+"|"+link.ID+"|"+link.parentName+"|"+link.id1_XML+"|"+link.id2_XML+"}");
        
        return;
    }
    
    private static void readBooleanConnectorXML(String ss,TreeMap components) {
        BooleanConnector bc = new BooleanConnector();
        
        String ss1;
        
        bc.name = getAttributeXML(ss,"Name");
        
        ss1 = getAttributeIDXML(ss,"id");
        bc.ID = stringToInt(ss1,"id of boolean connector ("+bc.name+")");
        updateMaxUnusedID(bc.ID);

        bc.type = getAttributeXML(ss,"Type");

        bc.setSizeArea();

        components.put(new Integer(bc.ID),bc);

        //System.out.println("Boolean Connector : {"+bc.name+"|"+bc.ID+"|"+bc.type+"}");
        
        return;
    }

    private static void addCommentXML(String name,String ss,BufferedReader in) {
        if (name == null) return;
        
        String ss1;

        try {
            StringBuffer buf = new StringBuffer();
            DefaultStyledDocument doc = new DefaultStyledDocument();
            
            ss1 = getElementAfterStartTagXML(ss,TASK_COMMENT_XML);
            buf.append(ss1).append("\n");
            //System.out.println(ss1);
            
            while ((ss1 = in.readLine()) != null) {
                if (stringContains(ss1,TASK_COMMENT_XML_END)) break;
                
                buf.append(ss1).append("\n");
                //System.out.println(ss1);
            }

            ByteArrayInputStream b = new ByteArrayInputStream(buf.toString().getBytes());
            
            (new RTFEditorKit()).read(b,doc,0);
            
            Manager.RTFDB.add(name,doc);
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }
    
    private static void readTaskXML(BufferedReader in,TreeMap components) {
        String name = null;
        String style = null;
        String semantics = null;
        boolean composite = false;
        
        //shijian 2001-3-22
        String warning = null;
        String actor = null;
        String other = null;
       
        int id = 0;
        boolean mandatory = true;
        int minCard = 0;
        int maxCard = -1;
        boolean terminal = false;
        boolean dirty = true;
        String precondition = null;
        String feedback = null;
        String postcondition = null;
        String preconDM = null;
        String feedbackDM = null;

        String ss,ss1;
        Task task;
        
        try {
            // read task core fields
            while ((ss = in.readLine()) != null) {
                if (stringContains(ss,TASK_CORE_XML)) {
                    name = getAttributeXML(ss,"Name");
                    
                    ss1 = getAttributeXML(ss,"Style");
                    if (ss1.equals("Interactive")) style = Task.STYLE_VALUE[0];
                    else if (ss1.equals("Automatic")) style = Task.STYLE_VALUE[1];
                    else if (ss1.equals("Manual")) style = Task.STYLE_VALUE[2];
                    else style = Task.STYLE_VALUE[0];
                    
                    ss1 = getAttributeXML(ss,"Composite");
                    if (ss1.equals("Composite")) composite = true;
                    else composite = false;
                    
                    //shijian 2002-3-22
                    ss1 = getAttributeXML(ss,"Warning");
                    if (ss1 != null) warning = ss1;
                    ss1 = getAttributeXML(ss,"Actor");
                    if (ss1 != null) actor = ss1;
                    ss1 = getAttributeXML(ss,"Other");
                    if (ss1 != null) other = ss1;
               }
                
                if (stringContains(ss,TASK_SEMANTICS_XML,TASK_SEMANTICS_XML_END))
                    semantics = getElementXML(ss,TASK_SEMANTICS_XML,TASK_SEMANTICS_XML_END);
                //if (stringContains(ss,TASK_COMMENT_XML))
                 //   addCommentXML(name,ss,in);
                   //shijian 27-9-2001
                String startTag =getStartTag(ss) ;
                if (startTag != null){
                	//System.out.println("start tag = "+ startTag);
                	String cat = (String)Manager.RTFDBM._catTagBeginXML.get(startTag);
                	if (cat != null)
                		Manager.RTFDBM.readXML(name,ss,in, cat);
             	}
               
                if (stringContains(ss,TASK_CORE_XML_END)) break;
            }
            
            if (ss == null) return;
            
            //System.out.println("Task Core : {"+name+"|"+style+"|"+composite+"|"+semantics+"}");
            
            // read task context fields
            while ((ss = in.readLine()) != null) {
                if (stringContains(ss,TASK_CONTEXT_XML)) {
                    ss1 = getAttributeIDXML(ss,"id");
                    id = stringToInt(ss1,"id of task ("+name+")");
                    
                    ss1 = getAttributeXML(ss,"Mandatory");
                    if (ss1.equals("Mandatory")) mandatory = true;
                    else if (ss1.equals("Optional")) mandatory = false;
                    else mandatory = true;
                    
                    ss1 = getAttributeXML(ss,"MinCardinal");
                    minCard = (new Integer(ss1)).intValue();
                    
                    ss1 = getAttributeXML(ss,"MaxCardinal");
                    maxCard = (new Integer(ss1)).intValue();
                    
                    ss1 = getAttributeXML(ss,"Terminal");
                    if (ss1.equals("Yes")) terminal = true;
                    else terminal = false;
                    
                    ss1 = getAttributeXML(ss,"Dirty");
                    if (ss1 == null) dirty = true;
                    else {
                        if (ss1.equals("No")) dirty = false;
                        else dirty = true;
                    }
        
			        //shijian 2001-3-26
			        if (getAttributeXML(ss,"PreconDM") != null) 
			        	preconDM = getAttributeXML(ss,"PreconDM");
			        if (getAttributeXML(ss,"FeedbackDM") != null) 
				        feedbackDM = getAttributeXML(ss,"FeedbackDM");

                    
                }
                
                if (stringContains(ss,PRECONDITION_XML,PRECONDITION_XML_END))
                    precondition = getElementXML(ss,PRECONDITION_XML,PRECONDITION_XML_END);
                    
                if (stringContains(ss,TASK_FEEDBACK_XML,TASK_FEEDBACK_XML_END))
                    feedback = getElementXML(ss,TASK_FEEDBACK_XML,TASK_FEEDBACK_XML_END);
                    
                if (stringContains(ss,TASK_POSTCONDITION_XML,TASK_POSTCONDITION_XML_END))
                    postcondition = getElementXML(ss,TASK_POSTCONDITION_XML,TASK_POSTCONDITION_XML_END);
                    
                if (stringContains(ss,TASK_CONTEXT_XML_END)) {
                    //System.out.println("Task Context : {"+id+"|"+mandatory+"|"+minCard+"|"+maxCard+"|"+terminal+"}");
                    //System.out.println("               |"+precondition+"|");
                    //System.out.println("               |"+feedback+"|");
                    //System.out.println("               |"+postcondition+"|");
                    
                    task = new Task();
        
                    task.name = name;
                    task.style = style;
                    task.composite = composite;
 
                    //shijian 2001-3-22
                    if (warning != null)
       					task.setWarning(XMLUtility.
       						checkAndConvertForEntities(warning));
                    if (actor != null)
                  		task.setActor(XMLUtility.
                  			checkAndConvertForEntities(actor));
                    if (other != null)
                   		task.setOther(XMLUtility.
                   			checkAndConvertForEntities(other));
                 
                    task.ID = id;
                    updateMaxUnusedID(id);

                    task.mandatory = mandatory;
                    task.minCard = minCard;
                    task.maxCard = maxCard;
                    task.terminal = terminal;
                    task.dirty = dirty;
                    task.precondition = precondition;
                    task.feedback = feedback;
                    task.postcondition = postcondition;
                    
                     //shijian 2001-3-26
                    if (preconDM != null)
                    	task.setPreconDM(preconDM);
                    if (feedbackDM != null)
	                   	task.setFeedbackDM (feedbackDM);
                    task.semantics = semantics;
                    
        
                    task.setSizeArea();

                    components.put(new Integer(task.ID),task);
                    
                    // initialize variables again for next task
                    id = 0;
                    mandatory = true;
                    minCard = 0;
                    maxCard = -1;
                    terminal = false;
                    precondition = null;
                    feedback = null;
                    postcondition = null;
                    
                    warning = null;
                    actor = null;
                    other = null;
                  	preconDM = null;
                    feedbackDM = null;
               }

                if (stringContains(ss,TASK_XML_END)) break;
            }
        }
        catch (Exception ex) {
            System.out.println("error in read XML file!! "+ ex.toString());
        }

        return;
    }

    private static void updateMaxUnusedID(int id) {
        int tmpUnsedID = id+1;
        
        if (tmpUnsedID > Manager.currentUnusedID) {
            Manager.currentUnusedID = tmpUnsedID;
        }
    }

    private static int stringToInt(String ss,String message) {
        int result = 0;
        
        try {
            Integer ii = new Integer(ss);
            result = ii.intValue();
        }
        catch (Exception ex) {
            System.out.println(ex+" : Conversion error in "+message);
        }
        
        return result;
    }

    public static String getElementAfterStartTagXML(String ss,String startTag) {
        int j;
        
        j = ss.indexOf(startTag);
        if (j < 0) return null;
        
        j += startTag.length();    // skip startTag
        
        return (ss.substring(j));
    }
    
    private static String getElementXML(String ss,String startTag,String endTag) {
        int j,k;
        
        j = ss.indexOf(startTag);
        if (j < 0) return null;
        
        j += startTag.length();    // skip startTag
        
        k = ss.indexOf(endTag,j);  // find closing endTag
        if (k < 0) return null;
        
        //return (ss.substring(j,k));
        
        String result = ss.substring(j,k);
        result = XMLUtility.checkAndConvertForEntities(result);
        
        return result;
    }

    private static String getAttributeIDXML(String ss,String attribute) {
        String ss1 = getAttributeXML(ss,attribute);
        
        if (ss1 == null) return null;
        
        if (ss1.length() > 1)
            return (ss1.substring(1));    // skip _
        else
            return null;
    }
    
    private static String getAttributeXML(String ss,String attribute) {
        int j,k;
        
        j = ss.indexOf(attribute);
        if (j < 0) return null;
        
        j += attribute.length();   // skip attribute
        
        j = ss.indexOf("=",j);
        if (j < 0) return null;
        
        j += 1;                    // skip =
        
        j = ss.indexOf("\"",j);
        if (j < 0) return null;
        
        j += 1;                    // skip "

        k = ss.indexOf("\"",j);    // find closing "
        if (k < 0) return null;
        
        //return (ss.substring(j,k));
        
        String result = ss.substring(j,k);
        result = XMLUtility.checkAndConvertForEntities(result);
        
        return result;
    }

    private static String getAttributeXML2(String ss,String attribute) {
        int j,k;
        
        j = ss.indexOf(attribute);
        if (j < 0) return null;
        
        j += attribute.length();   // skip attribute
        
        j = ss.indexOf(" ",j);
        if (j < 0) return null;
        
        j += 1;                    // skip ' '
        
        j = ss.indexOf("\"",j);
        if (j < 0) return null;
        
        j += 1;                    // skip "

        k = ss.indexOf("\"",j);    // find closing "
        if (k < 0) return null;
        
        return (ss.substring(j,k));
    }

    private static boolean stringContains(String ss,String startTag,String endTag) {
        boolean result = false;
        
        if (stringContains(ss,startTag)) {
            if (stringContains(ss,endTag)) result = true;
        }
        
        return result;
    }
    
    public static boolean stringContains(String ss,String tag) {
        int i = ss.indexOf(tag);
        
        if (i < 0) return false;
        else return true;
    }
    
    private static boolean setSkeletonFromXML(BufferedReader in) {
        //Intermediate structures
        TreeMap components = new TreeMap();
        TreeMap expansions = new TreeMap();
        LinkedList links = new LinkedList();        
        String s;
        
        int index = -1;
        
        //1. read the stream
        try {
            //int iLineNum = 0;
            while ((s = in.readLine()) != null) {
                //System.out.println("iLineNum = "+iLineNum);
                //iLineNum++;
                if (stringContains(s,TASK_XML)) {
                    readTaskXML(in,components);
                }
                else if (stringContains(s,BOOLEAN_CONNECTOR_XML)) {
                    readBooleanConnectorXML(s,components);
                }
                else if (stringContains(s,LINK_XML)) {
                    readLinkXML(index,s,in,links);
                    index++;
                }
                else if (stringContains(s,EXPANSION_XML)) {
                    readExpansionXML(s,in,expansions);
                }
            }
        }
        catch (Exception ex) {
            System.out.println(ex.toString());
        }
        
        //2. create the tree
        if (!createNodeXML(ROOT,Manager.skeleton.root,components,expansions)) return false;
        
        //3. add the links
        int nb = links.size();
        Link l;
        //System.out.println(nb+" links to add");
        
        for (int i=0;i<nb;i++) {
            l = (Link)links.removeFirst();
            
            fillNamesInLink(l,components);  // fill name1 & name2 of link l from components

            // get lc1 & lc2 from id1_XML & id2_XML
            // add link l in lc1 & lc2 respectively
            l.updateLink();
            
            //TMUtility.displayLink("setSkeletonFromXML",l);
            
            //System.out.print("Adding '"+l.name+"' in '"+l.parentName+"'"+" ID = "+l.ID);
            
            Node parentNode = Manager.skeleton.toParentNode(l.name1,l.parentName);
            parentNode.add(l);
            
            // add link in nodes of other duplicated tasks in the same parent window
            addLinkInOtherDuplicatedTasks(l,parentNode);
            
            Manager.skeleton.addInRegister(l.name,new Integer(l.ID),l.parentName,parentNode);
            //shijian 2001-10-2
            Manager.RTFDB.add(l.name);
            Manager.RTFDBM.add(l.name);
            //info(" ok");
        }

        return true;
    }
    
    private static void addLinkInOtherDuplicatedTasks(Link link,Node parentNode) {
        Integer parentID2;
        Couple tmpParentCouple;
        Node grandParentNode,tmpParentNode;
        
        String parentName = link.parentName;

        if (Manager.skeleton.nodeRegister.containsKey(parentName)) {
            TreeMap tmGrandParent = (TreeMap)Manager.skeleton.nodeRegister.get(parentName);

            for (Iterator i = (tmGrandParent.keySet()).iterator();i.hasNext();) {
                grandParentNode = (Node)(tmGrandParent.get(i.next()));
                
                if (grandParentNode.containsKey(parentName)) {
                    TreeMap tmpParent = (TreeMap)grandParentNode.get(parentName);

                    for (Iterator it = (tmpParent.keySet()).iterator();it.hasNext();) {
                        parentID2 = (Integer)it.next();
                        tmpParentCouple = (Couple) tmpParent.get(parentID2);
                        tmpParentNode = tmpParentCouple.node;
                        
                        if (!tmpParentNode.equals(parentNode)) {
                            tmpParentNode.add(link);
                        }
                    }
                }
            }
        }
    }

    private static void fillNamesInLink(Link link,TreeMap components) {
        Integer id2;
        LinkableComponent lc;
        
        // find name1
        id2 = new Integer(link.id1_XML);

        if (!components.containsKey(id2)) {
            JOptionPane.showMessageDialog(MainFrame.mainFrame,"The component '"+id2+
                "' defined in the link with ID = '"+link.ID+"' has no specification.","Error",
                JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        lc = (LinkableComponent)components.get(id2);

        link.name1 = lc.name;

        // find name2
        id2 = new Integer(link.id2_XML);

        if (!components.containsKey(id2)) {
            JOptionPane.showMessageDialog(MainFrame.mainFrame,"The component '"+id2+
                "' defined in the link with ID = '"+link.ID+"' has no specification.","Error",
                JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        lc = (LinkableComponent)components.get(id2);

        link.name2 = lc.name;
    }
    
    private static void setSkeleton(BufferedReader in) {
    	//Intermediate structures
    	TreeMap components=new TreeMap();
    	TreeMap expansions=new TreeMap();
    	LinkedList links=new LinkedList();    	
    	String s;
        GenericComponent gc=null;
        String last=null;
        StringBuffer buf;
        DefaultStyledDocument doc;
        
        int index=-1;
        
        //1. read the stream
    	try {
    	    while ((s=in.readLine())!=null){
    	    	//System.out.println(" readin : "+s);

    	        if (s.equals(TASK)){
    	            gc=new Task();
    	            gc.readASCII(in);
    	            //gc.setID();                    //Thomas ?V5
    	            components.put(gc.getName(),gc);
    	            last=gc.getName();
    	            //info("Task '"+last+"' loaded");
    	        }
    	        else if (s.equals(BOOLEAN_CONNECTOR)){
    	            gc=new BooleanConnector();
    	            gc.readASCII(in);
    	            gc.setID();                    //Thomas ?V5
    	            components.put(gc.getName(),gc);
    	            last=gc.getName();
    	            //info("BooleanConnector '"+last+"' loaded");
    	        }
    	        else if (s.equals(LINK)){
    	            gc=new Link(index);
    	            index++;
    	            gc.readASCII(in);
    	            gc.setID();
    	            links.add(gc);
    	            last=gc.getName();
    	            //info("Link '"+last+"' loaded");
    	        }
    	        else if (s.equals(EXPANSION)){    	            
    	            String name=in.readLine();
    	            LinkedList list=new LinkedList();
    	            int count=0;
    	            while (!((isExpansionKey(s=in.readLine()))&&(count%3==0))){
    	            	//boolean ookk1 = isExpansionKey(s);
    	            	//int int2 = count%3;
    	            	//System.out.println("exp : "+s+" ookk1 : "+ookk1+"; int2 : "+int2);
    	            	list.add(s);
    	            	count++;
    	            }
    	            if ((list.size()%3)==0) {
    	            	//System.out.println("  %3 : "+s);
    	            	expansions.put(name,list);
    	            }
    	            last=null;
    	            //info("Expansion '"+name+"' detected");
    	        }
    	        
    	        //shijian 2001-3-22
     	        else if (s.equals(BEGIN_PRECONDM)){ 
    	            if (gc==null || !(gc instanceof Task)) {
    	            	// System.out.println(" task is null");
    	            	while (!(s=in.readLine()).equals(END_PRECONDM));
    	            }
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_PRECONDM)){
    	                    buf.append(s).append("\n");
    	                    //System.out.println(" warning : "+buf.toString());

    	                }
    	            	//System.out.println(" warning : "+buf.toString());
    	                ((Task)gc).setPreconDM(buf.toString());
    	            }
    	        }
     	        else if (s.equals(BEGIN_FEEDBACKDM)){ 
    	            if (gc==null || !(gc instanceof Task)) {
    	            	// System.out.println(" task is null");
    	            	while (!(s=in.readLine()).equals(END_FEEDBACKDM));
    	            }
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_FEEDBACKDM)){
    	                    buf.append(s).append("\n");
    	                    //System.out.println(" warning : "+buf.toString());

    	                }
    	            	//System.out.println(" warning : "+buf.toString());
    	                ((Task)gc).setFeedbackDM(buf.toString());
    	            }
    	        }
    	        //shijian 26-9-2001
   	        /*	else if (s.equals(BEGIN_WARNING)){ 
    	            if (gc==null || !(gc instanceof Task)) {
    	            	// System.out.println(" task is null");
    	            	while (!(s=in.readLine()).equals(END_WARNING));
    	            }
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_WARNING)){
    	                    buf.append(s).append("\n");
    	                    //System.out.println(" warning : "+buf.toString());

    	                }
    	            	//System.out.println(" warning : "+buf.toString());
    	                ((Task)gc).setWarning(buf.toString());
    	            }
    	        }	*/
    	        else if (s.equals(BEGIN_ACTOR)){ 
    	            if (gc==null || !(gc instanceof Task)) 
    	            	while (!(s=in.readLine()).equals(END_ACTOR));
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_ACTOR)){
    	                    buf.append(s).append("\n");
    	                }
        	            System.out.println(" actor : "+buf.toString());
	                	((Task)gc).setActor(buf.toString());
    	            }
    	        }
    	        else if (s.equals(BEGIN_OTHER)){ 
    	            if (gc==null || !(gc instanceof Task)) 
    	            	while (!(s=in.readLine()).equals(END_OTHER));
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_OTHER)){
    	                    buf.append(s).append("\n");
	                	}
         	            System.out.println(" other : "+buf.toString());
   	                	((Task)gc).setOther(buf.toString());
    	            }
    	        }
    	        else if (s.equals(BEGIN_LINKCONDM)){ 
    	            if (gc==null || !(gc instanceof Link)) 
    	            	while (!(s=in.readLine()).equals(END_LINKCONDM));
    	            else {
    	            	buf=new StringBuffer();
    	                while (!(s=in.readLine()).equals(END_LINKCONDM)){
    	                    buf.append(s).append("\n");
	                	}
         	            System.out.println(" other : "+buf.toString());
   	                	((Link)gc).setPreconDM(buf.toString());
    	            }
    	        }
    	        
					//shijian 26-9-2001
    	        else if (Manager.RTFDBM._catTagBegin.get(s) != null)
  		  	        	Manager.RTFDBM.readRTF(last, in,
  		  	        		(String)Manager.RTFDBM._catTagBegin.get(s)); 
    	      		/*  (s.equals(BEGIN_DESCRIPTION)){ 
    	            if (last==null) while (!(s=in.readLine()).equals(END_DESCRIPTION));
    	            else {
    	            	buf=new StringBuffer();
    	            	doc=new DefaultStyledDocument();
    	                //System.out.println("################## RTF ###############");
    	                while (!(s=in.readLine()).equals(END_DESCRIPTION)){
    	                    buf.append(s).append("\n");
    	                    //System.out.println(s);
    	                }
    	                //System.out.println("################## RTF ###############");
    	                ByteArrayInputStream b=new ByteArrayInputStream(buf.toString().getBytes());
    	                (new RTFEditorKit()).read(b,doc,0);
    	                Manager.RTFDB.add(last,doc);
    	                //System.out.println(Manager.RTFDB.getDocument(last));
    	                last=null;
    	            }
    	            
    	        }*/
    	        //last=null;

    	    }
        } catch (Exception excep){}
        
        //2. create the tree
        createNode(ROOT,Manager.skeleton.root,components,expansions);
        
        //3. check for auto-placement
        //addCoordinates(Manager.skeleton.root);
        
        
        //4. add the links
        int nb=links.size();
        Link l;
        //System.out.println(nb+" links to add");
        for (int i=0;i<nb;i++){
            
            l=(Link)links.removeFirst();
            l.updateLink();
            //System.out.print("Adding '"+l.name+"' in '"+l.parentName+"'"+" ID = "+l.ID);
            Node parentNode=Manager.skeleton.toParentNode(l.name1,l.parentName);
            parentNode.add(l);
            Manager.skeleton.addInRegister(l.name,new Integer(l.ID),l.parentName,parentNode);
            Manager.RTFDB.add(l.name);
            //shijian 25-9-2001
            Manager.RTFDBM.add(l.name);
        }
    }

    
    /*private void setRTF(BufferedInputStream in){
    	int nb=RTFList.size();
    	if ((nb%3)==0){
    	    int nb/=3;
    	    int line=0;
    	    final int newLine=Character.getNumericValue('\n');
    	    int c;
    	    LinkedList list=new LinkedList();
    	    String name;
    	    String begin;
    	    String nbLines;
    	    for (int i=0;i<nb;i++){
    	    	name=(String)list.removeFirst();
    	    	begin=((Integer)list.removeFirst()).intValue();
    	    	nbLines=((Integer)list.removeFirst()).intValue();
    	    	while ((c=in.read())!=-1){
    	    	    if 
    	    	    if (c==newLine) nbLine++;
    	    	}
    	    }
    }*/

    
    private static boolean createNodeXML(String parentName,Node parentNode,TreeMap components,TreeMap expansions) {
    	Object obj = expansions.get(parentName);
        if (obj == null) return true;
        
        //LinkedList list = (LinkedList)obj; 
        LinkedList list1 = (LinkedList)obj; 
        LinkedList list = (LinkedList) list1.clone();  // so that data is not lost for other duplicated tasks
        
        int nb = list.size()/3;
        LinkableComponent lc;
        Task task;
        String ss,name,sx,sy;
        Integer id3;
        
        for (int i=0;i<nb;i++) {
            ss = (String)list.removeFirst();
            id3 = new Integer(ss);
            
            if (!components.containsKey(id3)) {
                JOptionPane.showMessageDialog(MainFrame.mainFrame,"The component '"+id3+
                    "' defined in the expansion '"+parentName+"' has no specification.",
                    "Error in createNodeXML",
                    JOptionPane.ERROR_MESSAGE);

                return false;
            }
            
            lc = (LinkableComponent)components.get(id3);

            name = lc.name;
            
            //System.out.print("Adding '"+name+"' in '"+parentName+"'");
            
            // clone if it is Task
            if (lc instanceof Task) {
                task = new Task((Task)lc);

                if (task.ID == task.undefined) task.setID();

                if (expansions.containsKey(name)) task.composite = true;
                lc = task;                    
            }
        
            //add the coordinates
            try {
                sx = (String)list.removeFirst();
                sy = (String)list.removeFirst();
                
                if (sx.equals("")||sy.equals("")) {
                    //Manager.autoPlace(lc,parentNode);
                    lc.backupX = 0;//lc.FIRST_LOCATION_X;
                    lc.backupY = 0;//lc.FIRST_LOCATION_Y;
                    lc.floating = true;
                } else {
                    lc.backupX = Double.parseDouble(sx);
                    lc.backupY = Double.parseDouble(sy);
                }
                
                lc.setLocation(r(lc.backupX),r(lc.backupY));
            }
            catch (NumberFormatException excep) {
            }

            Integer id2 = new Integer(lc.ID);
            
            //update the tree
            parentNode.add(lc);

            if (!Manager.skeleton.isInRegister(name,parentName)) {
                //update the register
                if (parentName == ROOT) 
                    Manager.skeleton.addInRegister(name,id2,Manager.skeleton.ROOT_STRING,parentNode);
                else
                    Manager.skeleton.addInRegister(name,id2,parentName,parentNode);
    
                Manager.RTFDB.add(name);
                //shijian 25-9-2001
                Manager.RTFDBM.add(name);
                
                if (lc.floating) {
                    Manager.autoPlace(lc,parentNode);
                    lc.floating = false;
                }
            }
        }
    
        // create the branches
        Set keys = parentNode.keySet();
        Node currentNode;
        Integer id2;
        for (Iterator i = keys.iterator();i.hasNext();) {
            name = (String)i.next();
            
            for (Iterator itID = parentNode.getIDIterator(name);itID.hasNext();) {
                id2 = (Integer)(itID.next());
                
                currentNode = parentNode.getChild(name,id2);

                //System.out.println("id2 = "+id2);
                
                if (!createNodeXML(name,currentNode,components,expansions)) return false;
                
                //Manager.skeleton.printNode(currentNode,name);
            }
        }

        return true;
    }
    
    private static void createNode(String parentName,Node parentNode,TreeMap components,TreeMap expansions) {
        Object obj=expansions.get(parentName);
        if (obj!=null) {
            LinkedList list=(LinkedList)obj; 
            int nb=list.size()/3;
            LinkableComponent lc;
            Task t;
            String name,sx,sy;
            for (int i=0;i<nb;i++) {
                name=(String)list.removeFirst();
                if (!components.containsKey(name)) {
                    JOptionPane.showMessageDialog(MainFrame.mainFrame,"The component '"+name+
                        "' defined in the expansion '"+parentName+"' has no specification.","Error",
                        JOptionPane.ERROR_MESSAGE);
                }
                //System.out.print("Adding '"+name+"' in '"+parentName+"'");
                lc=(LinkableComponent)components.get(name);
                // clone if it is Task
                if (lc instanceof Task) {
                    t=new Task((Task)lc);

                    if (t.ID == t.undefined) t.setID();

                    if (expansions.containsKey(name)) t.composite=true;
                    lc=t;                    
                }
            
                //add the coordinates
                try {
                    sx=(String)list.removeFirst();
                    sy=(String)list.removeFirst();
                    if (sx.equals("")||sy.equals("")) {
                        //Manager.autoPlace(lc,parentNode);
                        lc.backupX=0;//lc.FIRST_LOCATION_X;
                        lc.backupY=0;//lc.FIRST_LOCATION_Y;
                        lc.floating=true;
                    } else {
                        lc.backupX=Double.parseDouble(sx);
                        lc.backupY=Double.parseDouble(sy);
                    }
                    lc.setLocation(r(lc.backupX),r(lc.backupY));
                } catch (NumberFormatException excep){}

                Integer id2 = new Integer(lc.ID);
                
                //update the register
                if (parentName==ROOT) 
                    Manager.skeleton.addInRegister(name,id2,Manager.skeleton.ROOT_STRING,parentNode);
                else
                    Manager.skeleton.addInRegister(name,id2,parentName,parentNode);
                Manager.RTFDB.add(name);
                //shijian 25-9-2001
                Manager.RTFDBM.add(name);

                //update the tree
                parentNode.add(lc);
                
                if (lc.floating) {
                    Manager.autoPlace(lc,parentNode);
                    lc.floating=false;
                }
                
                //info("ok");
            }
        
            // create the branches
            Set keys=parentNode.keySet();
            Node child;
            for(Iterator i=keys.iterator();i.hasNext();){
                name=(String)i.next();
                createNode(name,parentNode.getChild(name),components,expansions);
            }
        }
    }
    
    private static void addCoordinates(Node node){
    	Set set=node.keySet();
    	GenericComponent gc;
    	String name;
    	Node n;
    	LinkedList nodes=new LinkedList();
    	for (Iterator i=set.iterator();i.hasNext();){
    	    name=(String)i.next();
    	    gc=node.getComponent(name);
    	    if (gc instanceof LinkableComponent){
    	    	Manager.autoPlace(gc,node);
    	        if (node.hasBranch(name)) nodes.add(node.getChild(name));
    	    }
    	}
    	int nb=nodes.size();
    	for (int i=0;i<nb;i++){
    	   n=(Node)nodes.getFirst();
    	   addCoordinates(n);
    	}
    }
    
    /*private boolean isKey(String s){
    	if (s==null) return true;
    	else return ((s.equals(TASK))||(s.equals(BOOLEAN_CONNECTOR))||(s.equals(LINK))||(s.equals(EXPANSION))||(s.equals("")));
    }*/

    private static boolean isExpansionKey(String s){
    	if (s==null) return true;
    	else return (s.equals(""));
    }

    private static int r(double d){
    	return (int)Math.round(d);
    }

    private static void info(String s) {
    	System.out.println(s);
    }
    
    public static String getFolder()
    {
    	if (FOLDER == null) FOLDER=DEFAULT_FOLDER;
    	return FOLDER;
    	
    }
        public static String getFileName()
    {
    	if (FILE_NAME == null) FILE_NAME=DEFAULT_FILE_NAME;
    	return FILE_NAME;
    	
    }
    
    
    public static boolean fileOverWrite(File f) {
        if (f.isFile()) {
            //String name=(String)alist.getSelectedValue();            	
            String [] options={"Yes","No"};
            int choice=JOptionPane.showOptionDialog(MainFrame.mainFrame,
            					"Over write "+f.getName()+"' ?",
            					"Warning",JOptionPane.YES_NO_OPTION,
            					JOptionPane.WARNING_MESSAGE,null,options,options[1]);
            if (choice==0) return true;
            else return false;
         }
         else return true;
    }

    public static void selectTaskAttributes(Task t, PrintWriter out) {
        int counter, valueI; 
        String key, valueS;
        boolean valueB;
        Field[] fields = t.getClass().getFields();
        
        for (Iterator i=Manager.filedsKeyForHTML.keySet().iterator();i.hasNext();) {
            key = (String)i.next();

            if (key.equals("comment")) continue;
            
            counter =  ((Integer)Manager.filedsKeyForHTML.get(key)).intValue();
            
            String type=fields[counter].getType().getName();
            
           
            String s = "    <FONT SIZE=\"-1\"><I><B>"+key +"</B></I></FONT>";
            out.print(s);

            if (type.equals("java.lang.String"))
            {
                try{
                    valueS= (String)fields[counter].get(t);
                    out.println(":    "+valueS + "<BR>");
                } catch (Exception except){}
                
            }
            else if (type.equals("int"))
            {
                 try{
                     valueI= fields[counter].getInt(t);
                     out.println(":    "+valueI+ "<BR>");
                } catch (Exception except){}
                
            }
            else if (type.equals("boolean")) {
                try{
                    valueB= fields[counter].getBoolean(t);
                    out.println(":    "+valueB+ "<BR>");
                } catch (Exception except){}
                
              
            }
           

        }

       //  out.print("</P>");

    }

   // ------------------------------------------------------------------------------------------
   //added on 00-1-27 
   // to update link after opening a tmt file
    public static void linkValidate() {
        Set compSet=new TreeSet();
      	Set set=Manager.skeleton.nodeRegister.keySet();
      	GenericComponent gc;
        Link li;
      	String name;
      	for (Iterator i=set.iterator();i.hasNext();) {
            String pName= (String) i.next();
      	    gc=Manager.skeleton.stringToFirstGenericComponent(pName);   
      	    name=gc.getName();
              
       	    if (!compSet.contains(name)) {
      	    	compSet.add(name);
                
                if (gc instanceof Link) {
                   li = (Link)gc;
                   li.updateLink();
                }
      	    }
      	}       	
    }

    // Contents : view in big-window, allow http
    public static void openHelpContents() {
        File helpDirectory = new File("help");
        //System.out.println("Help directory = "+helpDirectory);

        File helpFile = new File(helpDirectory.getAbsolutePath()+File.separator+"index.htm");
        //System.out.println("Help file = "+helpFile);
        
        String fileroot = helpFile.getAbsolutePath();
        //Manager.desktop.openTVFrame("TV", 
        //   fileroot.substring(0, fileroot.lastIndexOf('.')) + ".htm");
        Manager.openTVFrame("TV", 
           fileroot.substring(0, fileroot.lastIndexOf('.')) + ".htm");

        /*
        // maximize help window
        JInternalFrame helpFrame = Manager.desktop.fetchFrame("TV");
        try {
            helpFrame.setMaximum(true);
        }
        catch (java.beans.PropertyVetoException ex) {
            System.out.println("openHelpContents : [ "+ex.getMessage()+" ]");
        }*/
    }
    
    // Open on-line help : view in small-window, not allow http
	public static void openHTMLView(){
    	final JFileChooser fc=new JFileChooser(getFolder());
    	fc.addChoosableFileFilter(new HTMLFilter());
        fc.setFileView(new HTMLFileView());
        
        if (CURRENT_HTML != null) fc.setSelectedFile(CURRENT_HTML);
        
        String approveButtonText="Open HTML";
        int returnVal=fc.showDialog(MainFrame.mainFrame,approveButtonText);
									   //showSaveDialog(MainFrame.mainFrame);
        
        //fc.setApproveButtonText(approveButtonText);

        if (returnVal==JFileChooser.APPROVE_OPTION) {
            File f=fc.getSelectedFile();
            
            FOLDER = f.getParent();
            FILE_NAME = f.getName();
            CURRENT_HTML =f;
            
            javax.swing.filechooser.FileFilter ff=fc.getFileFilter();
            if (ff instanceof HTMLFilter) {
            	// code to add for text view - kvlinden, 22feb00 
       			//     probably should check the feedback from generateOLP() before doing this...
       			String fileroot = CURRENT_HTML.getAbsolutePath();
                
       			Manager.desktop.openTVFrame("TV", 
			   	    fileroot.substring(0, fileroot.lastIndexOf('.')) + ".html");
                //Manager.openTVFrame("TV", 
                //    fileroot.substring(0, fileroot.lastIndexOf('.')) + ".html");
            }
        }
	
	}
	
public static void listenHelp(){

}
	
	/**
	* return a reference of the XMamager xDm (domain model Xmanager)
	*/
	public static XManager getXDM(){
		return Manager.getXDM();
	}//getXDM()
	
	/**
	* set the XMamager xDm (domain model Xmanager) to aX
	*/
	public static void setXDM(XManager aX){
		Manager.setXDM(aX);
	}//setXDM()

	//brasser 2001-6-21
	//opens a text file and extracts tasks from it
	//we may eventually move part of this functionality elsewhere
	/*
	public static void extractText(File f) {
	 	try {
	 		BufferedReader in = new BufferedReader(new FileReader(f));
			String sentence;
			String prevSentence = null;
			GenericComponent _gc = null;
			String taskStyle = Task.STYLE_VALUE[0];
			//shijian	2001-8-20
			//stop parsing
			//parser.FSParser.Parser parser = new parser.FSParser.Parser(Manager.getXDM().getDmManager(),"action.grammar");
	 		
			
			while ((sentence = in.readLine()) != null) {
				//parser.parse(sentence);
				//parser.createDM(_gc);
				
				//shijian
				//2001-8-23
				//create automatic task if the sentence has prefix "-" 
				sentence=sentence.trim();
				if (sentence.startsWith("-")){
					sentence= sentence.substring(1);
					taskStyle = Task.STYLE_VALUE[1];
				}else {
					if (sentence.startsWith("+"))
						sentence= sentence.substring(1);
					taskStyle = Task.STYLE_VALUE[0];
				}
				//create a task
				Task t = NewManager.newTask(-1,-1, sentence.trim());
				t.setStyle(taskStyle);
	
				//this assures that the name will be correct for linking purposes
				sentence = t.getName();
		
				//link the tasks
				if (prevSentence != null)	
					NewManager.newLink(prevSentence, sentence);
				
				prevSentence = sentence;	
			}
			

	 	}
		catch (java.io.FileNotFoundException e) { }
		catch (java.io.IOException e) {};
		
	}
*/

	//brasser 2001-6-21
	//update 2001-7-23
	//opens a text file and extracts tasks from it
	//we may eventually move part of this functionality elsewhere
  public static void extractText(File f) {
    try {
      BufferedReader in = new BufferedReader(new FileReader(f));
      String sentence;
      String fullSentence;
      String prevSentence = null;
      GenericComponent _gc = null;
      parser.FSParser.Parser parser = new parser.FSParser.Parser(Manager.getXDM().getDmManager(),"action.grammar");
	 		
			
      while ((sentence = in.readLine()) != null) {
	fullSentence = "";
	while (!sentence.equals(""))
	  {
	    fullSentence += (sentence + " ");
					
	    sentence = in.readLine();
	    if (sentence == null)
	      break;
	  } 
					
	//System.out.println(fullSentence); 
	parser.parse(fullSentence);
	parser.createTM(_gc);
				
      } 

			

    }
    catch (java.io.FileNotFoundException e) { }
    catch (java.io.IOException e) {};
  }

	//shijian 27-9-2001
	public static String getStartTag(String s){
		s = s.trim();
		//System.out.println("beginning ="+s);
		String tagStart = "<";
		String tagEnd = ">";
		String tagCloseStart= "</";
		
		if (!(s.startsWith(tagStart)) || 
				s.startsWith(tagCloseStart) ||
					s.indexOf(tagEnd) < 0)
			return null;
			
		int last = 	s.indexOf(tagEnd);
		//System.out.println("endTag Index ="+last);

		return s.substring(0,last+1);
	}
////3-10-2001 
    public static void saveHTML(File f) {
    	final String BEGIN_BODY="<body>";
    	final String END_BODY="</body>";
    	
    	final String BEGIN_COMPONENT=" <HR size=\"1\">    <TABLE BORDER=\"0.5\" CELLPADDING=\"3\" CELLSPACING=\"0\" WIDTH=\"100%\"><TR BGCOLOR=\"#F2E8D3\" ID=\"TableHeadingColor\"><TD COLSPAN=2><FONT SIZE=\"+1\"><CENTER><B>";
    	final String END_COMPONENT="    </B></CENTER></FONT></TD></TR></TABLE>";
    	
    	final int lbb=BEGIN_BODY.length();
    	final int leb=END_BODY.length();
    	try {
    		PrintWriter out=new PrintWriter(new FileWriter(f));
    		CharArrayWriter tempOut;
    		BufferedReader tempIn;
    		
    		//Thomas
    		//HTMLEditorKit kit;
			MinimalHTMLWriter2 w;   // modify MinimalHTMLWriter in order to fix its bug

    		String name;
    		String s;
    		boolean body;
    		DefaultStyledDocument doc;
    		//shijian 2001-10-2
    		//Set keys = Manager.RTFDB.keySet();
  			Set keys=Manager.skeleton.nodeRegister.keySet();
    	
    		//out.println("<HR>");
    		out.println("<html>");
    		out.println("  <body>");

    		out.println(BEGIN_COMPONENT);
    		out.println("      "+"Root");
    		out.println(END_COMPONENT);
    		out.println("    <IMG SRC=\""+"Root"+"."+type+"\">");

    		//Thomas
        	addDetailsForSubtasks("/",out);
    	
    		for (Iterator i=keys.iterator();i.hasNext();) {
    	    	name = (String)i.next();
    	    	GenericComponent gc=Manager.skeleton.stringToFirstGenericComponent(name);
    	    	if (gc instanceof Task){
    	    		out.println(BEGIN_COMPONENT);
 				   	out.println("      "+name);
    				out.println(END_COMPONENT);

    	    		selectTaskAttributes((Task)gc,out);
    		    	if (Manager.skeleton.hasChildNode(name)) {
    		    		out.println(" <P>   <IMG SRC=\""+name+"."+type+"\"> </P>");
	    	    	   	addDetailsForSubtasks(name,out);
	    	        }
	    	        
	    	        Manager.RTFDBM.reportRTF_HTML(name,out);
	    	    }
    		}
    
    		out.println("  </body>");
    		out.println("</html>");

    		out.close();
    	
	     	MainFrame.mainFrame.setCursor(Manager.waitCursor);

    		imagesCreation(Manager.skeleton.root,FOLDER,"ROOT",new TreeSet());//"save/","ROOT",new TreeSet());

    	    MainFrame.mainFrame.setCursor(Manager.normalCursor);
	   		Toolkit.getDefaultToolkit().beep();

   			System.out.println("folder name : " +  FOLDER);
    	}
    	catch (Exception e) {
    		System.out.println("Error: "+(e.toString()));
    	}
    }
 }