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

public class KernelTree extends Graph {
    //protected static final String TOP_ROOT = "/";
    protected String ROOT_STRING;
    protected static final Integer ROOT_ID = new Integer(9999);

    public KernelTree(String rootString){
    	super((rootString==null)?"/": rootString);   //TOP_ROOT:rootString);  
    	ROOT_STRING=(rootString==null)?"/": rootString;   // TOP_ROOT:rootString;     
    }
    
    //-----------------------------------------------------------
    //               parent and child node operations
    //-----------------------------------------------------------
    
    /**
     * Returns a GenericComponent if found.
     */
    public GenericComponent stringToGenericComponent(String s,String parentS) {
        return getComponent(s,parentS);
    }
    
    public GenericComponent stringToGenericComponent(String s,String parentS,Integer id2) {
        return getComponent(s,parentS,id2);
    }
    
    public GenericComponent stringToFirstGenericComponent(String s) {
        return getFirstComponent(s);
    }
    
    public int numOfParents(String name) {
        int result = 0;
        
        if (name.equals(ROOT_STRING)) return result;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap) nodeRegister.get(name);
            
            result = t.size();
        }
        
        return result;
    }
    
    public boolean isInTree(String s) {
    	if (s.equals(ROOT_STRING)) return true;
    	else return (isInRegister(s));
    }
    
    public boolean isInTree(String name,String parentName,Integer id2) {
        boolean result = false;
        
        if (name.equals(ROOT_STRING)) return result;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap) nodeRegister.get(name);
            
            if (t.containsKey(parentName)) {
                Node parentNode = (Node)t.get(parentName);
                
                result = parentNode.hasChild(name,id2);
            }
        }
        
        return result;
    }

    public boolean isInTree(String name, Integer id2) {
        boolean result = false;
        
        if (name.equals(ROOT_STRING)) return result;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap) nodeRegister.get(name);
            
            for (Iterator i=(t.keySet()).iterator();i.hasNext();) {
                String parentName = (String) i.next();
                Node parentNode = (Node) t.get(parentName);
                
                if (parentNode.hasChild(name,id2)) {
                    result = true;
                    break;
                }
            }
        }
        
        return result;
    }

    // s may contain '*' for wild-card search 
    // it check if s is in nodeRegister
    public boolean isInTree_wild_card_search(String s) {
    	// search if s contains '*'
    	int i = s.indexOf('*');
    	if (i<0) return isInTree(s);
    	else {
	    	// searching if s with '*' is in the tree : e.g. *ask*3*
    		return (isInRegister_wild_card_search(s));
    	}
    }

    public boolean isRoot(String s) {
        return (s.equals(ROOT_STRING));
    }

        
    public boolean hasParentNode(String s) {
    	//Thomas
    	//return ((!(s.equals(ROOT_STRING)))||isInTree(s));
    	return ((!(s.equals(ROOT_STRING)))&&isInTree(s));
    }
    
    public boolean hasChildNode(String name) {
    	if (name.equals(ROOT_STRING)) return true;
    	else if (isInTree(name)) return !getFirstNode(name).hasLeaf(name);
    	     else return false;   
    }
    
    public boolean hasChildNode(String name,Integer id2) {
        if (name.equals(ROOT_STRING)) return true;
        else {
            if (isInTree(name)) {
                String parentName = toParentName(name,id2);
                if (parentName != null) {
                    Node parentNode = getNode(name,parentName);
                    return !parentNode.hasLeaf(name,id2);
                }
                else return false;
            }
            else return false;   
        }
    }
    
    /**
     * return null if the node is the root
     * get parent node corresponding to s
     */
    public Node toParentNode(String name,String parentName) {
    	if (name.equals(ROOT_STRING)) return null;
    	else return getNode(name,parentName);
    }
    
    /**
     * returns null if the node is a leaf
     * get node corresponding to name,parentName
     */
    public Node toChildNode(String name,String parentName) {
    	if (name.equals(ROOT_STRING)) return getRoot();
    	else
    		if (isInTree(name)) {
    			Node parentNode = getNode(name,parentName);

    			if (!parentNode.hasLeaf(name)) return parentNode.getChild(name);
    	       	else return null;
    	   }
    	   else return null;
    }
    
    public Node toChildNode(String name,String parentName,Integer id2) {
    	if (name.equals(ROOT_STRING)) return getRoot();
    	else
    		if (isInTree(name)) {
    			Node parentNode = getNode(name,parentName);

    			if (!parentNode.hasLeaf(name,id2)) return parentNode.getChild(name,id2);
    	       	else return null;
    	   }
    	   else return null;
    }

    public Node toChildNode(String name,Integer id2) {
        if (name.equals(ROOT_STRING)) return getRoot();
        else
            if (isInTree(name)) {
                String parentName = toParentName(name,id2);
                Node parentNode = getNode(name,parentName);

                if (!parentNode.hasLeaf(name,id2)) return parentNode.getChild(name,id2);
                else return null;
           }
           else return null;
    }
    
    /**
     * returns null if the node is a leaf
     * get node corresponding to name from its first parent with first ID
     */
    public Node toChildNode(String name) {
    	if (name.equals(ROOT_STRING)) return getRoot();
    	else 
    	   if (isInTree(name)) {
    	       Node firstParentNode = getFirstNode(name);
    	       
    	       if (!firstParentNode.hasLeaf(name)) return firstParentNode.getChild(name);
    	       else return null;
    	   }
    	   else return null;
    }
    
    public Node[] toChildNodes(String name) {
        Node [] result = null;
        
        if (name.equals(ROOT_STRING)) {
            result = new Node[1];
            result[0] = getRoot();
        } else {
            if (isInTree(name)) {
                Node[] parentNodeArray = getNodes(name);
                
                result = new Node[parentNodeArray.length];
                
                for (int i = 0; i < parentNodeArray.length; i++) {
                    Node parentNode = parentNodeArray[i];
                    
                    if (!parentNode.hasLeaf(name)) result[i] = parentNode.getChild(name);
                    else result[i] = null;
                }
            }
        }
        
        return result;
    }

    public int getNumInstance(String name) {
        int result = 0;
        
        if (name.equals(ROOT_STRING)) return result;
        
        if (nodeRegister.containsKey(name)) {
            TreeMap t = (TreeMap)nodeRegister.get(name);
            
            Set keys = t.keySet();
            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 String toParentName(String name) {
    	if (name.equals(ROOT_STRING)) return ROOT_STRING;
    	else 
    	   if (isInTree(name)) {
    	       return getFirstParent(name);
    	   }
    	   else return null;
    }
    	
    public String toParentName(String name,Integer id2) {
        if (name.equals(ROOT_STRING)) return ROOT_STRING;
        else 
           if (isInTree(name)) {
               return getParent(name,id2);
           }
           else return null;
    }

    private boolean checkIfParentsRecursiveTask(String oldName, String newName) {
        if (oldName.equals(ROOT_STRING)) return false;
        
        //System.out.println("oldName = "+oldName);

        if (nodeRegister.containsKey(oldName)) {
            TreeMap t = (TreeMap)nodeRegister.get(oldName);

            String parentName;
            //Node parentNode;
            Set keys = t.keySet();
            for (Iterator it = keys.iterator();it.hasNext();) {
                parentName = (String)(it.next());
                
                //System.out.println("    parentName = "+parentName);
                
                if (parentName.equals(newName)) return true;
                
                //parentNode = (Node) t.get(parentName);
                
                if (!parentName.equals(ROOT_STRING)) {
                    if (checkIfParentsRecursiveTask(parentName,newName)) return true;
                }

                //System.out.println("");
            }
        }
        
        return false;
    }

    private boolean checkIfChildrenRecursiveTask(String oldName, String newName) {
        return checkIfParentsRecursiveTask(newName,oldName);
    }
    
    public boolean checkIfRecursiveTask(String oldName, String newName) {
        //System.out.println("checkIfParentsRecursiveTask : newName = "+newName);
        
        // check if any of the parents of oldName is also called newName
        if (checkIfParentsRecursiveTask(oldName,newName)) return true;
        
        //System.out.println("checkIfChildrenRecursiveTask : ");
        
        // check if any of the childrens of oldName is also called newName
        if (checkIfChildrenRecursiveTask(oldName,newName)) return true;
        
        return false;
    }
        
    public Integer toChildNodeID(String name) {
    	if (name.equals(ROOT_STRING)) return ROOT_ID;
    	else 
    	   if (isInTree(name)) {
    	       Node firstParentNode = getFirstNode(name);
    	       
    	       if (!firstParentNode.hasLeaf(name)) return firstParentNode.getChildID(name);
    	       else return null;
    	   }
    	   else return null;
    }
}