/*---------------------------------------------------------------------------
File:         			Operator.java
Package:                        JFLAP Version 3.1
Author:			        Ted Hung
                                
Description of Contents:	Contains abstract base class Operator.
				
--------------------------------------------------------------------------*/

/* 
 * Susan H. Rodger, Magda Procopiuc, Octavian Procopiuc, Eric Gramond, Ted Hung
 * Computer Science Department
 * Duke University
 * August 1999
 * Supported by National Science Foundation DUE-9596002, DUE-9555084,
 *  and DUE-9752583
 *
 * Copyright (c) 1999
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the author.  The name of the author may not be used to
 * endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package flap.operators;

import java.util.*;
import flap.*;
//
//
// operator
//
//
public abstract class Operator implements Cloneable
{
   public Environment environ;

   /**
    * sets the desktop that the nodes should be
    * displayed in
    */
   public void setEnvironment(Environment env)
   {
      environ = env;
   }

   /**
    * clones the operator so it can be used in a factory
    */
   abstract public Operator Clone();

   /**
    * returns the identifier that is specific to the
    * operator
    */
   abstract public String getIdentifier();

   /**
    * returns the priority of the given operator
    * so operator precedence can be handled
    */
   abstract public int getPriority();

   /**
    * returns whether the result of this operator can be concatenated with
    * for example "a*b", a* can be concatenated with
    * but not "a+bc", "a+b" cannot be concatenated with
    */
   abstract public boolean canConcatenate();
   
   /**
    * executes the given operator on the given operands
    */
   abstract public String execute(Stack operands);

   /**
    * returns the number of arguments that this operator
    * pops off of the stack
    */
   abstract public int numArguments();

   /**
    *  Finds the final state encountered given a starting node
    *  Used to find the final state of a detached subexpression FSA
    *  in the state diagram.  Returns the a vector of final states.
    */
   protected void findFinalSubExpFinal(State aState, Vector returnStates)
   {
      findFinalRecursive(aState, returnStates, new Vector());
   }

   protected void findFinalRecursive(State aState, Vector returnStates, Vector visited)
   {
      for(Enumeration e = visited.elements(); e.hasMoreElements(); )
      {
	 if(((State) e.nextElement()).id == aState.id)
	 {
	    return;
	 }
      }

      visited.addElement(aState);

      if(aState.isFinal)
      {
	 returnStates.addElement(aState);
      }

      Vector outnodes = new Vector();

      //get all of the transitions that leave 
      // the given transition
      Transition atrans;
      for(Enumeration e = environ.dfa.d.theTransitions.elements(); e.hasMoreElements(); )
      {
	 atrans = (Transition) e.nextElement();
	 if(atrans.from.id == aState.id)
	 {
	    outnodes.addElement(atrans.to);
	 }
      }

      State temp;
      for(Enumeration enum = outnodes.elements(); enum.hasMoreElements(); )
      {
	 findFinalRecursive((State) enum.nextElement(), returnStates, visited);
      }
   }

   /**
    * function to place two connected states on a specified desktop
    * trying to deal with placement problems.
    */
   protected void placeStates(Desktop d, State startState, State endState)
   {
      d.theStates.removeElement(startState);
      d.placeState(startState, d.theStates);
      d.theStates.addElement(startState);
   
      d.theStates.removeElement(endState);
      d.placeState(endState, d.theStates);
      d.theStates.addElement(endState);

      d.theStates.removeElement(startState);
      d.placeState(startState, d.theStates);
      d.theStates.addElement(startState);
   }
}

