/*
   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/.

   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 java.util.*;
import java.io.*;

/**
 * This class implement a tree structure used a TreeMap structure.
 * The TreeMap provided is based on a red-black tree. (The functioning
 * similar to a hash table. The elements are accessed using a key
 * (usualy a name). The advantage of a TreeMap compared to other maps is
 * that the elements can be easily listed in the order given by a
 * comparator (usualy lexicograhic order).   
 * <P><A HREF="../source/Graph.html#Graph_beginning">Source</A>
 */
///Graph_beginning
public class Graph implements Serializable {
    protected Node root;

    /**
     * Given the name of a GenericComponent, it is very long to fetch 
     * its position: the whole tree needs to be scanned until the
     * GenericComponent is found.
     * The purpose of this register is to have the position directly.
     */    
    protected TreeMap nodeRegister;
    
    /**
     * Creates a new Node and a new register
     * <P><A HREF="../source/Graph.html#Graph">Source</A>
     */
    public Graph(String rootName) {
    	root = new Node();
    	nodeRegister = new TreeMap();
    }
    
    /**
     * Returns the root node of the graph
     * <P><A HREF="../source/Graph.html#getRoot">Source</A>
     */
    public Node getRoot() {
    	return root;
    }
    
    public boolean isRoot(Node node) {
    	return (node==root);
    }
    
    
    //---------------------------------------------------------------
    //                  operations in the register
    //---------------------------------------------------------------
    /**
     * Adds a new entry to the register.
     * The register contain a node or a set of nodes.
     * <P><A HREF="../source/Graph.html#addInRegister">Source</A>
     */
    public void addInRegister(String name,Integer currentID,String parentName,Node parentNode) {
    //public void addInRegister(String name,String ParentName,Node parentNode) {
   	    //Thomas - to fix the NullPointerException error in printRegister()
    	if (parentNode == null) return;
    	
    	//System.out.print(" --- [addInRegister : name = "+name+", ID = "+currentID+", parent name = "+
    	//	parentName+"] --- ");
    	
    	if (!nodeRegister.containsKey(name)) {
            TreeMap t=new TreeMap();
            t.put(parentName,parentNode);
    	    nodeRegister.put(name,t);
    	} else {
    	    TreeMap t=(TreeMap)nodeRegister.get(name);
    	    t.put(parentName,parentNode);
    	}
    }
    
    /**
     * Add a new entry to the register, and
     * all the entries of subtree of name in node to the register
     * <P><A HREF="../source/Graph.html#addRecursivelyInRegister">Source</A>
     */
    public void addRecursivelyInRegister(String name,Integer currentID,String parentName,Node parentNode) {
    	addInRegister(name,currentID,parentName,parentNode);
    	
		if (parentNode.hasBranch(name)) {
			// get the node n of name
	    	Node currentNode = parentNode.getChild(name);
	    	
    	    Set keys = currentNode.keySet();					// get all task names of n
    	    /*String [] tab=new String[keys.size()];	// tab contains all the task names of n
            int i=0;
            for (Iterator it = keys.iterator();it.hasNext();)
	        	tab[i++]=(String)(it.next());
	        	
	    	for (i=0;i<tab.length;i++) 
	    		addRecursivelyInRegister(tab[i],name,currentNode);*/
    	    String childName;
    	    Integer childID;
            for (Iterator it = keys.iterator();it.hasNext();) {
	        	childName = (String)(it.next());
	        	
	        	for (Iterator itID = currentNode.getIDIterator(childName);itID.hasNext();) {
	        		childID = (Integer)(itID.next());
	    			addRecursivelyInRegister(childName,childID,name,currentNode);
	        	}
            }
		}
    }
    
    /**
     * Removes all the nodes whose name is <it>name</it>.
     * Do nothing if <it>name</it> is not a key.
     * <P><A HREF="../source/Graph.html#removeInRegister">Source</A>
     */
    public void removeFromRegister(String name) {
    	nodeRegister.remove(name);
    }
    
