src/java/isac/bridge/CalcTree.java
author rgradisc
Thu, 11 Dec 2003 11:16:07 +0100
changeset 1254 ec81f3c6561b
parent 1240 95c45efd7b28
child 1257 39bd7cc2925c
permissions -rw-r--r--
*** empty log message ***
     1 /*
     2  * Created on Sep 11, 2003
     3  */
     4 package isac.bridge;
     5 
     6 import isac.util.CalcChangedEvent;
     7 import isac.util.Formula;
     8 import isac.util.ICalcIterator;
     9 import isac.util.IToCalc;
    10 import isac.util.IToUser;
    11 import isac.util.Tactic;
    12 import isac.wsdialog.DialogGuide;
    13 
    14 import java.io.Serializable;
    15 import java.rmi.RemoteException;
    16 import java.util.Iterator;
    17 import java.util.Vector;
    18 
    19 /**
    20  * A CalcTree represents a Calculation: It is a tree which consists
    21  * of one CalcHead at the top and abitrarily many Formulas and Tactics.
    22  * SubCalculations (with separate CalcHeads) are also part of CalcTree
    23  * This is the main interface between the Bridge and the Dialog
    24  * The CalcTree calls methods of the Math Engine, which in turn are
    25  * delegated to the BridgeRMI object on the other side of the RMI connection
    26  * The communication with the SML Kernel is completly hided from
    27  * the Dialog and the Frontend.
    28  * @author rgradisc
    29  */
    30 public class CalcTree implements IToCalc, Serializable {
    31 
    32   private final static int SCOPE_CURRENT_SUBPROBLEM = 1;
    33   private final static int SCOPE_CURRENT_SUBCALCULATION = 2;
    34   private final static int SCOPE_WHOLE_CALCULATION = 3;
    35 
    36   private int id;
    37   private Vector listeners;
    38   private MathEngine mathEngine;
    39   private ICalcIterator hotSpot;
    40 
    41   /**
    42   Start a new calculation. In case of failure, 
    43   the constructor may change the formalization object to hint at incomplete or
    44   contradictory specifications. 
    45   <br> Under normal circumstances, only complete calcHeads should be passed. 
    46   <br> Check every CalcHead for completeness (with the
    47   static method checkcalcHead() before constructing a CalcTree
    48   * @param calcHead The CalcHead for this CalcTree
    49   */
    50   CalcTree(MathEngine mathEngine, int id) {
    51     this.id = id;
    52     this.mathEngine = mathEngine;    
    53     listeners = new Vector();
    54   }
    55 
    56   /**
    57   Attach another dialog to the existing calculation tree. 
    58   * @param dlg The new Dialog to be attached to this CalcTree
    59   */
    60   public void attach(DialogGuide dg) {
    61   	listeners.add(dg);
    62   }
    63 
    64   /**
    65   Get a new iterator referencing the root element of the calculation tree. 
    66   <p> The functionality for navigating the calculation 
    67   is implemented in the CalcIterator object.
    68   * @return new instance of CalcIterator
    69   */
    70   public ICalcIterator iterator() {
    71     return new CalcIterator(this);
    72   }
    73 
    74   /**
    75   Makes the passed formula the active formula, i.e. the formula 
    76   the next tactic is applied to.
    77   * @param newActiveFormula
    78   */
    79   public void moveActiveFormula(ICalcIterator newActiveFormula) {
    80     //String s = sendToBridge("moveActiveFormula 1 1;");
    81     //not implemented in kernel
    82     ((CalcIterator)hotSpot).moveTo((CalcIterator)newActiveFormula);	
    83   }
    84 
    85   /**
    86   Tries to replaces the active formula in the calculation tree by 
    87   the passed formula. This could fail if no valid derivation from 
    88   the preceding formula to the (new) active formula can be found. 
    89   <p>Parts of the calculation after the replaced 
    90   formula are likely to become invalid, listeners will be informed
    91   of this with the update message, which contains the last unchanged 
    92   formula.
    93   * @param newFormula
    94   * @return The method will return 0 on success or a nonzero value 
    95   indicating the status otherwise. 
    96   */
    97   public int replaceFormula(Formula newFormula) {
    98     //String s = sendToBridge("replaceFormula 1 1;");
    99     //Not implemented in kernel
   100 	informListeners((ICalcIterator)hotSpot.clone(), generateTransactionID());
   101     return 0;
   102   }
   103 
   104   /**
   105   Tries to append the passed formula after the active formula. 
   106   This could fail if no valid derivation from the preceding formula 
   107   to the (new) active formula can be found. The method will fail as 
   108   well if the active formula is not the last formula in the (sub)calculation.
   109   Parts of the calculation might become invalid.
   110   * @param newFormula
   111   * @return The method will return 0 on success or a nonzero value 
   112   indicating the status otherwise.
   113   */
   114   public int appendFormula(Formula newFormula) {
   115 	informListeners((ICalcIterator)hotSpot.clone(), generateTransactionID());
   116     return 0;
   117   }
   118 
   119   /**
   120   Set and use a tactic in the next step of calculation.   
   121   * @param tactic the Tactic to be used in the the next step
   122   * @return The return value indicates success, failure or probable
   123   success at a later time.
   124   */
   125   public int setNextTactic(Tactic tactic) {
   126     int result = -1;
   127     try {
   128       result = mathEngine.setNextTactic(this.id, tactic);
   129       if (result == 0) {
   130         hotSpot.moveDown(); // move to the new formula/calcHead
   131 		informListeners((ICalcIterator)hotSpot.clone(),generateTransactionID());
   132       }	  
   133     } catch (RemoteException e) {
   134       // TODO Auto-generated catch block
   135       e.printStackTrace();
   136     }
   137     return -1;
   138   }
   139 
   140   /**
   141   Retrieve the tactic proposed by the SML-Kernel for 
   142   the next step in the calculation.  
   143   * @return proposed tactic.
   144   * Can be null, if the kernel does
   145   * not know what to do next, or if the end 
   146   * of the calculation is reached 
   147   */
   148   public Tactic fetchProposedTactic() {
   149     try {
   150       return mathEngine.fetchProposedTactic(this.id);
   151     } catch (RemoteException e) {
   152       // TODO Auto-generated catch block
   153       e.printStackTrace();
   154     }
   155     return null;
   156   }
   157 
   158   /**
   159   Get a list of tactics applicable to the active formula. 
   160   * @param scope The filter parameter selects the scope of
   161   search for applicable tactics: all tactics / all tactics from the 
   162   current theory / all tactics from the (calculation) method being applied.
   163   * @return Array with applyable tactics
   164   */
   165   public Tactic[] fetchApplicableTactics(int scope) {
   166     Tactic[] result = null;
   167     try {
   168       result = mathEngine.fetchAppliableTactics(this.id, scope);
   169 	} catch (RemoteException e) {
   170       // TODO Auto-generated catch block
   171       e.printStackTrace();
   172     }
   173     return result;
   174   }
   175 
   176   /**
   177   Calculate the next n steps starting from the active formula.   
   178   * @param scope The scope parameter can have following values:
   179   <ul>
   180   <li> 1 .. Stay in the current subproblem
   181   <li> 2 .. Stay in the current subcalculation (e.g. repetitions) 
   182   <li> 3 .. Stay in the current calculation as a whole. 
   183   </ul>
   184   * @param nSteps Specifies the count of steps to be autocalculated. 
   185   Passing 0 for nSteps will calculate until reaching a final result. 
   186   * @return The method returns an unique id to identify the request when 
   187   notifying about updates in the tree.
   188   */
   189   public int autoCalculate(int scope, int nSteps) {
   190     boolean isOK;
   191 	int transactionID = -1;
   192     try {
   193       isOK = mathEngine.autoCalculate(this.id, scope, nSteps);
   194       if (isOK) {      
   195 		transactionID = generateTransactionID();
   196 	    informListeners((ICalcIterator)hotSpot.clone(),transactionID);
   197       }
   198     } catch (RemoteException e) {
   199       e.printStackTrace();
   200     }
   201     return transactionID;
   202   }
   203 
   204   /**
   205    * Add a Listener to this CalcTree. Listeners will be informed about any
   206    * changes in the CalcTree.
   207    * @param listener the new Listener, has to implement the interface IToUser
   208    * @return true, if the listener has been added successfully
   209    */
   210   public boolean addListener(IToUser listener) {
   211     if (listeners.contains(listener)) {
   212       return false;
   213     } else {
   214       listeners.add(listener);
   215     }
   216     return true;
   217   }
   218 
   219   /**
   220    * Retrieve the active formula in a CalcTree. This is the formula form
   221    * where the calculation will continue.
   222    * @return Iterator that marks the currently active formula
   223    */
   224   public ICalcIterator getActiveFormula() {    
   225     return (ICalcIterator)hotSpot.clone();
   226   }  
   227 
   228   /**
   229   * Destruct this CalcTree: the sml-Representation of the CalcTree
   230   * is disposed, the id can be used for a new CalcTree
   231   * @return boolean value: success of operation (complete/failed)
   232   */
   233   public boolean destruct() {
   234     try {
   235       return mathEngine.destruct(this.id);
   236     } catch (RemoteException e) {
   237       // TODO Auto-generated catch block
   238       e.printStackTrace();
   239     }
   240     return false;
   241   } 
   242   
   243   // send an update event to the registered listeners
   244   private void informListeners(ICalcIterator firstChangedFormula, int transactionID) {
   245     Iterator it = listeners.iterator();    
   246     DialogGuide dg;
   247     CalcChangedEvent e = new CalcChangedEvent(
   248     transactionID,    // transactionID 
   249     true, // completed    
   250     firstChangedFormula);
   251     while (it.hasNext()) {
   252       dg = (DialogGuide)it.next();
   253       dg.calcChanged(e);
   254     }
   255   }  
   256   
   257   MathEngine getMathEngine() {
   258     return mathEngine;
   259   }
   260 
   261   public int getId() {
   262     return id;
   263   }
   264   
   265   // Special iterator hotSpot: marks the currently active formula of
   266   // the calcTree 
   267   void setHotSpot(ICalcIterator iterator) {
   268     hotSpot = iterator;
   269   }
   270   
   271   private int generateTransactionID() {
   272 	return (int)(Math.random()*0xFFFF);
   273   }
   274 
   275 }