2 * Created on Sep 11, 2003
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;
14 import java.io.Serializable;
15 import java.rmi.RemoteException;
16 import java.util.Iterator;
17 import java.util.Vector;
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.
30 public class CalcTree implements IToCalc, Serializable {
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;
37 private Vector listeners;
38 private MathEngine mathEngine;
39 private ICalcIterator hotSpot;
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
50 CalcTree(MathEngine mathEngine, int id) {
52 this.mathEngine = mathEngine;
53 listeners = new Vector();
57 Attach another dialog to the existing calculation tree.
58 * @param dlg The new Dialog to be attached to this CalcTree
60 public void attach(DialogGuide dg) {
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
70 public ICalcIterator iterator() {
71 return new CalcIterator(this);
75 Makes the passed formula the active formula, i.e. the formula
76 the next tactic is applied to.
77 * @param newActiveFormula
79 public void moveActiveFormula(ICalcIterator newActiveFormula) {
80 //String s = sendToBridge("moveActiveFormula 1 1;");
81 //not implemented in kernel
82 ((CalcIterator)hotSpot).moveTo((CalcIterator)newActiveFormula);
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
94 * @return The method will return 0 on success or a nonzero value
95 indicating the status otherwise.
97 public int replaceFormula(Formula newFormula) {
98 //String s = sendToBridge("replaceFormula 1 1;");
99 //Not implemented in kernel
100 informListeners((ICalcIterator)hotSpot.clone(), generateTransactionID());
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.
111 * @return The method will return 0 on success or a nonzero value
112 indicating the status otherwise.
114 public int appendFormula(Formula newFormula) {
115 informListeners((ICalcIterator)hotSpot.clone(), generateTransactionID());
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.
125 public int setNextTactic(Tactic tactic) {
128 result = mathEngine.setNextTactic(this.id, tactic);
130 hotSpot.moveDown(); // move to the new formula/calcHead
131 informListeners((ICalcIterator)hotSpot.clone(),generateTransactionID());
133 } catch (RemoteException e) {
134 // TODO Auto-generated catch block
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
148 public Tactic fetchProposedTactic() {
150 return mathEngine.fetchProposedTactic(this.id);
151 } catch (RemoteException e) {
152 // TODO Auto-generated catch block
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
165 public Tactic[] fetchApplicableTactics(int scope) {
166 Tactic[] result = null;
168 result = mathEngine.fetchAppliableTactics(this.id, scope);
169 } catch (RemoteException e) {
170 // TODO Auto-generated catch block
177 Calculate the next n steps starting from the active formula.
178 * @param scope The scope parameter can have following values:
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.
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.
189 public int autoCalculate(int scope, int nSteps) {
191 int transactionID = -1;
193 isOK = mathEngine.autoCalculate(this.id, scope, nSteps);
195 transactionID = generateTransactionID();
196 informListeners((ICalcIterator)hotSpot.clone(),transactionID);
198 } catch (RemoteException e) {
201 return transactionID;
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
210 public boolean addListener(IToUser listener) {
211 if (listeners.contains(listener)) {
214 listeners.add(listener);
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
224 public ICalcIterator getActiveFormula() {
225 return (ICalcIterator)hotSpot.clone();
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)
233 public boolean destruct() {
235 return mathEngine.destruct(this.id);
236 } catch (RemoteException e) {
237 // TODO Auto-generated catch block
243 // send an update event to the registered listeners
244 private void informListeners(ICalcIterator firstChangedFormula, int transactionID) {
245 Iterator it = listeners.iterator();
247 CalcChangedEvent e = new CalcChangedEvent(
248 transactionID, // transactionID
250 firstChangedFormula);
251 while (it.hasNext()) {
252 dg = (DialogGuide)it.next();
257 MathEngine getMathEngine() {
265 // Special iterator hotSpot: marks the currently active formula of
267 void setHotSpot(ICalcIterator iterator) {
271 private int generateTransactionID() {
272 return (int)(Math.random()*0xFFFF);