    /**
     * Remove the ParentName node in TreeMap, and 
     * remove name from the register if its TreeMap is emtpy; 
     * return the deleted node if present.
     */
    public Node removeFromRegister(String name,String parentName) {
    	Node result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t=(TreeMap)nodeRegister.get(name);
    	    
    	    //Thomas - to fix the NullPointerException error in printRegister()
    	    if (t.containsKey(parentName)) {
	    	    result=(Node)t.remove(parentName);
    	    
    		    if (t.isEmpty()) nodeRegister.remove(name);
    	    }
    	}
    	
    	return result;
    }

    /**
     * Returns true if the specified name is in the register 
     * <P><A HREF="../source/Graph.html#isInRegister">Source</A>
     */
    ///isInRegister
    public boolean isInRegister(String name) {
    	return nodeRegister.containsKey(name);
    }
    
    //Thomas
    // searching if searchTaskName with '*' is in tmpTaskName : e.g. *ask*3*
    public boolean string_wide_card_search(String tmpTaskName, String searchTaskName) {
    	char ch,ch1;
    	boolean starFlag = false;
    	int iLength = searchTaskName.length();
    	int iTmpIndex = 0;
    	int iPos;
    	
    	for (int iSearchIndex=0; iSearchIndex<iLength; iSearchIndex++) {
	    	ch = searchTaskName.charAt(iSearchIndex);
	    	if (ch == '*') {
	    		starFlag = true;
	    		continue;
	    	}
	    		
	    	if (starFlag) {
	    		iPos = tmpTaskName.indexOf(ch,iTmpIndex);
	    		if (iPos < 0) return false;
	    		
	    		iTmpIndex = iPos+1;
	    	} 
	    	else {
	    		ch1 = tmpTaskName.charAt(iTmpIndex++);
	    		if (ch != ch1) return false;
	    	}
	    	
	    	starFlag = false;
    	}
    	
    	if ( (!starFlag) && (iTmpIndex < tmpTaskName.length()) ) return false;
    	
    	return true;
    }

    
    //Thomas : return iterator for task names in nodeRegister
    public Iterator taskNameIterator() {
   	    Set keys = nodeRegister.keySet();		// get all task names of nodeRegister
		return keys.iterator();
    }
    
    //Thomas
	// searching if searchTaskName with '*' is in nodeRegister : e.g. *ask*3*
    public boolean isInRegister_wild_card_search(String searchTaskName) {
    	String tmpTaskName;
    	
   	    Set keys = nodeRegister.keySet();		// get all task names of nodeRegister
		for(Iterator it = keys.iterator();it.hasNext();) {
	       	tmpTaskName = (String)(it.next());
	       	if (string_wide_card_search(tmpTaskName,searchTaskName))
	       		return true;
		}
    	
    	return false;
    }
    	
    /**
     * Returns true if the specified name,parentName is in the register 
     * <P><A HREF="../source/Graph.html#isInRegister">Source</A>
     */
    public boolean isInRegister(String name,String parentName) {
    	boolean result = nodeRegister.containsKey(name);
    	
    	if (result) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    result = t.containsKey(parentName);
    	}
    	
    	return result;
    }
    
    /**
     * Returns the parent node if it is in the register, otherwise
     * returns null.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getNode
    public Node getNode(String name,String parentName) {
    	Node result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    result = (Node)t.get(parentName);
    	}
    	
    	return result;
    }

    /**
     * Return all the nodes of name if name is in the register, otherwise
     * return null.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getNodes
    public Node [] getNodes(String name) {
    	Node [] result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t=(TreeMap)nodeRegister.get(name);
    	    result = (Node[])(t.values()).toArray();
    	}
    	
    	return result;
    }

    /**
     * Returns the first parent node of name in register
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getFirstNode
    public Node getFirstNode(String name) {
    	Node result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    Node parentNode = (Node)t.get(t.firstKey());
    	    
    	    result = parentNode;
    	}
    	
    	return result;
    }

    public String getFirstParent(String name) {
    	String result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    result = (String)t.firstKey();
    	}
    	
    	return result;
    }

    public String getParent(String name,Integer id2) {
        String result = null;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap)nodeRegister.get(name);

            String parentName;
            Node parentNode;
            Integer tempID2;
            Set keys = t.keySet();
            for (Iterator it = keys.iterator();it.hasNext();) {
                parentName = (String)(it.next());
                parentNode = (Node) t.get(parentName);

                //System.out.println("getParent : "+parentName);
                for (Iterator itID = parentNode.getIDIterator(name);itID.hasNext();) {
                    tempID2 = (Integer)itID.next();
                    if (tempID2.equals(id2)) {
                        result = parentName;
                        return result;
                    }
                }
            }
        }
        
        return result;
    }

    /**
     * Return the GenericComponent of name,parentName if it is in the register, otherwise
     * return null.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getComponent
    public GenericComponent getComponent(String name,String parentName) {
    	GenericComponent result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
    	    if (t.containsKey(parentName)) {
    	    	result = ((Node)(t.get(parentName))).getComponent(name);
    	    }
    	}
    	
    	return result;
    }

    public GenericComponent getComponent(String name,String parentName,Integer id2) {
    	GenericComponent result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
    	    if (t.containsKey(parentName)) {
    	    	result = ((Node)(t.get(parentName))).getComponent(name,id2);
    	    }
    	}
    	
    	return result;
    }

    public int getPositionForDuplicatedTasks(String name,String parentName,Integer id2) {
    	int result = 0;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
    	    if (t.containsKey(parentName)) {
    	    	Node parentNode = (Node)t.get(parentName);

    	    	result = parentNode.getPositionForDuplicatedTasks(name,id2);
    	    }
    	}
    	
    	return result;
    }

    public int getNumDuplicatedTasks(String name) {
        int result = 0;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap)nodeRegister.get(name);
            
            Set keys = t.keySet();              // get all task names of n
            String parentName;
            Node parentNode;
            
            for (Iterator it = keys.iterator();it.hasNext();) {
                parentName = (String)(it.next());
                parentNode = (Node)t.get(parentName);
                
                result += parentNode.getNumCouples(name);
            }
        }
        
        return result;
    }

    public int getTreeIndex(String name,String parentName,Integer id2) {
    	int result = 0;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
    	    if (t.containsKey(parentName)) {
    	    	Node parentNode = (Node)t.get(parentName);

    	    	result = parentNode.getTreeIndex(name,id2);
    	    }
    	}
    	
    	return result;
    }
    
    /**
     * Returns the desired component if it is in the register, otherwise
     * returns null.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getComponent
    /*public GenericComponent getFirstComponent(String name){
    	GenericComponent result=null;
    	if (nodeRegister.containsKey(name)){
    	    TreeMap t=(TreeMap)nodeRegister.get(name);
    	    result=( (Node)t.get(t.firstKey()) ).getComponent(name);
    	}
    	return result;
    }*/

    /**
     * Return the array of GenericComponents of name if it is in the register, otherwise
     * return null.
     * Don't check the names of the components.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getComponents
    public GenericComponent [] getComponents(String name) {
    	GenericComponent [] result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
    	    Node parentNode;

    	    //find no. of GenericComponent
    	    int numGenericComponents = 0;
    	    for (Iterator i = (t.keySet()).iterator();i.hasNext();) {
    	        parentNode = (Node)(t.get(i.next()));
    	        numGenericComponents += parentNode.getNumCouples(name);
    	    }
    	    
    	    result = new GenericComponent[numGenericComponents];
    	    
    	    //fill array of GenericComponent
    	    int count=0;
    	    for (Iterator i = (t.keySet()).iterator();i.hasNext();) {
    	        parentNode = (Node)(t.get(i.next()));
    	        
        		for (Iterator itCurrentID = parentNode.getIDIterator(name);itCurrentID.hasNext();) {
	    			Integer id2 = (Integer)(itCurrentID.next());
		    		
	    	        result[count++] = parentNode.getComponent(name,id2);
		    	}
    	        
    	    }
    	}
    	
    	return result;
    }

    /**
     * Return the 1st GenericComponent of name if it is in the register, otherwise
     * return null.
     * <P><A HREF="../source/Graph.html#lookInRegister">Source</A>
     */
    ///getFirstComponent
    public GenericComponent getFirstComponent(String name) {
    	GenericComponent result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    
   	    	Node n = (Node)(t.get(t.firstKey()));
    	    result = n.getComponent(name);
    	}
    	
    	return result;
    }


    /**
     * return all the ParentName of oldName in register
     */
     public String[] toUpdate(String oldName) {
     	if (nodeRegister.containsKey(oldName)) {
     		String[] result;

     		//step 1: update the nodes' names in the register
    	    TreeMap t = (TreeMap)nodeRegister.get(oldName);
    	     
	    	result = new String[t.size()];
	     	int count=0;
    	 	for (Iterator i=(t.keySet()).iterator();i.hasNext();count++)
    	         result[count] = (String)(i.next());     

    	    return result;
         } 
         else 
         	return new String[0];
     }
     
    /**
     * Change the name of all the components of the same name
     */
    ///updateName
     public void updateName(String oldName,String newName) {
     	 if (nodeRegister.containsKey(oldName)) {
	    	//printRegister();				// for debug
     	 	//step 1: update names in nodes	     
            updateNamesInTree(oldName,newName);             
             
	    	//printRegister();				// for debug
    	    //step 2: update parent names in nodeRegister
            updateParentNamesInRegister(oldName,newName);
    	     
	    	//printRegister();				// for debug
    	    //step 3: update names in nodeRegister
            updateNamesInRegister(oldName,newName);
	    	//printRegister();				// for debug
         }
     }

     public void modifyItself_UpdateName(String oldName,Integer id2,String newName) {
         if (nodeRegister.containsKey(oldName)) {
             //System.out.println("Step1 : ");
             //printRegister();                // for debug
             //step 1: update parent node
             modifyItself_UpdateNamesInTree(oldName,id2,newName);             
             
             //System.out.println("Step2 : ");
             //printRegister();                // for debug
             //step 2: add new name in nodeRegister
             modifyItself_AddNewNameInRegister(oldName,newName);

             //System.out.println("Step3 : ");
             //printRegister();                // for debug
             //step 3: update parent names in nodeRegister
             modifyItself_UpdateParentNamesInRegister(oldName,id2,newName);

             //System.out.println("Step4 : ");
             //printRegister();                // for debug
         }
     }

    // update the nodes' names in the tree : 
    //   for all the nodes of oldName in register, 
    //     if task name = oldName, rename it to newName
    private void updateNamesInTree(String oldName,String newName) {    	
	    TreeMap t = (TreeMap)nodeRegister.get(oldName);
	    Set keys = t.keySet();
    	String parentName;
    	Node parentNode;

    	for (Iterator i = keys.iterator();i.hasNext();) {
    	 	parentName = (String)i.next();
    	 	parentNode = (Node)(t.get(parentName));
    	 	
     	    if (parentNode.containsKey(oldName)) {
     	    	Couple c = parentNode.removeCouple(oldName);
     	        c.object.setName(newName);
     	        parentNode.putCouple(c);
    		}
    	}
    }

    // modify itself : only modify the component with ID = id2
    //
    // update to newName in parentNode
    //
    private void modifyItself_UpdateNamesInTree(String oldName,Integer id2,String newName) {        
        TreeMap t = (TreeMap)nodeRegister.get(oldName);
        Set keys = t.keySet();
        String parentName;
        Node parentNode;

        for (Iterator i = keys.iterator();i.hasNext();) {
            parentName = (String)i.next();
            parentNode = (Node)(t.get(parentName));
            
            if (parentNode.hasChild(oldName,id2)) {
                 Couple c = parentNode.removeCouple(oldName,id2);
                 c.object.setName(newName);
                 parentNode.putCouple(c);
            }
        }
    }

    // update the parent nodes' names in the register
    private void updateParentNamesInRegister(String oldName,String newName) {
    	TreeMap t = (TreeMap)nodeRegister.get(oldName);    	
    	String childName,parentName;
    	Node parentNode,currentNode,oldNameNode;
    	Integer currentID,childID;
    	
        for (Iterator i=(t.keySet()).iterator();i.hasNext();) {
    	 	parentName = (String)i.next();
    	    parentNode = (Node)(t.get(parentName));
    	    
	        for (Iterator itID = parentNode.getIDIterator(newName);itID.hasNext();) {
   		    	currentID = (Integer)itID.next();
   		    	
	            if (parentNode.hasBranch(newName,currentID)) {
    	            currentNode = parentNode.getChild(newName,currentID);
                
    		        if (!currentNode.isEmpty())
     	    	        for (Iterator j = (currentNode.keySet()).iterator();j.hasNext();) {
    	        	        childName = (String)j.next();
    	                
    	            	    oldNameNode = removeFromRegister(childName,oldName);
	    	        
			        		for (Iterator itChildID = currentNode.getIDIterator(childName);itChildID.hasNext();) {
	    		    			childID = (Integer)(itChildID.next());
    	                
	    	                	addInRegister(childName,childID,newName,oldNameNode);
				        	}
    		            }
     		    }   	            	            
	        }
    	}
    }

    // modify itself : only modify the component with ID = id2
    //
    // duplicate another node, and then
    // duplicate another set of components in the immediate decomposition of oldName to newName
    // register the parent names of components in the decomposition to newName
    //
    //
    //                  currentNode
    // newName : id2 -----------------> childName : (childID) ------------------>
    //
    //
    private void modifyItself_UpdateParentNamesInRegister(String oldName,Integer id2,String newName) {
        TreeMap t = (TreeMap)nodeRegister.get(newName);
        String parentName;
        Node parentNode,currentNode,oldNameNode;
        Integer currentID;

        for (Iterator i=(t.keySet()).iterator();i.hasNext();) {
            parentName = (String)i.next();
            parentNode = (Node)(t.get(parentName));
            
            //printNode(parentNode,"parentNode");
            for (Iterator itID = parentNode.getIDIterator(newName);itID.hasNext();) {
                currentID = (Integer)itID.next();
                
                if (currentID.equals(id2)) {
                    if (parentNode.hasBranch(newName,currentID)) {
                        currentNode = parentNode.getChild(newName,currentID);
                        
                        Node duplicatedNode = new Node();
                        duplicatedNode.duplicateNode(currentNode);
                    
                        //printNode(currentNode,"currentNode1");
                        //printNode(duplicatedNode,"duplicatedNode1");

                        // make a duplicate set of components for currentNode
                        if (!duplicatedNode.isEmpty()) {
                            makeUniqueIDsInDecomposition(duplicatedNode,newName);

                            //printNode(currentNode,"currentNode2");
                            //printNode(duplicatedNode,"duplicatedNode2");
                            
                            parentNode.setChild(newName,currentID,duplicatedNode);
                        }

                        //Node node = (Node) parentNode.getChild(oldName);
                        //printNode(node,"old node");
                        //node = (Node) parentNode.getChild(newName);
                        //printNode(node,"new node");
                    }
                }
            }
        }
    }
    
    private void makeUniqueIDsInDecomposition(Node duplicatedNode,String newName) {
        String childName;
        Integer childID,newChildID;
        Couple couple;
        GenericComponent tmpGC;
        
        // get the static initial array of name first 
        // because the content of duplicateNode may change later
        Set keys = duplicatedNode.keySet();
        int ilength = keys.size();
        String [] nameArray = new String[ilength];
        int index = 0;
        for (Iterator j = keys.iterator();j.hasNext();) {
            nameArray[index] = (String)j.next();
            index++;
        }
        
        // make a new different set of unique IDs of the new decomposition
        for (index=0; index<ilength; index++) {
            childName = nameArray[index];

            //System.out.println("childName : "+childName);
            
            // get the static initial array of ID first 
            // because the content of duplicateNode may change later
            TreeMap tmID = (TreeMap) duplicatedNode.get(childName);
            Set keysID = tmID.keySet();
            int ilengthID = keysID.size();
            Integer [] childIDArray = new Integer[ilengthID];
            int indexID = 0;
            for (Iterator j = keysID.iterator();j.hasNext();) {
                childIDArray[indexID] = (Integer)j.next();
                indexID++;
            }
            
            /*for (Iterator itChildID = duplicatedNode.getIDIterator(childName);itChildID.hasNext();) {
                childID = (Integer)(itChildID.next());*/
            for (indexID=0; indexID<ilengthID; indexID++) {
                childID = childIDArray[indexID];
                
                // set new ID for each Couple in the immediate decomposition, i.e. currentNode
                couple = duplicatedNode.removeCouple(childName,childID);
                tmpGC = couple.object;
                tmpGC.setID();
                duplicatedNode.putCouple(couple);
                
                newChildID = new Integer(tmpGC.ID);
                
                //System.out.println("newChildID = "+newChildID);
                
                addInRegister(childName,newChildID,newName,duplicatedNode);
            }
        }
        
        updateLinks_ID_Comment_InNode(duplicatedNode);
    }
    
    private void updateLinks_ID_Comment_InNode(Node duplicatedNode) {
        String childName;
        Integer childID;
        Couple couple;
        GenericComponent tmpGC;
        Link link;

        Set keys = duplicatedNode.keySet();
        for (Iterator j = keys.iterator();j.hasNext();) {
            childName = (String)j.next();
            
            //System.out.println("updateAllConnectedLinksInNode : childName : "+childName);
            
            for (Iterator itChildID = duplicatedNode.getIDIterator(childName);itChildID.hasNext();) {
                childID = (Integer)(itChildID.next());
                
                //System.out.println("updateAllConnectedLinksInNode : newChildID = "+childID);
                
                couple = duplicatedNode.getCouple(childName,childID);
                tmpGC = couple.object;
                
                if (tmpGC instanceof Link) {
                    link = (Link) tmpGC;
                    
                    link.id1_XML = link.lc1.ID;
                    link.id2_XML = link.lc2.ID;

                    Manager.RTFDB.add(link.name);
                }
            }
        }
    }
    
    private void updateNamesInRegister(String oldName,String newName) {
    	 TreeMap told=(TreeMap)nodeRegister.remove(oldName);
    	         	     
    	 if (nodeRegister.containsKey(newName)) {
    	 	TreeMap tnew=(TreeMap)nodeRegister.get(newName);
	        tnew.putAll(told);
	     }
	     else
	     	nodeRegister.put(newName,told);
    }

    private void modifyItself_AddNewNameInRegister(String oldName,String newName) {
         TreeMap told=(TreeMap)nodeRegister.get(oldName);
                          
         if (nodeRegister.containsKey(newName)) {
             TreeMap tnew=(TreeMap)nodeRegister.get(newName);
            tnew.putAll(told);
         }
         else
             nodeRegister.put(newName,told);
    }

    
