/**
 *  Tamot --- Task Modelling Editor
 *  Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
 *  (CSIRO), Australia. All rights reserved. 
 *
 *  The Software, owned by CSIRO Australia, habeen developed by the CSIRO 
 *  Intelligent Interactive Technology group. s 
 *  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. 
 *
 *  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 tmrose;

import java.util.*;
import rose.*;
import rosetm.*;
import tmrose.*;
import domainModel.*;
import taskModellingTool.*;

/**
 * class UseCaseDiagramTM is a wrapper class for RoseClassDiagram generated by 
 * using J-Integra. (See  <A HREF="http://www.linar.com/">http://www.linar.com/</A><P>)
 * The aim of this class is to provide customised functionality for create 
 * usecase diagrams, 20-11-2001
*/

public class TaskRoseManager{
	private static RoseApplication _a;
    private static IRoseModel _m;
    private static IRoseCategory _useCaseView;
    private static IRoseCategory _logicalView;
    private static IRoseClassDiagram _mainUseCaseDia; 
    private static IRoseClassDiagram _mainClassDia; 
	private static TreeMap _useCases = new TreeMap();
    public static final String ROSE_MAIN_USECASE_DIAGRAM_NAME  = "Main";
    public static final String ROSE_MAIN_CLASS_NAME  = "Main";
    public static final String ROSE_ASSOCIATION_NAME  = "use";
    public static final String ROSE_ACTOR_STEREOTYPE  = "Actor";
    
    public static  boolean _heuristicScenarioDia  = true;
    private static String _domain=null, _userName= null, _password=null;
    private static LoginDialog _login=null;
    
	//name and IRoseInstanceView pair for scenario diagrams
    //_objectViews is reset in createSceDiaSkeleton()
	private static TreeMap _objectViews = new TreeMap(); 
	private static TreeMap _objectInstances = new TreeMap(); 

	public static boolean init() {
	    //System.out.println( "initialise " );
    	_useCases = new TreeMap();
    	
    	if (!login()) {
    		//System.out.println( "uer name = " + _userName+" password =" + _password);
     		return false;
   		}

    	try{
	        //System.out.println( "uer name = " + _userName+" password =" + _password);
			//com.linar.jintegra.AuthInfo.setDefault("CMIS", "shijian", "password");
			com.linar.jintegra.AuthInfo.setDefault(_domain, _userName, _password);
    	}catch (Exception e) {
    		System.out.println("login falied!! "+e);
    		return false;
    	}
    	
    	try {
	        RoseModel rm1 =  new RoseModel();
	        _a = new rose.RoseApplication(rm1.getApplication());
	        _m = _a.newModel();
	        _m.setName("newTest");
	        _a.setVisible(true);
	
	        //	x.a.openModel("C:\\Data\\Isolde\\Tamot2\\Current\\test.mdl");
	        _useCaseView =_m.getRootUseCaseCategory();
	        _logicalView =_m.getRootCategory(); //setRootCategory( rc);
		    
			//get main usecase diagram  
			IRoseClassDiagram tempUCD = null;
			IRoseClassDiagramCollection ucDiaCol = _useCaseView.getClassDiagrams();
	   	    //System.out.println( "number of usecase diagrams = "+ ucDiaCol.getCount());
		    for (short i = 1; i<= ucDiaCol.getCount(); i++){
	        	tempUCD=(IRoseClassDiagram)ucDiaCol.getAt(i);
	        	//System.out.println( "use case diagram name = " + tempUCD.getName());
	        	if (tempUCD.getName().equals(ROSE_MAIN_USECASE_DIAGRAM_NAME)){
	        		_mainUseCaseDia= tempUCD;
					break;
	        	}
	        }
			//get main class diagram  
			tempUCD = null;
			ucDiaCol = _logicalView.getClassDiagrams();
		    for (short i = 1; i<= ucDiaCol.getCount(); i++){
	        	tempUCD=(IRoseClassDiagram)ucDiaCol.getAt(i);
	        	if (tempUCD.getName().equals(ROSE_MAIN_CLASS_NAME)){
	        		_mainClassDia= tempUCD;
					break;
	        	}
	        }
	        return true;
	        
    	}catch (Exception e2) {
    		System.out.println("Rose initialization falied!! "+e2);
    		return false;
    	}
    }
    
    public static void main(String[] args) throws
    	java.net.UnknownHostException,
    	java.io.IOException, 
    	com.linar.jintegra.AutomationException {
    		
		init();    
    }
    
