2 * Created on Sep 11, 2003
7 import isac.util.CalcChanged;
8 import isac.util.CalcChangedEvent;
9 import isac.util.formulae.CalcHead;
10 import isac.util.formulae.CalcFormula;
11 import isac.util.formulae.Position;
12 import isac.util.interfaces.ICalcIterator;
13 import isac.util.interfaces.IToCalc;
14 import isac.util.interfaces.IToUser;
15 import isac.util.tactics.Tactic;
16 import isac.wsdialog.DialogGuide;
18 import java.io.Serializable;
19 import java.rmi.RemoteException;
20 import java.util.Iterator;
21 import java.util.Vector;
23 import org.apache.log4j.Logger;
26 * A CalcTree represents a Calculation: It is a tree which consists of one
27 * CalcHead at the top and abitrarily many Formulas and SubCalculations (with
28 * separate CalcHeads). This is the main interface between the Bridge and the
29 * Dialog. The CalcTree calls methods of the Math Engine, which in turn are
30 * delegated to the BridgeRMI object on the other side of the RMI connection
31 * ??????WN0409. The communication with the SML Kernel is completly hided from
32 * the Dialog and the Frontend.
34 * @author Richard Gradischnegg
37 public class CalcTree implements IToCalc, Serializable {
41 private Vector listeners_;
43 private MathEngine mathEngine_;
45 private ICalcIterator hot_spot_;//WN040924 ..delete: control hotSpot --> DG
47 private IBridgeRMI bridgeRMI_;//WN040924 added for completeCalcHead & Co.
49 static Logger logger_ = Logger.getLogger(CalcTree.class.getName());
52 * Start a new calculation. In case of failure, the constructor may change
53 * the formalization object to hint at incomplete or contradictory
54 * specifications. <br>
55 * Only complete calcHeads should be passed. <br>
56 * Check every CalcHead for completeness (with the static method
57 * checkcalcHead() before constructing a CalcTree ..TODO WN040824 shift to
60 * @param identification
61 * for the CalcTree as delivered by the SML-kernel
63 CalcTree(MathEngine me, int id) {
65 this.mathEngine_ = me;
66 this.bridgeRMI_ = me.getBridgeRMI();//WN040924
67 listeners_ = new Vector();
71 * Attach another dialog to the existing calculation tree.
74 * The new Dialog to be attached to this CalcTree
76 public void attach(DialogGuide dg) {
81 * Get a new iterator referencing the root element of the calculation tree.
83 * The functionality for navigating the calculation is implemented in the
84 * CalcIterator object.
86 * @return new instance of CalcIterator
88 public ICalcIterator iterator() {
89 return new CalcIterator(this);
93 * Makes the passed formula the active formula, i.e. the formula the next
94 * tactic is applied to.
96 * @param newActiveFormula
98 public void moveActiveFormula(ICalcIterator cit) {
100 Position p = mathEngine_.moveActiveFormula(id_, cit.getPosition());
101 // if (p == null)//WN0412 message ?!
105 } catch (RemoteException e) {
106 // TODO Auto-generated catch block
112 * WN040924 copied + updated from MathEngine
114 * @see isac.util.interfaces.IToCalc#startSolving()
116 public void startSolving() throws Exception {
117 // TODO Auto-generated method stub
121 * @see isac.util.interfaces.IToCalc#startSolving(isac.util.formulae.CalcHead)
122 * WN040924 copied + updated from MathEngine
124 * public void startSolving() throws Exception {
125 * logger.warn("startSolving"); int id = calcHead.getCalcTreeID();//WN040922
126 * TODO simplify CalcHead CalcTree calcTree = (CalcTree) calcTrees.get(new
127 * Integer(id));//WN040922 TODO simplify
129 * if (calcHead.getCalcHeadStatus() != CalcHead.CALCHEAD_CORRECT) { throw
130 * new Exception("Startsolving with incorrect CalcHead"); } Tactic t =
131 * calcTree.fetchProposedTactic(); if (t.getName().compareTo("Apply_Method") !=
132 * 0) { throw new Exception("Startsolving fetches " + t.getName()); } //Next
133 * Tactic must always be Apply_Method calcTree.setNextTactic(t); //return
138 * TODO WN040924 redesign COMPLETE_PROBLEM, COMPLETE_GIVEN ... public static
139 * final int COMPLETE_METHOD = 1; public static final int COMPLETE_THEORY =
140 * 2; public static final int COMPLETE_PROBLEM = 3; public static final int
141 * COMPLETE_GIVEN = 4; public static final int COMPLETE_FIND = 5; public
142 * static final int COMPLETE_RELATE = 6; //FIXME WN040820 complete a
143 * particular model-item is not included into this design
147 * @see isac.util.interfaces.IToCalc#modifyCalcHead(isac.util.formulae.CalcHead)
149 public void modifyCalcHead(CalcHead calcHead) {
150 logger_.fatal(" DG->BR: modifyCalcHead(" + calcHead.toSMLString());
151 CalcHead newCalcHead = null;
153 //WN040924 newCalcHead = bridgeRMI.modifyCalcHead(calcHead);
154 bridgeRMI_.modifyCalcHead(calcHead);
155 //WN040924 calcHead.fillValuesfrom(newCalcHead);
156 } catch (RemoteException e) {
162 * @see isac.util.interfaces.IToCalc#completeCalcHead(isac.util.formulae.CalcHead)
164 public void completeCalcHead() {
165 logger_.fatal(" DG->BR: completeCalcHead()");
167 //WN040924 newCalcHead = bridgeRMI.completeCalcHead(calcHead);
168 bridgeRMI_.completeCalcHead(this.id_);
169 //WN040924 calcHead.fillValuesfrom(newCalcHead);
170 } catch (RemoteException e) {
176 * @see isac.util.interfaces.IToCalc#completeCalcHead(isac.util.formulae.CalcHead,
179 * eventually updated by the user
180 * @param completeItem
181 * requested by the DialogGuide
183 * WN040924 copied from MathEngine
185 public void completeCalcHead(CalcHead calcHead, int completeItem) {
186 CalcHead newCalcHead;
188 //WN040924 newCalcHead = bridgeRMI.completeCalcHead(calcHead,
190 bridgeRMI_.completeCalcHead(this.id_, calcHead, completeItem);
191 //WN040924 calcHead.fillValuesfrom(newCalcHead);
192 //TODO: Remove the following line!!
193 calcHead.setCalcHeadStatus(CalcHead.CALCHEAD_CORRECT);
195 } catch (RemoteException e) {
201 * Calculate the next n steps starting from the active formula. The Tactic
202 * to be applied in this step may be preset by setNextTactic
205 * The scope parameter can have following values:
207 * <li>Stay in the current subproblem
208 * <li>Stay in the current subcalculation (e.g. repetitions)
209 * <li>Stay in the current calculation as a whole.
211 * Constants for this scopes are found in the IToCalc class
213 * Specifies the count of steps to be autocalculated. Passing 0
214 * for nSteps will calculate until reaching a final result.
215 * @return The method returns an unique id to identify the request when
216 * notifying about updates in the tree.
218 public int autoCalculate(int scope, int nSteps) {
219 logger_.fatal(" DG->BR: autoCalculate(" + scope + ", " + nSteps + ")");
221 int transactionID = -1;
223 cc = mathEngine_.autoCalculate(this.id_, scope, nSteps);
225 hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
226 transactionID = generateTransactionID();
227 informListeners(new CalcIterator(this, cc.getLastUnchanged()),
228 new CalcIterator(this, cc.getLastDeleted()),
229 new CalcIterator(this, cc.getLastGenerated()),
232 } catch (RemoteException e) {
235 return transactionID;
239 * Tries to replaces the active formula in the calculation tree by the
240 * passed formula. This could fail if no valid derivation from the preceding
241 * formula to the (new) active formula can be found.
243 * Parts of the calculation after the replaced formula are likely to become
244 * invalid, listeners will be informed of this with the update message,
245 * which contains the last unchanged formula.
248 * @return The method will return 0 on success or a nonzero value indicating
249 * the status otherwise.
251 public int replaceFormula(CalcFormula f) throws RemoteException {
252 logger_.fatal(" DG->BR: replaceFormula(" + f.toSMLString() + ")");
254 int transactionID = -1;
256 cc = mathEngine_.replaceFormula(this.id_, f);
258 hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
259 transactionID = generateTransactionID();
260 informListeners(new CalcIterator(this, cc.getLastUnchanged()),
261 new CalcIterator(this, cc.getLastDeleted()),
262 new CalcIterator(this, cc.getLastGenerated()),
265 } catch (RemoteException e) {
272 * Tries to append the passed formula after the active formula. This could
273 * fail if no valid derivation from the preceding formula to the (new)
274 * active formula can be found. The method will fail as well if the active
275 * formula is not the last formula in the (sub)calculation. Parts of the
276 * calculation might become invalid.
279 * @return The method will return 0 on success or a nonzero value indicating
280 * the status otherwise.
282 public int appendFormula(CalcFormula f) throws RemoteException {
283 logger_.fatal(" DG->BR: appendFormula(" + f.toSMLString() + ")");
285 int transactionID = -1;
287 cc = mathEngine_.appendFormula(this.id_, f);
289 hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
290 transactionID = generateTransactionID();
291 informListeners(new CalcIterator(this, cc.getLastUnchanged()),
292 new CalcIterator(this, cc.getLastDeleted()),
293 new CalcIterator(this, cc.getLastGenerated()),
296 } catch (RemoteException e) {
303 * Set a tactic for usage by autocalculate.
306 * the Tactic to be used in the the next step
307 * @return The return value indicates success, failure or probable success
310 public int setNextTactic(Tactic tactic) {
311 logger_.fatal(" DG->BR: setNextTactic(" + tactic.toSMLString() + ")");
314 result = mathEngine_.setNextTactic(this.id_, tactic);
316 hot_spot_.moveDown(); // move to the new formula/calcHead
318 informListeners((ICalcIterator) hot_spot_.clone(),
319 // FIXXXME: nothing changed, but if outcommented: subpbl shows
320 // Add_Given etc. ... discuss with LK !
321 (ICalcIterator) hot_spot_.clone(),
322 (ICalcIterator) hot_spot_.clone(),
323 generateTransactionID());
325 } catch (RemoteException e) {
326 // TODO Auto-generated catch block
332 // public int setNextTactic(Tactic tactic) {
333 // logger_.fatal(" DG->BR: setNextTactic(" + tactic.toSMLString() + ")");
337 // result = mathEngine_.setNextTactic(this.id_, tactic);
338 // //^^^^ should be CalcChanged !
339 // if (result == 0) {
340 // //hack before @@@ autoCalculate --->
341 // // isac.wsdialog.DialogGuide#notifyUserAction
342 // //works only if nothing is deleted by use in <Next Step>
343 // it = (ICalcIterator) hot_spot_.clone();
344 // hot_spot_.moveDown();
345 // informListeners((ICalcIterator) it, it,//thus deleted nodes
346 // // are not reported !!!
347 // (ICalcIterator) hot_spot_.clone(),
348 // generateTransactionID());
350 // } catch (RemoteException e) {
351 // // TODO Auto-generated catch block
352 // e.printStackTrace();
358 * Retrieve the tactic proposed by the SML-Kernel for the next step in the
361 * @return proposed tactic. Can be null, if the kernel does not know what to
362 * do next, or if the end of the calculation is reached
364 public Tactic fetchProposedTactic() {
365 logger_.fatal(" DG->BR: fetchProposedTactic()");
367 Tactic tac = mathEngine_.fetchProposedTactic(this.id_);
368 logger_.fatal(" DG<-BR: fetchProposedTactic <- "
369 + tac.toSMLString());
371 } catch (RemoteException e) {
372 // TODO Auto-generated catch block
375 logger_.fatal(" DG<-BR: fetchProposedTactic <- NULL helpless");
380 * Get a list of tactics applicable to the active formula.
383 * The filter parameter selects the scope of search for
384 * applicable tactics: all tactics / all tactics from the current
385 * theory / all tactics from the (calculation) method being
387 * @return Array with applyable tactics
389 public Tactic[] fetchApplicableTactics(int scope) {
390 logger_.fatal(" DG->BR: fetchApplicableTactics(" + scope + ")");
391 Tactic[] result = null;
393 result = mathEngine_.fetchAppliableTactics(this.id_, scope);
394 } catch (RemoteException e) {
395 // TODO Auto-generated catch block
402 * Add a Listener to this CalcTree. Listeners will be informed about any
403 * changes in the CalcTree.
406 * the new Listener, has to implement the interface IToUser
407 * @return true, if the listener has been added successfully
409 public boolean addDataChangeListener(IToUser listener) {
410 logger_.fatal(" DG->BR: addDataChangeListener(" + listener + ")");
411 if (listeners_.contains(listener)) {
414 listeners_.add(listener);
420 * Retrieve the active formula in a CalcTree. This is the formula form where
421 * the calculation will continue.
423 * @return Iterator that marks the currently active formula
425 public ICalcIterator getActiveFormula() {
427 .fatal(" DG<>BR: getActiveFormula <- "
428 + hot_spot_.toSMLString());
429 return (ICalcIterator) hot_spot_.clone();
433 * Destruct this CalcTree: the sml-Representation of the CalcTree is
434 * disposed, the id can be used for a new CalcTree
436 * @return boolean value: success of operation (complete/failed) TODO
437 * WN040824 call mathEngine.destruct when WS is closed TODO WN040824
438 * call mathEngine.destruct when session is closed
440 public boolean destruct() {
442 return mathEngine_.destruct(this.id_);
443 } catch (RemoteException e) {
444 // TODO Auto-generated catch block
450 // send an update event to the registered listeners
451 private void informListeners(ICalcIterator lastUnchangedFormula,
452 ICalcIterator lastDeletedFormula,
453 ICalcIterator lastGeneratedFormula, int transactionID)
454 throws RemoteException {
455 logger_.fatal(" . . <-BR: informListeners (unc="
456 + lastUnchangedFormula.toSMLString() + ", del="
457 + lastDeletedFormula.toSMLString() + ", gen="
458 + lastGeneratedFormula.toSMLString());
459 Iterator listn_it = listeners_.iterator();
462 CalcChangedEvent e = new CalcChangedEvent(transactionID, true, // completed
463 lastUnchangedFormula, lastDeletedFormula, lastGeneratedFormula);
464 while (listn_it.hasNext()) {
465 dg = (IToUser) listn_it.next();
470 MathEngine getMathEngine() {
478 // Special iterator hotSpot: marks the currently active formula of
480 void setHotSpot(ICalcIterator iterator) {
481 hot_spot_ = iterator;
484 //WN0411 reminiscence to Dinopolis, drop it !?
485 //WN0501 ... _NO_: ... = return-value of autoCalculate,etc. =
486 // = CalcChangedEvent.transaction_id_
487 private int generateTransactionID() {
488 return (int) (Math.random() * 0xFFFF);
494 * @see isac.util.interfaces.IToCalc#intermediateSteps()
496 public Vector intermediateSteps(ICalcIterator i) throws RemoteException {
497 // TODO Auto-generated method stub
504 * @see isac.util.interfaces.IToCalc#getElementsFromTo(isac.util.interfaces.ICalcIterator,
505 * isac.util.interfaces.ICalcIterator, java.lang.Integer, boolean)
507 public Vector getElementsFromTo(ICalcIterator iterator_from,
508 ICalcIterator iterator_to, Integer level,
509 boolean result_includes_tactics) throws RemoteException {
510 logger_.fatal(" DG->BR: getElementsFromTo("
511 + iterator_from.toSMLString() + ", "
512 + iterator_to.toSMLString() + level + ")");
514 return mathEngine_.getElementsFromTo(this.id_, iterator_from,
515 iterator_to, level,result_includes_tactics);
516 } catch (RemoteException e) {