// DEBUG METHODS

    // display all names in register
    // for each name, 
    //		display all its ParentName
    public void printRegister() {
    	System.out.println("------------------- Register ----------------");
    	
    	if (nodeRegister.isEmpty())
    		System.out.println("Empty!!!");
    	else {
    	    String name,parentName,taskName;
    	    Node parentNode;
    	    
     	    for (Iterator i = (nodeRegister.keySet()).iterator();i.hasNext();) {
   	        	name = (String)i.next();
   	        	TreeMap t = (TreeMap)nodeRegister.get(name);
   	        	
   	        	GenericComponent tmpGC = null;
   	        	
   	        	System.out.println(name+" --> {");
     	        for (Iterator j = (t.keySet()).iterator();j.hasNext();) {
		    	 	parentName = (String)j.next();
    			 	parentNode = (Node)(t.get(parentName));
     	            
     	        	// print all components under parentName
    			 	System.out.print("      "+parentName+" : [");
     	            for (Iterator k = (parentNode.keySet()).iterator();k.hasNext();) {
			    	 	taskName = (String)k.next();
		   	        	System.out.print(taskName+", ");
     	            }
     	            System.out.println("]; ");

			    	if (parentNode.containsKey(name)) {
			    		Integer currentID,objectID;
			    		
			        	for (Iterator itID = parentNode.getIDIterator(name);itID.hasNext();) {
	    		    		currentID = (Integer)(itID.next());
    	                
			   	        	Couple tmpCouple = parentNode.getCouple(name,currentID);
			   	        	tmpGC = tmpCouple.object;
                            objectID = new Integer(tmpGC.ID);

                            if (currentID.equals(objectID)) {
                                 System.out.print("          ID = "+currentID);
                                 System.out.println(" : ("+tmpGC.getX()+","+tmpGC.getY()+
                                       ") width = "+tmpGC.getWidth()+", height = "+tmpGC.getHeight());
                            } else {
                                 System.out.print("          ID = "+currentID);
                                 System.out.print(", object ID = "+objectID);
                                 System.out.println(" : ("+tmpGC.getX()+","+tmpGC.getY()+
                                       ") width = "+tmpGC.getWidth()+", height = "+tmpGC.getHeight());
                            }
                            
                            if (tmpGC instanceof Link) dspLinkMsg((Link) tmpGC);
			        	}
	     	        }
     	        }
     	        System.out.println("}");
    			System.out.println("");
   	    	}
    	}
    	
	    //Thomas ?V5
    	System.out.println("max. unused ID = "+Manager.currentUnusedID);
    	System.out.println("");

    	System.out.println("--------------- End Register -------------");
    }
    
    private void dspLinkMsg(Link link) {
        Integer id1 = new Integer(link.lc1.ID);
        Integer id2 = new Integer(link.lc2.ID);
        
        System.out.println("          ID of lc1 = "+id1+", ID of lc2 = "+id2);
        System.out.println("          id1_XML = "+link.id1_XML+", id2_XML = "+link.id2_XML);
    }
    
    private void dspLinkMsg2(Link link) {
        Integer id1 = new Integer(link.lc1.ID);
        Integer id2 = new Integer(link.lc2.ID);
        
        System.out.print(" (ID of lc1 = "+id1+", ID of lc2 = "+id2);
        System.out.print("); (id1_XML = "+link.id1_XML+", id2_XML = "+link.id2_XML+")");
    }
    
    public void printNode(Node node,String nodeName) {
    	System.out.println("------------------- Node ----------------");
    	System.out.print(nodeName+" -->  ");
    	String name;
    	
        Integer id2,objectID;
        Couple tmpCouple;
        
    	System.out.println("{");
     	for (Iterator i=(node.keySet()).iterator();i.hasNext();) {
     		name=(String)(i.next());
     	    System.out.print("    "+name+" : [");
             
            for (Iterator itID = node.getIDIterator(name);itID.hasNext();) {
                id2 = (Integer)(itID.next());
                
                tmpCouple = node.getCouple(name,id2);
                GenericComponent tmpGC = tmpCouple.object;

                objectID = new Integer(tmpGC.ID);
                
                if (id2.equals(objectID))
                    System.out.print(id2+", ");
                else
                    System.out.print(id2+"("+objectID+"), ");

                if (tmpGC instanceof Link) dspLinkMsg2((Link) tmpGC);
            }
            
            System.out.println("]; ");
     	}
    	System.out.println("}");
    	
    	/*Node child;
     	for (Iterator i=(node.keySet()).iterator();i.hasNext();) {
     		name = (String)(i.next());
    	    child = (node.getCouple(name)).node;
    	    if (child!=null) printNode(child,name);
    	}*/
    	System.out.println("----------------- End Node ---------------");
    }
    
    public void printTree(){
    	System.out.println("------------------- Tree ----------------");
    	printNode(root,"Root");
    	System.out.println("----------------- End Tree --------------");

    }

    //shijian 2001-4-17
    public Set getAllParents(String name) {
    	Set result = null;
    	
    	if (nodeRegister.containsKey(name)) {
    	    TreeMap t = (TreeMap)nodeRegister.get(name);
    	    result = t.keySet();
    	}
    	
    	return result;
    }


}