src/java/isac/bridge/CalcTree.java
author wneuper
Fri, 29 Apr 2005 15:16:51 +0200
changeset 2265 724052025566
parent 2241 b2a210700075
child 2391 59a60ef2a2c8
permissions -rw-r--r--
java: DGuide implements IToCalc NOTANYMORE, DialogGuide cleaned from IToCalc-methods
     1 /*
     2  * Created on Sep 11, 2003
     3  * @author rgradisc
     4  */
     5 package isac.bridge;
     6 
     7 import isac.util.CalcChanged;
     8 import isac.util.CalcChangedEvent;
     9 import isac.util.StartSolvingException;
    10 import isac.util.formulae.CalcHead;
    11 import isac.util.formulae.CalcFormula;
    12 import isac.util.formulae.Position;
    13 import isac.util.interfaces.ICalcIterator;
    14 import isac.util.interfaces.IToCalc;
    15 import isac.util.interfaces.IToUser;
    16 import isac.util.tactics.Tactic;
    17 import isac.wsdialog.DialogGuide;
    18 
    19 import java.io.Serializable;
    20 import java.rmi.RemoteException;
    21 import java.util.Iterator;
    22 import java.util.Vector;
    23 
    24 import org.apache.log4j.Logger;
    25 
    26 /**
    27  * A CalcTree represents a Calculation: It is a tree which consists of one
    28  * CalcHead at the top and abitrarily many Formulas and SubCalculations (with
    29  * separate CalcHeads). This is the main interface between the Bridge and the
    30  * Dialog. The CalcTree calls methods of the Math Engine, which in turn are
    31  * delegated to the BridgeRMI object on the other side of the RMI connection
    32  * ??????WN0409. The communication with the SML Kernel is completly hided from
    33  * the Dialog and the Frontend.
    34  * 
    35  * @author Richard Gradischnegg
    36  */
    37 
    38 public class CalcTree implements IToCalc, Serializable {
    39 
    40 	private int id_;
    41 
    42 	private Vector listeners_;
    43 
    44 	private MathEngine mathEngine_;
    45 
    46 	private ICalcIterator hot_spot_;//WN040924 ..delete: control hotSpot --> DG
    47 
    48 	private IBridgeRMI bridgeRMI_;//WN040924 added for completeCalcHead & Co.
    49 
    50 	static Logger logger_ = Logger.getLogger(CalcTree.class.getName());
    51 
    52 	/**
    53 	 * Start a new calculation. In case of failure, the constructor may change
    54 	 * the formalization object to hint at incomplete or contradictory
    55 	 * specifications. <br>
    56 	 * Only complete calcHeads should be passed. <br>
    57 	 * Check every CalcHead for completeness (with the static method
    58 	 * checkcalcHead() before constructing a CalcTree ..TODO WN040824 shift to
    59 	 * authoring-tools
    60 	 * 
    61 	 * @param identification
    62 	 *            for the CalcTree as delivered by the SML-kernel
    63 	 */
    64 	CalcTree(MathEngine me, int id) {
    65 		this.id_ = id;
    66 		this.mathEngine_ = me;
    67 		this.bridgeRMI_ = me.getBridgeRMI();//WN040924
    68 		listeners_ = new Vector();
    69 	}
    70 
    71 	/**
    72 	 * Attach another dialog to the existing calculation tree.
    73 	 * 
    74 	 * @param dlg
    75 	 *            The new Dialog to be attached to this CalcTree
    76 	 */
    77 	public void attach(DialogGuide dg) {
    78 		listeners_.add(dg);
    79 	}
    80 
    81 	/**
    82 	 * Get a new iterator referencing the root element of the calculation tree.
    83 	 * <p>
    84 	 * The functionality for navigating the calculation is implemented in the
    85 	 * CalcIterator object.
    86 	 * 
    87 	 * @return new instance of CalcIterator
    88 	 */
    89 	public ICalcIterator iterator() {
    90 		return new CalcIterator(this);
    91 	}
    92 
    93 	/**
    94 	 * Makes the passed formula the active formula, i.e. the formula the next
    95 	 * tactic is applied to.
    96 	 * 
    97 	 * @param newActiveFormula
    98 	 */
    99 	public void moveActiveFormula(ICalcIterator cit) {
   100 		try {
   101 			Position p = mathEngine_.moveActiveFormula(id_, cit.getPosition());
   102 			//			if (p == null)//WN0412 message ?!
   103 			//				return false;
   104 			//			else
   105 			//				return true;
   106 		} catch (RemoteException e) {
   107 			// TODO Auto-generated catch block
   108 			e.printStackTrace();
   109 		}
   110 	}
   111 
   112 	/**
   113 	 * @see isac.util.interfaces.IToCalc#startSolving()
   114 	 */
   115 	public void startSolving() throws Exception {
   116 		Tactic tac = this.fetchProposedTactic();
   117 		if (tac.getName().compareTo("Apply_Method") == 0)
   118 			this.autoCalculate(IToCalc.SCOPE_CALCULATION, 1);
   119 		else
   120 			new StartSolvingException (tac);
   121 	}
   122 
   123 	/**
   124 	 * @see isac.util.interfaces.IToCalc#modifyCalcHead(isac.util.formulae.CalcHead)
   125 	 */
   126 	public void modifyCalcHead(CalcHead calcHead) {
   127 		logger_.fatal("  DG->BR: modifyCalcHead(" + calcHead.toSMLString());
   128 		CalcHead newCalcHead = null;
   129 		try {
   130 			//WN040924 newCalcHead = bridgeRMI.modifyCalcHead(calcHead);
   131 			bridgeRMI_.modifyCalcHead(calcHead);
   132 			//WN040924 calcHead.fillValuesfrom(newCalcHead);
   133 		} catch (RemoteException e) {
   134 			e.printStackTrace();
   135 		}
   136 	}
   137 
   138 	/**
   139 	 * @see isac.util.interfaces.IToCalc#completeCalcHead(isac.util.formulae.CalcHead)
   140 	 */
   141 	public void completeCalcHead() {
   142 		logger_.fatal("  DG->BR: completeCalcHead()");
   143 		try {
   144 			//WN040924 newCalcHead = bridgeRMI.completeCalcHead(calcHead);
   145 			bridgeRMI_.completeCalcHead(this.id_);
   146 			//WN040924 calcHead.fillValuesfrom(newCalcHead);
   147 		} catch (RemoteException e) {
   148 			e.printStackTrace();
   149 		}
   150 	}
   151 
   152 	/**
   153 	 * @see isac.util.interfaces.IToCalc#completeCalcHead(isac.util.formulae.CalcHead,
   154 	 *      int)
   155 	 * @param calcHead
   156 	 *            eventually updated by the user
   157 	 * @param completeItem
   158 	 *            requested by the DialogGuide
   159 	 * 
   160 	 * WN040924 copied from MathEngine
   161 	 * WN050429 
   162 	 */
   163 	public void completeCalcHead(CalcHead calcHead, int completeItem) {
   164 		//		CalcHead newCalcHead;
   165 		//		try {
   166 		//			//WN040924 newCalcHead = bridgeRMI.completeCalcHead(calcHead,
   167 		//			// completeItem);
   168 		//			bridgeRMI_.completeCalcHead(this.id_, calcHead, completeItem);
   169 		//			//WN040924 calcHead.fillValuesfrom(newCalcHead);
   170 		//			//TODO: Remove the following line!!
   171 		//			calcHead.setCalcHeadStatus(CalcHead.MODEL_ITEM_CORRECT);
   172 		//
   173 		//		} catch (RemoteException e) {
   174 		//			e.printStackTrace();
   175 		//		}
   176 	}
   177 
   178 	/**
   179 	 * Calculate the next n steps starting from the active formula. The Tactic
   180 	 * to be applied in this step may be preset by setNextTactic
   181 	 * 
   182 	 * @param scope
   183 	 *            The scope parameter can have following values:
   184 	 *            <ul>
   185 	 *            <li>Stay in the current subproblem
   186 	 *            <li>Stay in the current subcalculation (e.g. repetitions)
   187 	 *            <li>Stay in the current calculation as a whole.
   188 	 *            </ul>
   189 	 *            Constants for this scopes are found in the IToCalc class
   190 	 * @param nSteps
   191 	 *            Specifies the count of steps to be autocalculated. Passing 0
   192 	 *            for nSteps will calculate until reaching a final result.
   193 	 * @return The method returns an unique id to identify the request when
   194 	 *         notifying about updates in the tree.
   195 	 * 
   196 	 * WN0504 see differences to this method completely done by RG !
   197 	 */
   198 	public int autoCalculate(int scope, int nSteps) {
   199 		logger_.fatal("  DG->BR: autoCalculate(" + scope + ", " + nSteps + ")");
   200 		CalcChanged cc;
   201 		int transactionID = -1;
   202 		try {
   203 			cc = mathEngine_.autoCalculate(this.id_, scope, nSteps);
   204 			if (!(cc == null)) {
   205 				hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
   206 				transactionID = generateTransactionID();
   207 				informListeners(new CalcIterator(this, cc.getLastUnchanged()),
   208 						new CalcIterator(this, cc.getLastDeleted()),
   209 						new CalcIterator(this, cc.getLastGenerated()),
   210 						transactionID);
   211 			}
   212 		} catch (RemoteException e) {
   213 			e.printStackTrace();
   214 		}
   215 		return transactionID;
   216 	}
   217 
   218 	/**
   219 	 * Tries to replaces the active formula in the calculation tree by the
   220 	 * passed formula. This could fail if no valid derivation from the preceding
   221 	 * formula to the (new) active formula can be found.
   222 	 * <p>
   223 	 * Parts of the calculation after the replaced formula are likely to become
   224 	 * invalid, listeners will be informed of this with the update message,
   225 	 * which contains the last unchanged formula.
   226 	 * 
   227 	 * @param newFormula
   228 	 * @return The method will return 0 on success or a nonzero value indicating
   229 	 *         the status otherwise.
   230 	 */
   231 	public int replaceFormula(CalcFormula f) throws RemoteException {
   232 		logger_.fatal("  DG->BR: replaceFormula(" + f.toSMLString() + ")");
   233 		CalcChanged cc;
   234 		int transactionID = -1;
   235 		try {
   236 			cc = mathEngine_.replaceFormula(this.id_, f);
   237 			if (!(cc == null)) {
   238 				hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
   239 				transactionID = generateTransactionID();
   240 				informListeners(new CalcIterator(this, cc.getLastUnchanged()),
   241 						new CalcIterator(this, cc.getLastDeleted()),
   242 						new CalcIterator(this, cc.getLastGenerated()),
   243 						transactionID);
   244 			}
   245 		} catch (RemoteException e) {
   246 			e.printStackTrace();
   247 		}
   248 		return 0;
   249 	}
   250 
   251 	/**
   252 	 * Tries to append the passed formula after the active formula. This could
   253 	 * fail if no valid derivation from the preceding formula to the (new)
   254 	 * active formula can be found. The method will fail as well if the active
   255 	 * formula is not the last formula in the (sub)calculation. Parts of the
   256 	 * calculation might become invalid.
   257 	 * 
   258 	 * @param newFormula
   259 	 * @return The method will return 0 on success or a nonzero value indicating
   260 	 *         the status otherwise.
   261 	 */
   262 	public int appendFormula(CalcFormula f) throws RemoteException {
   263 		logger_.fatal("  DG->BR: appendFormula(" + f.toSMLString() + ")");
   264 		CalcChanged cc;
   265 		int transactionID = -1;
   266 		try {
   267 			cc = mathEngine_.appendFormula(this.id_, f);
   268 			if (!(cc == null)) {
   269 				hot_spot_ = new CalcIterator(this, cc.getLastGenerated());
   270 				transactionID = generateTransactionID();
   271 				informListeners(new CalcIterator(this, cc.getLastUnchanged()),
   272 						new CalcIterator(this, cc.getLastDeleted()),
   273 						new CalcIterator(this, cc.getLastGenerated()),
   274 						transactionID);
   275 			}
   276 		} catch (RemoteException e) {
   277 			e.printStackTrace();
   278 		}
   279 		return 0;
   280 	}
   281 
   282 	/**
   283 	 * @see isac.util.interfaces.IToCalc#intermediateSteps()
   284 	 */
   285 	public int intermediateSteps(ICalcIterator ci) throws RemoteException {
   286 		logger_.fatal("  DG->BR: intermediateSteps(" + ci.toSMLString() + ")");
   287 		CalcChanged cc;
   288 		int transactionID = -1;
   289 		try {
   290 			cc = mathEngine_.intermediateSteps(this.id_, ci);
   291 			if (!(cc == null)) {
   292 				transactionID = generateTransactionID();
   293 				informListeners(new CalcIterator(this, cc.getLastUnchanged()),
   294 						new CalcIterator(this, cc.getLastDeleted()),
   295 						new CalcIterator(this, cc.getLastGenerated()),
   296 						transactionID);
   297 			}
   298 		} catch (RemoteException e) {
   299 			e.printStackTrace();
   300 		}
   301 		return 0;
   302 	}
   303 
   304 	/**
   305 	 * Set a tactic for usage by autocalculate.
   306 	 * 
   307 	 * @param tactic
   308 	 *            the Tactic to be used in the the next step
   309 	 * @return The return value indicates success, failure or probable success
   310 	 *         at a later time.
   311 	 */
   312 	public int setNextTactic(Tactic tactic) {
   313 		logger_.fatal("  DG->BR: setNextTactic(" + tactic.toSMLString() + ")");
   314 		int result = -1;
   315 		try {
   316 			result = mathEngine_.setNextTactic(this.id_, tactic);
   317 			if (result == 0) {
   318 				hot_spot_.moveDown(); // move to the new formula/calcHead
   319 				// FIXXXME
   320 				informListeners((ICalcIterator) hot_spot_.clone(),
   321 				// FIXXXME: nothing changed, but if outcommented: subpbl shows
   322 						// Add_Given etc. ... discuss with LK !
   323 						(ICalcIterator) hot_spot_.clone(),
   324 						(ICalcIterator) hot_spot_.clone(),
   325 						generateTransactionID());
   326 			}
   327 		} catch (RemoteException e) {
   328 			// TODO Auto-generated catch block
   329 			e.printStackTrace();
   330 		}
   331 		return -1;
   332 	}
   333 
   334 	//	public int setNextTactic(Tactic tactic) {
   335 	//		logger_.fatal(" DG->BR: setNextTactic(" + tactic.toSMLString() + ")");
   336 	//		int result = -1;
   337 	//		ICalcIterator it;
   338 	//		try {
   339 	//			result = mathEngine_.setNextTactic(this.id_, tactic);
   340 	//			//^^^^ should be CalcChanged !
   341 	//			if (result == 0) {
   342 	//				//hack before @@@ autoCalculate --->
   343 	//				// isac.wsdialog.DialogGuide#notifyUserAction
   344 	//				//works only if nothing is deleted by use in <Next Step>
   345 	//				it = (ICalcIterator) hot_spot_.clone();
   346 	//				hot_spot_.moveDown();
   347 	//				informListeners((ICalcIterator) it, it,//thus deleted nodes
   348 	//													   // are not reported !!!
   349 	//						(ICalcIterator) hot_spot_.clone(),
   350 	//						generateTransactionID());
   351 	//			}
   352 	//		} catch (RemoteException e) {
   353 	//			// TODO Auto-generated catch block
   354 	//			e.printStackTrace();
   355 	//		}
   356 	//		return -1;
   357 	//	}
   358 
   359 	/**
   360 	 * Retrieve the tactic proposed by the SML-Kernel for the next step in the
   361 	 * calculation.
   362 	 * 
   363 	 * @return proposed tactic. Can be null, if the kernel does not know what to
   364 	 *         do next, or if the end of the calculation is reached
   365 	 */
   366 	public Tactic fetchProposedTactic() {
   367 		logger_.fatal("  DG->BR: fetchProposedTactic()");
   368 		try {
   369 			Tactic tac = mathEngine_.fetchProposedTactic(this.id_);
   370 			logger_.fatal("  DG<-BR: fetchProposedTactic <- "
   371 					+ tac.toSMLString());
   372 			return tac;
   373 		} catch (RemoteException e) {
   374 			// TODO Auto-generated catch block
   375 			e.printStackTrace();
   376 		}
   377 		logger_.fatal("  DG<-BR: fetchProposedTactic <- NULL helpless");
   378 		return null;
   379 	}
   380 
   381 //	/**
   382 //	 * Get a list of tactics applicable to the active formula.
   383 //	 * 
   384 //	 * @param scope
   385 //	 *            The filter parameter selects the scope of search for
   386 //	 *            applicable tactics: all tactics / all tactics from the current
   387 //	 *            theory / all tactics from the (calculation) method being
   388 //	 *            applied.
   389 //	 * @return Array with applyable tactics
   390 //	 */
   391 //	public Tactic[] fetchApplicableTactics(int scope) {
   392 //		logger_.fatal("  DG->BR: fetchApplicableTactics(" + scope + ")");
   393 //		Tactic[] result = null;
   394 //		//		try {
   395 //		//			result = mathEngine_.fetchAppliableTactics(this.id_, scope);
   396 //		//		} catch (RemoteException e) {
   397 //		//			// TODO Auto-generated catch block
   398 //		//			e.printStackTrace();
   399 //		//		}
   400 //		return result;
   401 //	}
   402 
   403 	/**
   404 	 * Add a Listener to this CalcTree. Listeners will be informed about any
   405 	 * changes in the CalcTree.
   406 	 * 
   407 	 * @param listener
   408 	 *            the new Listener, has to implement the interface IToUser
   409 	 * @return true, if the listener has been added successfully
   410 	 */
   411 	public boolean addDataChangeListener(IToUser listener) {
   412 		logger_.fatal("  DG->BR: addDataChangeListener(" + listener + ")");
   413 		if (listeners_.contains(listener)) {
   414 			return false;
   415 		} else {
   416 			listeners_.add(listener);
   417 		}
   418 		return true;
   419 	}
   420 
   421 	/**
   422 	 * Retrieve the active formula in a CalcTree. This is the formula form where
   423 	 * the calculation will continue.
   424 	 * 
   425 	 * @return Iterator that marks the currently active formula
   426 	 */
   427 	public ICalcIterator getActiveFormula() {
   428 		logger_.fatal("  DG<>BR: getActiveFormula <- "
   429 				+ hot_spot_.toSMLString());
   430 		return (ICalcIterator) hot_spot_.clone();
   431 	}
   432 
   433 	/**
   434 	 * Destruct this CalcTree: the sml-Representation of the CalcTree is
   435 	 * disposed, the id can be used for a new CalcTree
   436 	 * 
   437 	 * @return boolean value: success of operation (complete/failed) TODO
   438 	 *         WN040824 call mathEngine.destruct when WS is closed TODO WN040824
   439 	 *         call mathEngine.destruct when session is closed
   440 	 */
   441 	public boolean destruct() {
   442 		try {
   443 			return mathEngine_.destruct(this.id_);
   444 		} catch (RemoteException e) {
   445 			// TODO Auto-generated catch block
   446 			e.printStackTrace();
   447 		}
   448 		return false;
   449 	}
   450 
   451 	// send an update event to the registered listeners
   452 	private void informListeners(ICalcIterator lastUnchangedFormula,
   453 			ICalcIterator lastDeletedFormula,
   454 			ICalcIterator lastGeneratedFormula, int transactionID)
   455 			throws RemoteException {
   456 		logger_.fatal(" . . <-BR: informListeners (unc="
   457 				+ lastUnchangedFormula.toSMLString() + ", del="
   458 				+ lastDeletedFormula.toSMLString() + ", gen="
   459 				+ lastGeneratedFormula.toSMLString());
   460 		Iterator listn_it = listeners_.iterator();
   461 		//DialogGuide dg;
   462 		IToUser dg;
   463 		CalcChangedEvent e = new CalcChangedEvent(transactionID, true, // completed
   464 				lastUnchangedFormula, lastDeletedFormula, lastGeneratedFormula);
   465 		while (listn_it.hasNext()) {
   466 			dg = (IToUser) listn_it.next();
   467 			dg.calcChanged(e);
   468 		}
   469 	}
   470 
   471 	MathEngine getMathEngine() {
   472 		return mathEngine_;
   473 	}
   474 
   475 	public int getId() {
   476 		return id_;
   477 	}
   478 
   479 	// Special iterator hotSpot: marks the currently active formula of
   480 	// the calcTree
   481 	void setHotSpot(ICalcIterator iterator) {
   482 		hot_spot_ = iterator;
   483 	}
   484 
   485 	//WN0411 reminiscence to Dinopolis, drop it !?
   486 	//WN0501 ... _NO_: ... = return-value of autoCalculate,etc. =
   487 	// = CalcChangedEvent.transaction_id_
   488 	private int generateTransactionID() {
   489 		return (int) (Math.random() * 0xFFFF);
   490 	}
   491 
   492 	/*
   493 	 * (non-Javadoc)
   494 	 * 
   495 	 * @see isac.util.interfaces.IToCalc#getElementsFromTo(isac.util.interfaces.ICalcIterator,
   496 	 *      isac.util.interfaces.ICalcIterator, java.lang.Integer, boolean)
   497 	 */
   498 	public Vector getElementsFromTo(ICalcIterator iterator_from,
   499 			ICalcIterator iterator_to, Integer level,
   500 			boolean result_includes_tactics) throws RemoteException {
   501 		logger_.fatal("  DG->BR: getElementsFromTo("
   502 				+ iterator_from.toSMLString() + ", "
   503 				+ iterator_to.toSMLString() + level + ")");
   504 		try {
   505 			return mathEngine_.getElementsFromTo(this.id_, iterator_from,
   506 					iterator_to, level, result_includes_tactics);
   507 		} catch (RemoteException e) {
   508 			e.printStackTrace();
   509 		}
   510 		return null;
   511 	}
   512 
   513 }