	/**
    * containsCompositeTask
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @return    return value.  "true" if the node in question
   	* contains composite tasks, otherwise, "false"
   	*/
    public static boolean containsCompositeTask(Node node){
    	Set keys=node.keySet();
    	Couple c;
    	LinkableComponent lc;
    	String childName;   	
   		//go through each component in the node
    	boolean first;
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (c.getObject() instanceof LinkableComponent){
    	    	lc=(LinkableComponent)c.getObject();
    	    		
                //only for a CompositeComponent
    	    	if (!c.getNode().isEmpty()){
    	    	    return true;
    	    	}
    	    }
    	}
    	return false;
    }
    
	/**
    * containsBranches
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @return    return value.  "true" if the node in question
   	* contains branches, otherwise, "false"
   	*/
    public static boolean containsBranches(Node node){
    	Set keys=node.keySet();
    	Couple c;
    	Link l;
    	LinkableComponent lc;
    	String childName; 
    	ArrayList start = new ArrayList();
    	ArrayList end = new ArrayList();
   		//go through each component in the node
    	boolean first;
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (!(c.getObject() instanceof LinkableComponent)){
    	    	l=(Link)c.getObject();
    	    	
    	    	if (l.getFirstLC() != null && l.getSecondLC() != null){
	    	    	lc = l.getFirstLC();
	    	    	if (start.contains(lc))	return true;
	    	    	else start.add(lc);
	    	    	
	    	    	lc = l.getSecondLC();
	    	    	if (end.contains(lc))	return true;
	    	    	else end.add(lc);
    	    	}
    	    	
    	    }
    	}
    	return false;
    }
    
	/**
    * containsTask
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @return    return value.  "true" if the node in question
   	* contains any task, otherwise, "false"
   	*/
    public static boolean containsTask(Node node){
    	Set keys=node.keySet();
    	Couple c;
    	String childName;   	
   		//go through each component in the node
    	boolean first;
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (c.getObject() instanceof Task){
    	    	    return true;
    	    }
    	}
    	return false;
    }
    
	/**
    * generateRoseModel
    *
   	*/
    public static void generateRoseModel(){
    	try{						
	    	if (!init()) return;    
	    	if (containsTask(Manager.getSkeleton().getRoot())){
	    		generateRoseModel(ROSE_MAIN_USECASE_DIAGRAM_NAME,
	    			Manager.getSkeleton().getRoot(), null);
	    		saveModel();		
	    	}else return;
    	}
 		catch (Exception e)
		{
			System.err.println("generate rose model failed! "+ e);
		}
   }
    
	/**
    * generateRoseModel
    *
   	*/
    private static void generateRoseModel(String nodeName, 
    						Node node,IRoseUseCase parent){
    	
    	if (containsCompositeTask(node) ||
    		containsBranches(node)){
    		//create usecase diagram
    		createUseCasediagram(nodeName, node, parent);
		} else{
			//create scenario daigrams
			if (_heuristicScenarioDia)
	    		createSceDiaWithHeuristics(nodeName, node,parent);
	    	else
	    		createSceDia(nodeName, node,parent);
		}
    	return;
    }
    
	/**
    * generateRoseModel
    *
   	*/
    private static void createUseCasediagram(String nodeName,
    						Node node,IRoseUseCase parent){
		try {
	    	IRoseClassDiagram currentUCDia= null;
	    	//first create usecase Diagram
	    	if(parent == null){
	    		currentUCDia = _mainUseCaseDia;
	    	} else{
	    		currentUCDia = parent.addUseCaseDiagram(nodeName);
	    	}
	  System.out.println( " use casedia name= "+ currentUCDia.getName());
  	
	    	Set keys=node.keySet();
	    	Couple c;
	    	LinkableComponent lc;
	    	String childName;
	    	LinkedList list=new LinkedList();
	    	int nb=0;
	  System.out.println( " use casedia 2 ");
	    	
	    	//TreeMap useCases = new TreeMap();
	   		IRoseUseCase ucTemp;
	     	ArrayList links = new ArrayList();
	     	Task t;
	  		//1. create useCases add them to the usecase diagram
	    	for (Iterator it=keys.iterator();it.hasNext();){
	            childName=(String)it.next();
	    	    c=node.getCouple(childName);
	   	    	if (c.getObject() instanceof Task){
	   	    		t =(Task)c.getObject();
	   	    		//System.out.println( " task name= "+ t.getName());

	   	    		if (CategoryTM.getUseCase(_useCaseView,t.getName()) == null){
						//if (_useCaseView == null)  
						//	System.out.println( " use case vies is null= ");
	   	    			ucTemp= _useCaseView.addUseCase( t.getName());
						//if (_useCases == null)  
						//	System.out.println( " use cases is null= ");
						_useCases.put(ucTemp.getName(), ucTemp);
						//System.out.println( " use case created= "+ t.getName());
			 System.out.println( " use casedia 3 ");

						}else
							ucTemp= CategoryTM.getUseCase(_useCaseView,t.getName());

					if (ucTemp != null){
						if (currentUCDia != null){
	    	    	   System.out.println( " use case name =   "+ ucTemp.getName());
	    	    			currentUCDia.addUseCase(ucTemp);
	    	    	   System.out.println( " use casedia 3.2 ");
	
	    	    		}else 
	    	    			System.out.println( "current use case diagram is null");
					} 
					
	                //only for a CompositeComponent
	    	    	if (!c.getNode().isEmpty()){
	    	    	    list.add(c.getNode());
	    	    	    list.add(childName);
	    	    	    nb++;
	    	    	}
	    	    }
	    	    else if (c.getObject() instanceof Link){
	    	    	links.add((Link)c.getObject());
	    	    }
	    	}
	   System.out.println( " use casedia 4 ");

	    	//now create association between tasks linked
	    	createAssociations(_useCases, 
	    		Collections.unmodifiableCollection(links),currentUCDia);
	    	
	    	//one level down the tree 
	    	Node n;
	    	for (int i=0;i<nb;i++){
	    	    n=(Node)list.removeFirst();    	    
	    	  	childName=(String)list.removeFirst();
	    	  	IRoseUseCase pa =(IRoseUseCase)_useCases.get(childName);
	    	    generateRoseModel(childName,n, pa);
	    	}
		}
		catch (Exception e)
		{
			System.err.println("create usecase diagram failed!!!! "+ e);
		}
    }
    
	/**
    * getAllLinks
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @return    return value.  a collection which contains 
   	* all links included in the node
   	*/
    public static Collection getAllLinks(Node node){
    	Set keys=node.keySet();
    	Couple c;
    	Link l;
    	String childName; 
    	ArrayList links = new ArrayList();
   		//go through each component in the node
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (c.getObject() instanceof Link){
    	    	l=(Link)c.getObject();
    	    	links.add(l);
    	    }
    	}
    	return Collections.unmodifiableCollection(links);
    }
    
	/**
    * getAllLinks
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     from (in); the linkabelcomponent a link starts.
   	* @return    return value.  a collection which contains 
   	* all links in the node which has "from" as starts point
   	*/
    public static Collection getAllLinks(Node node, LinkableComponent from){
    	Set keys=node.keySet();
    	Couple c;
    	Link l;
    	String childName; 
    	ArrayList links = new ArrayList();
   		//go through each component in the node
    	boolean first;
    	for (Iterator it=keys.iterator();it.hasNext();){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (c.getObject() instanceof Link){
    	    	l=(Link)c.getObject();
    	    	if (l.getFirstLC().equals(from))
    	    		links.add(l);
    	    }
    	}
    	return Collections.unmodifiableCollection(links);
    }
    
    //    	createAssociations(, 
    //		Collections.unmodifiableCollection(links));

    
	/**
    * createAssociations
    *
   	* @param     useCases (in); name-usecase pairs to be considered
   	* @param     links (in); collection of all present links.
   	* create associations between use-cases whose corresponding 
   	* tasks are linked
   	*/
    public static void createAssociations(TreeMap useCases, 
    								Collection links,IRoseClassDiagram ucDiag){
    	try{
	    	Link l;
	    	LinkableComponent from, to;
	    	IRoseUseCase toUC, fromUC;
	    	Iterator it = links.iterator();
			while (it.hasNext()){
				l = (Link)it.next();
				from = l.getFirstLC();
				to = l.getSecondLC();
				
				if (from instanceof Task ){
					fromUC = (IRoseUseCase)useCases.get(from.getName());
					
					if(to instanceof Task){
						toUC = (IRoseUseCase)useCases.get(to.getName());
						addDirectionalAssociation(toUC.getName(),
							fromUC,ROSE_ASSOCIATION_NAME, ucDiag);
					} else{
						createAssociationsBool(fromUC,to,links, ucDiag);
					}
				}
			}
		}
		catch (Exception e)
		{
			System.err.println("create associations failed! "+ e);
		}
    }
    
	/**
    * createAssociationsBool
    *
   	* @param     useCases (in); name-usecase pairs to be considered
   	* @param     links (in); collection of all present links.
   	* create associations between use-cases whose corresponding 
   	* tasks are linked
   	*/
    public static void createAssociationsBool(IRoseUseCase fromUC, 
    						LinkableComponent bool,Collection links,
    							IRoseClassDiagram ucDiag){
    	try{
	    	Link l;
	    	LinkableComponent from, to;
	    	IRoseUseCase toUC;
	    	Iterator it = links.iterator();
			while (it.hasNext()){
				l = (Link)it.next();
				from = l.getFirstLC();
				to = l.getSecondLC();
				
				if (from.equals(bool) ){				
					if(to instanceof Task){
						addDirectionalAssociation(to.getName(),
							fromUC,ROSE_ASSOCIATION_NAME, ucDiag);
					} else{
						createAssociationsBool(fromUC,to,links, ucDiag);
					}
				}
			}
		}
		catch (Exception e)
		{
			System.err.println("create association bool failed! "+ e);
		}
    }
	
  /**
   * addDirectionalAssociation. 
   *
   * @param     fromName(in); a roseItem name will point to this usecase
   * @param     associationName (in); association name.
   * @return    return value.  An reference to a IRoseAssociation
   * @exception java.io.IOException If there are communications problems.
   * @exception com.linar.jintegra.AutomationException If the remote server throws an exception.
   */
	public static IRoseAssociation addDirectionalAssociation  (
	          			String fromName,
	          			IRoseUseCase to,
	          			String associationName,
	          				IRoseClassDiagram ucDiag ) {
	    
	    if (to == null) return null;
	    
		try {
	        String assName = "";
	        IRoseAssociation asso=to.addAssociation(assName,fromName);
	        asso.setName(associationName);
	        IRoseRole role= asso.getRole1();
			asso.setRoleForNameDirection(role);
			ucDiag.addAssociation(asso);
			return asso;
	
		}
		catch (Exception e)
		{
			System.err.println("create direction association failed! "+ e);
			return null;
		}
	}
		
	/**
    * createSceDia
    *
   	*/
    private static void createSceDia(String nodeName,
    						Node node,IRoseUseCase parent){
    							
		try {
	    	//IRoseClassDiagram currentClassDia= _mainClassDia;
	    	
	    	IRoseScenarioDiagram currentSceDia= null;
	    	//first create usecase Diagram 
	    /*		
	    	short type =1;
	    	if(parent == null){
	    		//if no use case, add the scenario diagram to the 
	    		//use case view category
	    		
   	    		if (CategoryTM.getScenDia(_useCaseView,nodeName) ==null)
	    			currentSceDia = _useCaseView.addScenarioDiagram(nodeName, type);
				else{
					currentSceDia= CategoryTM.getScenDia(_useCaseView,nodeName);
					return;
				}
	    	} else{
   	    		if (UseCaseTM.getScenDia(parent,nodeName) ==null)
	    			currentSceDia = parent.addScenarioDiagram(nodeName, type);
				else{
	    			currentSceDia = UseCaseTM.getScenDia(parent,nodeName);
	    			return;
				}
	    	}
	    */	
	    	if (sceDiaExists(nodeName,parent)) return;
	    	else
	    		currentSceDia =createSceDiaSkeleton(nodeName,parent);
	    		
	     	Task t, t1;
	     	short messageIndex=1;
	     	Iterator it = getStartingTasks(node).iterator();

	     	while (it.hasNext()){
	     		t = (Task)it.next();
	     		//System.err.println(t.getName()+" index="+messageIndex );
	     		createMessage(t, messageIndex++,currentSceDia);
	     		t1=getNextTask(node,t);
	     		while ( t1 != null){
	     			createMessage(t1, messageIndex++,currentSceDia);
	     			if (getNextTask(node,t1) != null)
	     				t1=getNextTask(node,t1);
	     			else 
	     				t1 = null;
	     		}
	     	}
	     		
		}
		catch (Exception e)
		{
			System.err.println("create scenrio diagram failed! "+ e);
		}
    }
	
	/**
    * createSceDia
    *
   	*/
    private static void createSceDiaWithHeuristics(String nodeName,
    						Node node, IRoseUseCase parent){
    							
		try {
	    	//IRoseClassDiagram currentClassDia= _mainClassDia;
	    	
	    	IRoseScenarioDiagram currentSceDia= null;
	    	//first create usecase Diagram skeleton
	    	if (sceDiaExists(nodeName,parent)) return;
	    	else
	    		currentSceDia =createSceDiaSkeleton(nodeName,parent);
	    	
	     	Task t, t1,currentT,lastAutomaticT, preceedingT;
	     	
	     	short messageIndex=1;
	     	Iterator it = getStartingTasks(node).iterator();
			String actor, actee,mSenderClass,mReceiverClass;
			
	     	while (it.hasNext()){
	     		t = (Task)it.next();
	     		
	     		//initialize for every starting branch
	     		preceedingT= t;
	     		if (t.isAutomatic()){
	     			lastAutomaticT= t;
					System.err.println(" preceeding is automatic ");
	     		}else {
	     			lastAutomaticT= null;
					System.err.println(" preceeding is NOT automatic ");
	     		}
	     			
	     		//System.err.println(t.getName()+" index="+messageIndex );
	     		createMessage(t, messageIndex++,currentSceDia);
	     		t1=getNextTask(node,t);
	     		if (t1.isAutomatic()){
					System.err.println(" t1 is automatic ");
	     		}else {
					System.err.println(" t1 is NOT automatic ");
	     		}
	     		while ( t1 != null){
	     			if (!(preceedingT.isAutomatic()) &&
	     				t1.isAutomatic()){
	     				actor = getMessageReceiver(preceedingT);
	     				mSenderClass = getMesRecClass(preceedingT);
	     				createMessageActor(t1, messageIndex++,currentSceDia, 
	     								actor,mSenderClass);
	    	System.err.println("it comes here sender=  "+ actor);
			System.err.println(" it comes here  actor class= "+ mSenderClass);
	     								
	     			}else if (preceedingT.isAutomatic() &&
	     				!(t1.isAutomatic())) {
	     				actee = getMessageReceiver(preceedingT);
	     				mReceiverClass = getMesRecClass(preceedingT);
	     				createMessageActee(t1, messageIndex++,currentSceDia,
	     								actee,mReceiverClass);
	     			}else if (!(preceedingT.isAutomatic()) &&
	     				!(t1.isAutomatic()) && lastAutomaticT != null){
	     				actee = getMessageReceiver(lastAutomaticT);	
	     				mReceiverClass = getMesRecClass(lastAutomaticT);
	     				createMessageActee(t1, messageIndex++,currentSceDia,
	     									actee,mReceiverClass );
	     			} else {
	     				createMessage(t1, messageIndex++,currentSceDia);
	     			}
	     			
	     			if (getNextTask(node,t1) != null){
	     				preceedingT = t1;
			     		if (t1.isAutomatic())
			     			lastAutomaticT= t1;
			     			
	     				t1=getNextTask(node,t1);
	     				
	     			}else 
	     				t1 = null;
	     		}
	     	}
	     		
		}
		catch (Exception e)
		{
			System.err.println("create scenrio diagram with heuristics failed! "+ e);
		}
    }
    
	/**
    * createSceDiaSkeleton
    *
   	*/
    private static IRoseScenarioDiagram createSceDiaSkeleton(String nodeName,
    						/*	Node node,*/IRoseUseCase parent){
    							
		try {	    	
	    	short type =1;
	    	if(parent == null){
	    		//if no use case, add the scenario diagram to the 
	    		//use case view category 
	    		
   	    		if (CategoryTM.getScenDia(_useCaseView,nodeName) ==null){
   	    			_objectInstances.clear();
   	    			_objectViews.clear();
	    			return _useCaseView.addScenarioDiagram(nodeName, type);
	    		}else return null;
	    	} else{
   	    		if (UseCaseTM.getScenDia(parent,nodeName) ==null){
   	    			_objectInstances.clear();
   	    			_objectViews.clear();
	    			return parent.addScenarioDiagram(nodeName, type);
	    		}else return null;
	    	}
		}
		catch (Exception e)
		{
			System.err.println("create scenrio diagram skeleton failed! "+ e);
			return null;
		}
    }
    
	/**
    * createSceDiaSkeleton
    *
   	*/
    private static boolean sceDiaExists(String name,
    						IRoseUseCase parent){
    							
		try {	    	
	    	short type =1;
	    	if(parent == null){
	    		//if no use case, add the scenario diagram to the 
	    		//use case view category
   	    		if (CategoryTM.getScenDia(_useCaseView,name) !=null)
					return true;
				else 
					return false;
	    	} else{
   	    		if (UseCaseTM.getScenDia(parent,name) !=null)
	    			return true;
				else 
					return false;
	    	}
		}
		catch (Exception e)
		{
			System.err.println("sceDiaExists failed! "+ e);
			return false;
		}
    }
    
    
	/**
    * getFirstTask
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @return    return value.  the first task in the node 
   	*/
    public static Collection getStartingTasks(Node node){
    	Set keys=node.keySet();
    	Iterator it=keys.iterator();
    	Couple c;
	    LinkableComponent lc;
    	String childName; 
     	ArrayList startingTasks = new ArrayList();
  		//go through each component in the node
    	while (it.hasNext()){
            childName=(String)it.next();
    	    c=node.getCouple(childName);
   	    	if (c.getObject() instanceof LinkableComponent){
    	    	lc=(LinkableComponent)c.getObject();
    	    	if (Manager.isFirstComponent(lc)){
     	    		if (lc instanceof Task){
     	    			startingTasks.add((Task)lc);
     	    			//System.err.println("starting task "+ ((Task)lc).getName());

     	    		}else {
     	    			startingTasks.add( getNextTask(node, lc));
     	    		
     	    		}
    	    	}	
    	    }
    	}
     	//System.err.println("starting task SIZE "+ startingTasks.size());
    	return Collections.unmodifiableCollection(startingTasks);
    }
    
	/**
    * getFirstTask
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     bo (in); the BooleanConnector which begins the
   	* 			 sequence
   	* @return    return value.  the next task down the track 
   	*/
    public static Task getNextTask(Node node, LinkableComponent lc){
    	Link l;
    	LinkableComponent to;
    	Collection links = getAllLinks(node, lc);
    	Iterator it = links.iterator();
		while (it.hasNext()){
			l = (Link)it.next();
			to = l.getSecondLC();
		
			if(to instanceof Task){
     	    	return (Task)to;
			} else{
				return getNextTask(node, to);
			}
		}
    	return null;
    }
    
	/**
    * createMessage
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     bo (in); the BooleanConnector which begins the
   	* 			 sequence
   	* @return    return value.  the next task down the track 
   	*/
    public static void createMessage(Task t, short index,IRoseScenarioDiagram dia){
    	if (dia == null) return;
    	 
    	String mSender = getMessageSender(t);
    	String mReceiver =getMessageReceiver(t);
    	String m = getMessage(t);
    	String mSenderClass = getMesSenClass(t);
    	String mReceiverClass = getMesRecClass(t);
		createMessage2(t,index,dia, mSender, mReceiver,m,
			mSenderClass ,mReceiverClass);

		/*
    	try {	
	    	//add object instances to the scenario diagram
	    	IRoseObjectInstance insTemp1, insTemp2;
	   		IRoseInstanceView insViewTemp1, insViewTemp2;
	
	   		insTemp1 = dia.addInstance(mSender, mSenderClass);
	    	insTemp2 = dia.addInstance(mReceiver, mReceiverClass);
	    	
	    	insViewTemp1 = dia.addInstanceView(insTemp1, true);
	    	insViewTemp2 = dia.addInstanceView(insTemp2, true);
	    	
	    	//add message to the scenario diagram
	    	dia.createMessage(m, insTemp1, insTemp2, index);
	    	
	    	//add class or actor to Rose categories
	     	if (t.isAutomatic()){
		    	addClass(mSenderClass);
		    	IRoseClass clasTemp = addClass(mReceiverClass);
		    	if (clasTemp != null)
		    		addOperation(clasTemp,m);
	     	}else{
		    	addActor(mSenderClass);
		    	addClass(mReceiverClass);
	     	}
		}
		catch (Exception e)
		{
			System.err.println("add create message failed! "+ e);
		}
		*/
    }
    
	/**
    * createMessageActor
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     bo (in); the BooleanConnector which begins the
   	* 			 sequence
   	* @return    return value.  the next task down the track 
   	*/
    public static void createMessageActor(Task t, short index,
    				IRoseScenarioDiagram dia, String actor, String actorClass){
    	if (dia == null) return;
    	 
    	String mSender = actor;
    	String mReceiver =getMessageReceiver(t);
    	String m = getMessage(t);
    	String mSenderClass = actorClass;
    	String mReceiverClass = getMesRecClass(t);
		createMessage2(t,index,dia,mSender, mReceiver,m,
			mSenderClass ,mReceiverClass);
    }
    
	/**
    * createMessageActor
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     bo (in); the BooleanConnector which begins the
   	* 			 sequence
   	* @return    return value.  the next task down the track 
   	*/
    public static void createMessageActee(Task t, short index,
    				IRoseScenarioDiagram dia, String actee, String acteeClass){
    	if (dia == null) return;
    	 
    	String mSender = getMessageSender(t);
    	String mReceiver =actee;
    	String m = getMessage(t);
    	String mSenderClass = getMesSenClass(t);
    	String mReceiverClass = acteeClass;
		createMessage2(t,index,dia, mSender, mReceiver,m,
			mSenderClass ,mReceiverClass);
    }
    
	/**
    * createMessage2
    *
   	* @param     node (in); the node/expansion to be examnied.
   	* @param     bo (in); the BooleanConnector which begins the
   	* 			 sequence
   	* @return    return value.  the next task down the track 
   	*/
    private static void createMessage2(Task t, short index,
    				IRoseScenarioDiagram dia,String mSender,String mReceiver,
    								String m,String mSenderClass ,
    									String mReceiverClass){
    	try {	
	    	//add object instances to the scenario diagram 
	    	IRoseObjectInstance insTemp1, insTemp2;
	   		IRoseInstanceView insViewTemp1, insViewTemp2;
			
	   		if (_objectInstances.get(mSender) == null){
	   			insTemp1 = dia.addInstance(mSender, mSenderClass);
	    		_objectInstances.put(mSender,insTemp1);
	    		System.err.println("create NEW Object=  "+ insTemp1.getName());
	   		} else
	   			insTemp1 = (IRoseObjectInstance)_objectInstances.get(mSender);
	   			
	   		if (_objectInstances.get(mReceiver) == null){
	   			insTemp2 = dia.addInstance(mReceiver, mReceiverClass);
	    		_objectInstances.put(mReceiver,insTemp2);
	    		System.err.println("create NEW Object=  "+ insTemp2.getName());
	   		} else
	   			insTemp2 = (IRoseObjectInstance)_objectInstances.get(mReceiver);

	   		if (_objectViews.get(mSender) == null){
	    		insViewTemp1 = dia.addInstanceView(insTemp1, true);
	    		_objectViews.put(mSender,insViewTemp1);
	    		System.err.println("create NEW view=  "+ insViewTemp1.getName());
	   		}else
	   			insViewTemp1 = (IRoseInstanceView)_objectViews.get(mSender);

	   		if (_objectViews.get(mReceiver) == null){
	    		insViewTemp2 = dia.addInstanceView(insTemp2, true);
	    		_objectViews.put(mReceiver,insViewTemp2);
	    		System.err.println("create NEW view=  "+ insViewTemp2.getName());
	   		}else 
	   			insViewTemp2 = (IRoseInstanceView)_objectViews.get(mReceiver);
	   			
	    	//add message to the scenario diagram
	    	dia.createMessage(m, insTemp1, insTemp2, index);
	    	
			System.err.println(" create message receiver= "+ insTemp2.getName());
			
	    	//add class or actor to Rose categories
	     	if (t.isAutomatic()){
		    	addClass(mSenderClass);
		    	IRoseClass clasTemp = addClass(mReceiverClass);
		    	if (clasTemp != null)
		    		addOperation(clasTemp,m);
	     	}else{
		    	addActor(mSenderClass);
		    	addClass(mReceiverClass);
	     	}
		}
		catch (Exception e)
		{
			System.err.println("add create message failed! "+ e);
		}
    }
    
	/**
    * getMessage
    *
   	* @param     t (in); the task to be examnied.
   	* @return    return value.  the message in the task  
   	*/
    public static String getMessage(Task t){
    	if (t == null) return null;
    	
    	DmManager dmm = Manager.getXDM().getDmManager();
    	String m;;
    	
     	//set coarse message  
     	m =t.getName();
     	
     	//refine message if possible
     	ActionInstance ai = dmm.getAInstance(t.getSemantics());
     	if (ai != null)
     		m = ai.getConceptOf().getName();
     	
     	return m;
    }
    
	/**
    * getMessageSender
    *
   	* @param     t (in); the task to be examnied.
   	* @return    return value.  the message sender in the task  
   	*/
    public static String getMessageSender(Task t){
    	if (t == null) return null;
    	
    	DmManager dmm = Manager.getXDM().getDmManager();
    	String mSender;
    	
     	//set coarse  message sender 
     	if (t.isAutomatic())
     		mSender = EntityInstance.getDefaultSystemInstance().getName();
     	else
     		mSender = EntityInstance.getDefaultUserInstance().getName();
     	     	
     	if (t.getActor() != null && t.getActor().trim() != "")
     		mSender = t.getActor().trim() ;
     	
     	//refine message if possible
     	ActionInstance ai = dmm.getAInstance(t.getSemantics());
     	if (ai != null){
     		TreeMap insRel =ai.getActionRelations();
     		if (insRel.get(DmRelation.getActor()) != null){
     			mSender = ((EntityInstance)insRel.
     				get(DmRelation.getActor())).getName();
     		}
     	}
     	return mSender;
    }
    
	/**
    * getMessageReceiver
    *
   	* @param     t (in); the task to be examnied.
   	* @return    return value.  the message receiver in the task  
   	*/
    public static String getMessageReceiver(Task t){
    	if (t == null) return null;
    	
    	DmManager dmm = Manager.getXDM().getDmManager();
    	String mReceiver;

    	//set coarse message receiver 
		mReceiver = EntityInstance.getDefaultUserInstance().getName();
     	
     	//refine message receiver if possible
     	ActionInstance ai = dmm.getAInstance(t.getSemantics());
     	if (ai != null){
     		TreeMap insRel =ai.getActionRelations();
     		if (insRel.get(DmRelation.getActee()) != null){
     			mReceiver = ((EntityInstance)insRel.
     				get(DmRelation.getActee())).getName();
     		}
     		
     	}
     	return mReceiver;
    }
    
	/**
    * getMesRecClass
    *
   	* @param     t (in); the task to be examnied.
   	* @return    return value.  the message receiver's class in the task  
   	*/
    public static String getMesRecClass(Task t){
    	if (t == null) return null;
    	
    	DmManager dmm = Manager.getXDM().getDmManager();
    	String  mReceiverClass;
     	
     	//set course message and message sender 
		mReceiverClass = DmConcept.getDefaultUserConcept().getName();

		//refine receiver class if possible
     	ActionInstance ai = dmm.getAInstance(t.getSemantics());
     	if (ai != null){
     		TreeMap insRel =ai.getActionRelations();
     		if (insRel.get(DmRelation.getActee()) != null){
     			mReceiverClass = ((EntityInstance)insRel.
     				get(DmRelation.getActee())).
     				getConceptOf().getName(); 
     		}
     	}
     	return mReceiverClass;
    }
    
	/**
    * getMesSenClass
    *
   	* @param     t (in); the task to be examnied.
   	* @return    return value.  the message sender's class in the task  
   	*/
    public static String getMesSenClass(Task t){
    	if (t == null) return null;
    	
    	DmManager dmm = Manager.getXDM().getDmManager();
    	String mSenderClass;
     	
     	//set course message and message sender 
     	if (t.isAutomatic()){
     		mSenderClass = DmConcept.getDefaultSystemConcept().getName(); 
     	}else{
     		mSenderClass = DmConcept.getDefaultUserConcept().getName(); 
     	}
     	
     	//refine message if possible
     	ActionInstance ai = dmm.getAInstance(t.getSemantics());
     	if (ai != null){
     		TreeMap insRel =ai.getActionRelations();
     		if (insRel.get(DmRelation.getActor()) != null){
     			mSenderClass = ((EntityInstance)insRel.get(DmRelation.
     				getActor())).getConceptOf().getName(); 
     		}
     	}
      	return mSenderClass;
   }
        
	/**
    * addClass
    *
   	* @param     clasName (in); the name of the class to add.
   	* @return    return value.  the class in the Rose logical category 
   	*			 with the className if existing, otherwise, create a
   	*			 new class.
   	*/
    public static IRoseClass addClass( String clasName){
    	IRoseClass clsTemp= null;
		
    	try{
			//create class if necessary
			if (CategoryTM.getClass(_logicalView, clasName) != null)
				clsTemp = CategoryTM.getClass(_logicalView, clasName);
			else{
				clsTemp = _logicalView.addClass(clasName);
				_mainClassDia.addClass(clsTemp);
			}
			return clsTemp;
		}
		catch (Exception e)
		{
			System.err.println("add class failed! "+ e);
			return null;
		}
    }
        
	/**
    * addOperation
    *
   	* @param     clasName (in); the name of the class.
   	* @param     op (in); operation name.
   	* @return    return value.  the operation in the class 
   	*			 with the op as name if existing, otherwise, create a
   	*			 new operation.
   	*/
    public static IRoseOperation addOperation(IRoseClass clas, 
    										String op){
     	if (clas == null) return null;
		try{
	     	IRoseOperation opTemp;
	    	String returnType = "void";
			//create operation if necessary
			if (!(ClassTM.containOperation(clas,op)))
				return clas.addOperation(op,returnType);
			else 
				return ClassTM.getOperation(clas,op);
		}
		catch (Exception e)
		{
			System.err.println("add operation failed! "+ e);
			return null;
		}
    }
        
	/**
    * addActor
    *
   	* @param     actName (in); the name of the actor.
   	* @return    return value.  the operation in the class 
   	*			 with the op as name if existing, otherwise, create a
   	*			 new operation.
   	*/
    public static IRoseClass addActor(String actName){
    	IRoseClass clsTemp = null;
		try{
			//create class if necessary
			if (CategoryTM.getClass(_useCaseView, actName) != null)
				clsTemp = CategoryTM.getClass(_useCaseView, actName);
			else{
				clsTemp = _useCaseView.addClass(actName);
				clsTemp.setStereotype(ROSE_ACTOR_STEREOTYPE);
				//_mainUseCaseDia.addClass(clsTemp);
			}
	 		return clsTemp;
		}
		catch (Exception e)
		{
			System.err.println("add actor failed! "+ e);
			return null;
		}
   }
        
	/**
    * saveModel
    *
   	* @return    return value.  true, if model saved successfully
   	*							false, otherwise.
   	*/
    public static boolean saveModel(){
		try{
	    		//save the model
	    		return _m.save();
		}
		catch (Exception e)
		{
			System.err.println("save model failed! "+ e);
			return false;
		}
   }
   
   //HEURISTIC_SCENARIO
        
	/**
    * login
    *
    * login to window server
   	*/
    public static boolean login(){
    	if (_login == null ||
    		_domain == null ||
    		_userName == null ||
    		_password == null){
    		
    		_login = new LoginDialog(MainFrame.getMainFrame(),"Please Login");
    		
    		_domain =_login.getDomain();
    		_userName =_login.getUserName();
    		_password =_login.getPassword();
	    	if (_domain == null || _domain.equals("") ||
	    		_userName == null ||_userName.equals("") ||
	    		_password == null ||_password.equals("") ){
	    			return false;
	    	}else {
    			return true;
	    	}
    	}
	   	return true;
    		
   }
        
	/**
    * setHeuristicScenarioDia
    *
  	* @param     b (in); boolean value which determines whether 
  	* or not using heuristics when creating scenario diagrams.
	* set the value of  _heuristicScenarioDia to b.
	*/
    public static void setHeuristicScenarioDia(boolean b){
		_heuristicScenarioDia = b; 
		return;
   }
   
   
}