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