Révision 3690
TXM/trunk/bundles/org.txm.core/src/java/org/txm/core/results/TXMResult.java (revision 3690) | ||
---|---|---|
5 | 5 |
import java.io.IOException; |
6 | 6 |
import java.lang.reflect.Constructor; |
7 | 7 |
import java.lang.reflect.Field; |
8 |
import java.lang.reflect.InvocationTargetException; |
|
8 | 9 |
import java.nio.file.Path; |
9 | 10 |
import java.text.DateFormat; |
10 | 11 |
import java.text.SimpleDateFormat; |
... | ... | |
73 | 74 |
* |
74 | 75 |
*/ |
75 | 76 |
public abstract class TXMResult implements Cloneable, Comparable<TXMResult> { |
76 |
|
|
77 |
|
|
77 | 78 |
public static final DateFormat ID_TIME_FORMAT = new SimpleDateFormat("yyyyMMdd_HHmmssSSS"); //$NON-NLS-1$ |
78 |
|
|
79 |
|
|
79 | 80 |
public static final DateFormat PRETTY_TIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); //$NON-NLS-1$ |
80 |
|
|
81 |
|
|
81 | 82 |
public static final DateFormat PRETTY_LOCALIZED_TIME_FORMAT = new SimpleDateFormat("dd MMMM yyyy, HH'h'mm", Locale.getDefault()); //$NON-NLS-1$ |
82 |
|
|
83 |
|
|
83 | 84 |
public static final String UUID_PREFIX = "txm_res_"; //$NON-NLS-1$ |
84 |
|
|
85 |
|
|
85 | 86 |
public static final Pattern FILE_NAME_PATTERN = Pattern.compile("[^a-zA-Z0-9\\.-_]+"); //$NON-NLS-1$ |
86 |
|
|
87 |
|
|
87 | 88 |
public static final String UNDERSCORE = "_"; //$NON-NLS-1$ |
88 |
|
|
89 |
|
|
89 | 90 |
/** |
90 | 91 |
* Results counter to create unique ids. |
91 | 92 |
*/ |
92 | 93 |
private static int next = 0; |
93 |
|
|
94 |
|
|
94 | 95 |
/** |
95 | 96 |
* The weight, essentially used for sorting purpose. |
96 | 97 |
*/ |
97 | 98 |
protected int weight; |
98 |
|
|
99 |
|
|
99 | 100 |
/** |
100 | 101 |
* the command this command to true when the result needs to be recomputed. |
101 | 102 |
* like after updating parameters |
102 | 103 |
*/ |
103 | 104 |
private boolean dirty = true; |
104 |
|
|
105 |
|
|
105 | 106 |
/** |
106 | 107 |
* If a method changed the internal data without **recomputing** the result, the result must be marked "altered" |
107 | 108 |
*/ |
108 | 109 |
private boolean altered = false; |
109 |
|
|
110 |
|
|
110 | 111 |
/** |
111 | 112 |
* The result parent. Should not be null except for roots TXMResult. |
112 | 113 |
*/ |
113 | 114 |
protected TXMResult parent; |
114 |
|
|
115 |
|
|
115 | 116 |
/** |
116 | 117 |
* Children results. |
117 | 118 |
*/ |
118 | 119 |
protected List<TXMResult> children; |
119 |
|
|
120 |
|
|
120 | 121 |
/** |
121 | 122 |
* Command preferences node path. |
122 | 123 |
*/ |
123 | 124 |
protected String commandPreferencesNodePath; |
124 |
|
|
125 |
|
|
125 | 126 |
/** |
126 | 127 |
* Parameters node path. Concatenation of the Project scope path + the result uuid |
127 | 128 |
*/ |
128 | 129 |
private String parametersNodePath; |
129 |
|
|
130 |
|
|
130 | 131 |
/** |
131 | 132 |
* Thread used when calling compute(). |
132 | 133 |
*/ |
133 | 134 |
protected Thread computingThread; |
134 |
|
|
135 |
|
|
135 | 136 |
/** |
136 | 137 |
* To manage the computing cancel with TreadDeath. |
137 | 138 |
*/ |
138 | 139 |
// FIXME: SJ: became useless? |
139 | 140 |
private Semaphore progressSemaphore = new Semaphore(1); |
140 |
|
|
141 |
|
|
141 | 142 |
/** |
142 | 143 |
* To keep track of the parameters used for the last computing and to determine if the result is dirty. |
143 | 144 |
* Also permits to optimize computing by testing if a specific parameter value has changed since last computing and skip or not some computing steps. |
144 | 145 |
*/ |
145 | 146 |
protected ArrayList<HashMap<String, Object>> parametersHistory = null; |
146 |
|
|
147 |
|
|
147 | 148 |
/** |
148 | 149 |
* User persistable state. |
149 | 150 |
*/ |
150 | 151 |
@Parameter(key = TXMPreferences.PERSITABLE, type = Parameter.INTERNAL) |
151 | 152 |
private boolean userPersistable; |
152 |
|
|
153 |
|
|
153 | 154 |
/** |
154 | 155 |
* The visibility state. |
155 | 156 |
*/ |
156 | 157 |
@Parameter(key = TXMPreferences.VISIBLE, type = Parameter.INTERNAL) |
157 | 158 |
private Boolean visible; |
158 |
|
|
159 |
|
|
159 | 160 |
/** |
160 | 161 |
* The user name (to rename a result). |
161 | 162 |
*/ |
162 | 163 |
@Parameter(key = TXMPreferences.USER_NAME, type = Parameter.INTERNAL) |
163 | 164 |
private String userName; |
164 |
|
|
165 |
|
|
165 | 166 |
/** |
166 | 167 |
* To store the simple name for unserialization and lazy loading. |
167 | 168 |
* This string can be used, for example, to display some information in UI even if the result has not yet been recomputed. |
... | ... | |
169 | 170 |
// TODO: SJ: we should do the same with getDetails() method |
170 | 171 |
@Parameter(key = TXMPreferences.LAZY_NAME, type = Parameter.INTERNAL) |
171 | 172 |
private String lazyName; |
172 |
|
|
173 |
|
|
173 | 174 |
/** |
174 | 175 |
* Last computing date. |
175 | 176 |
*/ |
176 | 177 |
@Parameter(key = TXMPreferences.LAST_COMPUTING_DATE, type = Parameter.INTERNAL) |
177 | 178 |
private Date lastComputingDate; |
178 |
|
|
179 |
|
|
179 | 180 |
/** |
180 | 181 |
* Creation date. |
181 | 182 |
*/ |
182 | 183 |
@Parameter(key = TXMPreferences.CREATION_DATE, type = Parameter.INTERNAL) |
183 | 184 |
private Date creationDate; |
184 |
|
|
185 |
|
|
185 | 186 |
/** |
186 | 187 |
* If locked, the result is not updated when computed. |
187 | 188 |
*/ |
188 | 189 |
@Parameter(key = TXMPreferences.LOCK, type = Parameter.INTERNAL) |
189 | 190 |
private Boolean locked = false; |
190 |
|
|
191 |
|
|
191 | 192 |
/** |
192 | 193 |
* Current computing state. |
193 | 194 |
* True if the result is in the process of computing (is in compute(,) method) |
194 | 195 |
*/ |
195 | 196 |
private boolean computing = false; |
196 |
|
|
197 |
|
|
197 | 198 |
/** |
198 | 199 |
* Synchronization state between this result and its parent. |
199 | 200 |
* If true, computing the parent will always also computes this child. |
200 | 201 |
*/ |
201 | 202 |
protected boolean synchronizedWithParent = false; |
202 |
|
|
203 |
|
|
203 |
|
|
204 |
|
|
204 | 205 |
/** |
205 | 206 |
* Creates a new TXMResult, child of the specified parent. |
206 | 207 |
* |
... | ... | |
209 | 210 |
public TXMResult(TXMResult parent) { |
210 | 211 |
this(null, parent); |
211 | 212 |
} |
212 |
|
|
213 |
|
|
213 | 214 |
/** |
214 | 215 |
* Creates a new TXMResult with no parent. |
215 | 216 |
* If a local preference node exists with parent_parameters_node_path value, the parent will be retrieved and this result will be added to it. |
... | ... | |
219 | 220 |
public TXMResult(String parametersNodePath) { |
220 | 221 |
this(parametersNodePath, null); |
221 | 222 |
} |
222 |
|
|
223 |
|
|
223 | 224 |
/** |
224 | 225 |
* Creates a new TXMResult, child of the specified parent. |
225 | 226 |
* If the parameters node path is null, a new path is generated from the project root path ending by a new generated UUID. |
... | ... | |
234 | 235 |
if (parent != null) { |
235 | 236 |
parent.addChild(this); |
236 | 237 |
} |
237 |
|
|
238 |
|
|
238 | 239 |
// new result |
239 | 240 |
if (parametersNodePath == null) { |
240 | 241 |
if (this.getProject() != null) { |
... | ... | |
243 | 244 |
else { |
244 | 245 |
parametersNodePath = ""; //$NON-NLS-1$ |
245 | 246 |
} |
246 |
|
|
247 |
|
|
247 | 248 |
this.parametersNodePath = parametersNodePath + createUUID() + "_" + this.getClass().getSimpleName(); //$NON-NLS-1$ ; |
248 | 249 |
} |
249 | 250 |
// lazy result (persistence / import) or linked result ("send to" commands) |
250 | 251 |
else { |
251 | 252 |
this.parametersNodePath = parametersNodePath; |
252 | 253 |
} |
253 |
|
|
254 |
|
|
254 | 255 |
Log.finest("TXMResult.TXMResult(): parameters node path: " + this.parametersNodePath + "."); //$NON-NLS-1$ //$NON-NLS-2$ |
255 |
|
|
256 |
|
|
256 | 257 |
this.weight = 0; |
257 |
|
|
258 |
|
|
258 | 259 |
this.children = new ArrayList<>(1); |
259 | 260 |
// this.children = Collections.synchronizedList(new ArrayList<TXMResult>()); // FIXME: SJ: can fix the concurrent exception if needed when accessing children from multiple threads |
260 |
|
|
261 |
|
|
261 | 262 |
this.commandPreferencesNodePath = FrameworkUtil.getBundle(getClass()).getSymbolicName(); |
262 | 263 |
Log.finest("TXMResult.TXMResult(): command preferences node path: " + this.commandPreferencesNodePath + "."); //$NON-NLS-1$ //$NON-NLS-2$ |
263 |
|
|
264 |
|
|
264 | 265 |
this.visible = true; |
265 | 266 |
this.dirty = true; |
266 |
|
|
267 |
|
|
267 | 268 |
// set result as persistent if AUTO_PERSISTENCE_ENABLED preference is activated |
268 | 269 |
if (TBXPreferences.getInstance().getBoolean(TBXPreferences.AUTO_PERSISTENCE_ENABLED)) { |
269 | 270 |
this.saveParameter(TXMPreferences.PERSITABLE, true); |
270 | 271 |
} |
271 |
|
|
272 |
|
|
272 | 273 |
// retrieving parent from UUID/node path |
273 | 274 |
String parentNodePath = this.getStringParameterValue(TXMPreferences.PARENT_PARAMETERS_NODE_PATH); |
274 |
|
|
275 |
|
|
275 | 276 |
// System.out.println("TXMResult.TXMResult(): parent UUID = " + parentUUID); |
276 |
|
|
277 |
// search for parent only if UUID != "ROOT"
|
|
277 |
|
|
278 |
// search for parent only if UUID != "ROOT" |
|
278 | 279 |
if (!("ROOT".equals(this.parametersNodePath)) && //$NON-NLS-1$ |
279 | 280 |
parent == null && |
280 | 281 |
this.parametersNodePath != null && |
281 | 282 |
!parentNodePath.isEmpty()) { |
282 |
|
|
283 |
|
|
283 | 284 |
Log.finest("Searching parent with UUID/node path " + parentNodePath + "..."); //$NON-NLS-1$ //$NON-NLS-2$ |
284 |
|
|
285 |
|
|
285 | 286 |
TXMResult retrievedParent = null; |
286 | 287 |
if (this.getProject() != null) { |
287 | 288 |
retrievedParent = TXMResult.getResult(this.getProject(), parentNodePath); // works only if parent and child are in the same project (which should be). |
... | ... | |
301 | 302 |
TBXPreferences.delete(this); |
302 | 303 |
} |
303 | 304 |
catch (Exception e) { |
304 |
|
|
305 |
|
|
305 | 306 |
} |
306 | 307 |
return; |
307 | 308 |
} |
308 | 309 |
} |
309 |
|
|
310 |
|
|
310 | 311 |
// loads parameters from local result node, current command preferences or default command preferences |
311 | 312 |
try { |
312 | 313 |
this.autoLoadParametersFromAnnotations(); // auto fill from Parameter annotations |
313 | 314 |
this.loadParameters(); // subclasses manual settings |
314 |
|
|
315 |
|
|
315 | 316 |
try { |
316 | 317 |
if (this.creationDate == null) { |
317 | 318 |
this.creationDate = Calendar.getInstance().getTime(); |
... | ... | |
327 | 328 |
Log.severe("Fail to load the " + parametersNodePath + " result: " + e); //$NON-NLS-1$ //$NON-NLS-2$ |
328 | 329 |
Log.printStackTrace(e); |
329 | 330 |
} |
330 |
|
|
331 |
|
|
331 | 332 |
// Log |
332 | 333 |
if (this.parent == null) { |
333 | 334 |
Log.finest("Warning: the TXMResult of " + this.getClass() + " is attached to no parent. (uuid = " + this.parametersNodePath + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-1$ |
334 | 335 |
} |
335 | 336 |
} |
336 |
|
|
337 |
|
|
337 | 338 |
/** |
338 | 339 |
* Sets the user name. |
339 | 340 |
* |
... | ... | |
342 | 343 |
public void setUserName(String name) { |
343 | 344 |
this.userName = name; |
344 | 345 |
} |
345 |
|
|
346 |
|
|
346 | 347 |
/** |
347 | 348 |
* @return true if the internal data has been modified |
348 | 349 |
*/ |
349 | 350 |
public boolean isAltered() { |
350 | 351 |
return altered; |
351 | 352 |
} |
352 |
|
|
353 |
|
|
353 | 354 |
/** |
354 | 355 |
* Mark the result as altered -> modifications are lost after a re-compute |
355 | 356 |
*/ |
356 | 357 |
public void setAltered() { |
357 | 358 |
this.altered = true; |
358 | 359 |
} |
359 |
|
|
360 |
|
|
360 | 361 |
/** |
361 | 362 |
* Do something when project is closed |
362 | 363 |
*/ |
363 | 364 |
public void onProjectClose() { |
364 |
|
|
365 |
|
|
365 | 366 |
} |
366 |
|
|
367 |
|
|
367 | 368 |
/** |
368 | 369 |
* Do something when project is opened |
369 | 370 |
*/ |
370 | 371 |
public void onProjectOpen() { |
371 |
|
|
372 |
|
|
372 | 373 |
} |
373 |
|
|
374 |
|
|
374 | 375 |
/** |
375 | 376 |
* Locks/unlocks the result. |
376 | 377 |
*/ |
377 | 378 |
public void setLocked(boolean state) { |
378 | 379 |
this.locked = state; |
379 |
|
|
380 |
|
|
380 | 381 |
if (this.locked && this.parent != null) { |
381 | 382 |
this.parent.setLocked(true); |
382 | 383 |
} |
... | ... | |
386 | 387 |
} |
387 | 388 |
} |
388 | 389 |
} |
389 |
|
|
390 |
|
|
390 | 391 |
/** |
391 | 392 |
* @return true if the result is locked |
392 | 393 |
*/ |
393 | 394 |
public boolean isLocked() { |
394 | 395 |
return this.locked; |
395 | 396 |
} |
396 |
|
|
397 |
|
|
397 | 398 |
/** |
398 | 399 |
* Creates an UUID dedicated to preferences/parameters storing and to persistence of a result. |
399 | 400 |
* |
... | ... | |
402 | 403 |
public static String createUUID() { |
403 | 404 |
return UUID_PREFIX + ID_TIME_FORMAT.format(new Date(System.currentTimeMillis())) + "_" + nextInt(); |
404 | 405 |
} |
405 |
|
|
406 |
|
|
406 | 407 |
/** |
407 | 408 |
* |
408 | 409 |
* @return the next integer in the current session of TXM |
... | ... | |
410 | 411 |
private static synchronized String nextInt() { |
411 | 412 |
return String.format("%04d", next++); //$NON-NLS-1$ |
412 | 413 |
} |
413 |
|
|
414 |
|
|
414 | 415 |
/** |
415 | 416 |
* Checks if the result has at least one child. |
416 | 417 |
* |
... | ... | |
419 | 420 |
public boolean hasChildren() { |
420 | 421 |
return this.children.size() > 0; |
421 | 422 |
} |
422 |
|
|
423 |
|
|
423 |
|
|
424 |
|
|
424 | 425 |
/** |
425 | 426 |
* Gets the preferences node path of the result linked command. |
426 | 427 |
* |
... | ... | |
429 | 430 |
public String getCommandPreferencesNodePath() { |
430 | 431 |
return this.commandPreferencesNodePath; |
431 | 432 |
} |
432 |
|
|
433 |
|
|
433 |
|
|
434 |
|
|
434 | 435 |
public String[] getCommandPreferencesKeys() throws BackingStoreException { |
435 | 436 |
return TXMPreferences.getCommandScopeKeys(this.commandPreferencesNodePath); |
436 | 437 |
} |
437 |
|
|
438 |
|
|
438 | 439 |
public String[] getDefaultPreferencesKeys() throws BackingStoreException { |
439 | 440 |
return TXMPreferences.getDefaultScopeKeys(this.commandPreferencesNodePath); |
440 | 441 |
} |
441 |
|
|
442 |
|
|
442 | 443 |
/** |
443 | 444 |
* Gets a current parameter specified by its annotation "key". |
444 | 445 |
* |
... | ... | |
449 | 450 |
public Object getParameter(String key) { |
450 | 451 |
return getParameter(key, false); |
451 | 452 |
} |
452 |
|
|
453 |
|
|
453 | 454 |
/** |
454 | 455 |
* Gets a current parameter specified by its annotation "key". |
455 | 456 |
* |
... | ... | |
474 | 475 |
} |
475 | 476 |
return null; |
476 | 477 |
} |
477 |
|
|
478 |
|
|
478 | 479 |
/** |
479 | 480 |
* Stores the parameters of the specified types used during last computing in the specified HashMap. |
480 | 481 |
* |
... | ... | |
483 | 484 |
* @throws Exception |
484 | 485 |
*/ |
485 | 486 |
protected void updateLastParameters(ArrayList<Integer> parametersTypes, HashMap<String, Object> lastParameters) throws Exception { |
486 |
|
|
487 |
|
|
487 | 488 |
List<Field> fields = BeanParameters.getAllFields(this); |
488 |
|
|
489 |
|
|
489 | 490 |
for (Field f : fields) { |
490 | 491 |
Parameter parameter = f.getAnnotation(Parameter.class); |
491 | 492 |
if (parameter == null || !parametersTypes.contains(parameter.type())) { |
492 | 493 |
continue; |
493 | 494 |
} |
494 |
|
|
495 |
|
|
495 | 496 |
String name; |
496 | 497 |
if (!parameter.key().isEmpty()) { |
497 | 498 |
name = parameter.key(); |
... | ... | |
499 | 500 |
else { |
500 | 501 |
name = f.getName(); |
501 | 502 |
} |
502 |
|
|
503 |
|
|
503 | 504 |
f.setAccessible(true); |
504 | 505 |
lastParameters.put(name, f.get(this)); |
505 | 506 |
} |
506 |
|
|
507 |
|
|
507 | 508 |
// if (lastParameters.isEmpty()) { |
508 | 509 |
// System.out.println("TXMResult.updateLastParameters() empty"); |
509 | 510 |
// } |
510 |
|
|
511 |
|
|
511 | 512 |
if (this.parametersHistory == null) { // |
512 | 513 |
this.parametersHistory = new ArrayList<HashMap<String,Object>>(); |
513 | 514 |
} |
514 | 515 |
this.parametersHistory.add(lastParameters); |
515 |
|
|
516 |
|
|
516 | 517 |
// truncate the stack to the max count |
517 | 518 |
// FIXME: SJ: later, store this in a TBX preference |
518 | 519 |
if (this.parametersHistory.size() > 5) { |
... | ... | |
521 | 522 |
this.parametersHistory.remove(0); |
522 | 523 |
} |
523 | 524 |
} |
524 |
|
|
525 |
|
|
525 | 526 |
/** |
526 | 527 |
* Stores the last parameters of the specified types used during last computing. |
527 | 528 |
* |
... | ... | |
531 | 532 |
protected void updateLastParameters(ArrayList<Integer> parametersTypes) throws Exception { |
532 | 533 |
this.updateLastParameters(parametersTypes, new HashMap<>()); |
533 | 534 |
} |
534 |
|
|
535 |
|
|
535 | 536 |
/** |
536 | 537 |
* Stores the last parameters used during last computing. |
537 | 538 |
* |
... | ... | |
542 | 543 |
parametersTypes.add(Parameter.COMPUTING); |
543 | 544 |
this.updateLastParameters(parametersTypes); |
544 | 545 |
} |
545 |
|
|
546 |
|
|
546 |
|
|
547 |
|
|
547 | 548 |
/** |
548 | 549 |
* Removes all the parameters of the specified type from the last parameters history. |
549 | 550 |
* |
... | ... | |
551 | 552 |
* @throws Exception |
552 | 553 |
*/ |
553 | 554 |
protected void clearLastParameters(int parameterType) { |
554 |
|
|
555 |
|
|
555 | 556 |
if (parametersHistory == null) return; // nothing to do |
556 |
|
|
557 |
|
|
557 | 558 |
List<Field> fields = BeanParameters.getAllFields(this); |
558 |
|
|
559 |
|
|
559 | 560 |
for (Field f : fields) { |
560 | 561 |
Parameter parameter = f.getAnnotation(Parameter.class); |
561 | 562 |
if (parameter == null || parameter.type() != parameterType) { |
562 | 563 |
continue; |
563 | 564 |
} |
564 |
|
|
565 |
|
|
565 | 566 |
String name; |
566 | 567 |
if (!parameter.key().isEmpty()) { |
567 | 568 |
name = parameter.key(); |
... | ... | |
569 | 570 |
else { |
570 | 571 |
name = f.getName(); |
571 | 572 |
} |
572 |
|
|
573 |
|
|
573 | 574 |
f.setAccessible(true); |
574 | 575 |
try { |
575 | 576 |
this.getLastParametersFromHistory().remove(name); |
... | ... | |
578 | 579 |
// nothing to do if the stack is empty |
579 | 580 |
} |
580 | 581 |
} |
581 |
|
|
582 |
|
|
582 |
|
|
583 |
|
|
583 | 584 |
try { |
584 | 585 |
if (this.parametersHistory != null && !this.getLastParametersFromHistory().isEmpty()) { |
585 | 586 |
this.parametersHistory.remove(this.parametersHistory.size() - 1); |
... | ... | |
589 | 590 |
// nothing to do if the stack is empty |
590 | 591 |
} |
591 | 592 |
} |
592 |
|
|
593 |
|
|
593 |
|
|
594 |
|
|
594 | 595 |
/** |
595 | 596 |
* Checks if a parameter value has changed since last computing. |
596 | 597 |
* |
... | ... | |
599 | 600 |
* @return |
600 | 601 |
*/ |
601 | 602 |
public boolean hasParameterChanged(String key) { |
602 |
|
|
603 |
|
|
603 | 604 |
if (parametersHistory == null) return true; |
604 |
|
|
605 |
|
|
605 | 606 |
return this.hasParameterChanged(key, this.getLastParametersFromHistory()); |
606 | 607 |
} |
607 |
|
|
608 |
|
|
608 | 609 |
/** |
609 | 610 |
* Checks if a parameter value has changed since last computing according to the specified external map. |
610 | 611 |
* |
... | ... | |
613 | 614 |
* @return |
614 | 615 |
*/ |
615 | 616 |
public boolean hasParameterChanged(String key, HashMap<String, Object> lastParameters) { |
616 |
|
|
617 |
|
|
617 | 618 |
if (lastParameters == null) { |
618 | 619 |
return true; |
619 | 620 |
} |
620 |
|
|
621 |
|
|
621 | 622 |
if (key.isEmpty()) { |
622 | 623 |
return false; |
623 | 624 |
} |
624 |
|
|
625 |
|
|
625 | 626 |
Object lastValue = lastParameters.get(key); |
626 | 627 |
Object newValue = this.getParameter(key, true); |
627 | 628 |
if (lastValue == null) { |
... | ... | |
636 | 637 |
return !lastValue.equals(newValue); |
637 | 638 |
} |
638 | 639 |
} |
639 |
|
|
640 |
|
|
640 | 641 |
/** |
641 | 642 |
* Checks if at least one parameter value of the specified parameter type has changed since last computing according to the specified external map. |
642 | 643 |
* |
... | ... | |
645 | 646 |
* @return |
646 | 647 |
*/ |
647 | 648 |
public boolean hasParametersChanged(HashMap<String, Object> lastParameters, int parameterType) throws Exception { |
648 |
|
|
649 |
|
|
649 | 650 |
// result has never been computed |
650 | 651 |
if (lastParameters == null) { |
651 | 652 |
return true; |
652 | 653 |
} |
653 |
|
|
654 |
|
|
654 | 655 |
boolean hasParameterChanged = false; |
655 |
|
|
656 |
|
|
656 | 657 |
List<Field> fields = BeanParameters.getAllFields(this); |
657 |
|
|
658 |
|
|
658 | 659 |
for (Field f : fields) { |
659 | 660 |
Parameter parameter = f.getAnnotation(Parameter.class); |
660 | 661 |
if (parameter == null || parameter.type() != parameterType) { |
... | ... | |
667 | 668 |
else { |
668 | 669 |
name = f.getName(); |
669 | 670 |
} |
670 |
|
|
671 |
|
|
671 | 672 |
f.setAccessible(true); // to be able to test the field values |
672 |
|
|
673 |
|
|
673 | 674 |
hasParameterChanged = this.hasParameterChanged(name, lastParameters); |
674 |
|
|
675 |
|
|
675 | 676 |
if (hasParameterChanged) { |
676 | 677 |
Log.finest("TXMResult.hasParameterChanged(): " + this.getClass().getSimpleName() + ": parameter " + name + " has changed (type = " + parameterType + ")."); |
677 | 678 |
break; |
678 | 679 |
} |
679 | 680 |
} |
680 |
|
|
681 |
|
|
681 | 682 |
return hasParameterChanged; |
682 | 683 |
} |
683 |
|
|
684 |
|
|
684 |
|
|
685 |
|
|
685 | 686 |
/** |
686 | 687 |
* Checks if at least one computing parameter value has changed since last computing. |
687 | 688 |
* |
... | ... | |
690 | 691 |
*/ |
691 | 692 |
public boolean hasParametersChanged() throws Exception { |
692 | 693 |
if (parametersHistory == null) return true; |
693 |
|
|
694 |
|
|
694 | 695 |
return this.hasParametersChanged(this.getLastParametersFromHistory(), Parameter.COMPUTING); |
695 | 696 |
} |
696 |
|
|
697 |
|
|
697 |
|
|
698 |
|
|
698 | 699 |
/** |
699 | 700 |
* Dumps the result current parameters, the command user preferences and the command default preferences linked to the result. |
700 | 701 |
* |
701 | 702 |
* @return |
702 | 703 |
*/ |
703 | 704 |
public String dumpPreferences() { |
704 |
|
|
705 |
|
|
705 | 706 |
StringBuilder str = new StringBuilder(); |
706 |
|
|
707 |
|
|
707 | 708 |
if (TXMPreferences.resultScopeNodeExists(this)) { |
708 | 709 |
str.append("\nResult local node preferences\n"); //$NON-NLS-1$ |
709 | 710 |
str.append(TXMPreferences.getKeysAndValues(this.getParametersNodePath())); |
710 | 711 |
} |
711 |
|
|
712 |
|
|
712 | 713 |
str.append("\nCommand preferences\n"); //$NON-NLS-1$ |
713 | 714 |
str.append(TXMPreferences.getKeysAndValues(this.commandPreferencesNodePath)); |
714 |
|
|
715 |
|
|
715 | 716 |
str.append("\nDefault command preferences\n"); //$NON-NLS-1$ |
716 | 717 |
str.append(TXMPreferences.getKeysAndValues(DefaultScope.INSTANCE + "/" + this.commandPreferencesNodePath)); |
717 |
|
|
718 |
|
|
718 | 719 |
return str.toString(); |
719 | 720 |
} |
720 |
|
|
721 |
|
|
721 |
|
|
722 |
|
|
722 | 723 |
/** |
723 | 724 |
* Dumps the result computing parameters (Parameter annotation). |
724 | 725 |
* |
... | ... | |
727 | 728 |
public String dumpParameters() { |
728 | 729 |
return this.dumpParameters(Parameter.COMPUTING); |
729 | 730 |
} |
730 |
|
|
731 |
|
|
731 |
|
|
732 |
|
|
732 | 733 |
/** |
733 | 734 |
* Dumps the result computing parameters (Parameter annotation). |
734 | 735 |
* |
... | ... | |
736 | 737 |
* @return |
737 | 738 |
*/ |
738 | 739 |
public String dumpParameters(int parametersType) { |
739 |
|
|
740 |
|
|
740 | 741 |
StringBuilder str = new StringBuilder(); |
741 |
|
|
742 |
|
|
742 | 743 |
str.append("Parameters (type = " + parametersType + " / " + Parameter.types[parametersType] + ")\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
743 |
|
|
744 |
|
|
744 | 745 |
List<Field> fields = BeanParameters.getAllFields(this); |
745 |
|
|
746 |
|
|
746 | 747 |
for (Field f : fields) { |
747 | 748 |
Parameter parameter = f.getAnnotation(Parameter.class); |
748 | 749 |
if (parameter == null || parameter.type() != parametersType) { |
749 | 750 |
continue; |
750 | 751 |
} |
751 | 752 |
f.setAccessible(true); |
752 |
|
|
753 |
|
|
753 | 754 |
String name; |
754 | 755 |
if (!parameter.key().isEmpty()) { |
755 | 756 |
name = parameter.key(); |
... | ... | |
757 | 758 |
else { |
758 | 759 |
name = f.getName(); |
759 | 760 |
} |
760 |
|
|
761 |
|
|
761 | 762 |
try { |
762 | 763 |
Object v = f.get(this); |
763 | 764 |
if (v != null) { |
... | ... | |
778 | 779 |
} |
779 | 780 |
return str.toString(); |
780 | 781 |
} |
781 |
|
|
782 |
|
|
783 |
|
|
782 |
|
|
783 |
|
|
784 |
|
|
784 | 785 |
// /** |
785 | 786 |
// * Updates the dirty state by comparing an old parameter with a new one. |
786 | 787 |
// * |
... | ... | |
796 | 797 |
// this.setDirty(); |
797 | 798 |
// } |
798 | 799 |
// } |
799 |
|
|
800 |
|
|
800 | 801 |
/** |
801 | 802 |
* Sets the dirty state to true if a parameter has changed since last computing. |
802 | 803 |
* |
... | ... | |
857 | 858 |
// else { |
858 | 859 |
// return this.hasParameterChanged(); |
859 | 860 |
// } |
860 |
|
|
861 |
|
|
861 | 862 |
if (this.hasParametersChanged()) { |
862 | 863 |
this.dirty = true; |
863 | 864 |
} |
864 | 865 |
} |
865 |
|
|
866 |
|
|
866 | 867 |
/** |
867 | 868 |
* Gets the list of parameters used during last computing or null if the result has not been computed yet. |
868 | 869 |
* |
... | ... | |
877 | 878 |
return null; |
878 | 879 |
} |
879 | 880 |
} |
880 |
|
|
881 |
|
|
881 | 882 |
/** |
882 | 883 |
* TODO seems to work but the TXMEditor.compute() method re-use the widgets values and the parametersHistory is appended with the 'new' parameters |
883 | 884 |
* |
... | ... | |
886 | 887 |
public void revertParametersFromHistory() throws Exception { |
887 | 888 |
ArrayList<HashMap<String, Object>> history = getParametersHistory(); |
888 | 889 |
if (history == null) return; // nothing to do |
889 |
|
|
890 |
|
|
890 | 891 |
if (history.size() < 2) return; // nothing to do |
891 |
|
|
892 |
|
|
892 | 893 |
history.remove(history.size() - 1); |
893 |
|
|
894 |
|
|
894 | 895 |
HashMap<String, Object> last = history.get(history.size() - 1); |
895 |
|
|
896 |
|
|
896 | 897 |
this.setParameters(last); // auto |
897 | 898 |
} |
898 |
|
|
899 |
|
|
899 |
|
|
900 |
|
|
900 | 901 |
/** |
901 | 902 |
* Dumps the parameters history stack to the specified StringBuffer. |
902 | 903 |
* |
... | ... | |
914 | 915 |
} |
915 | 916 |
} |
916 | 917 |
} |
917 |
|
|
918 |
|
|
918 |
|
|
919 |
|
|
919 | 920 |
/** |
920 | 921 |
* Gets the dirty state. |
921 | 922 |
* |
... | ... | |
924 | 925 |
public boolean isDirty() { |
925 | 926 |
return this.dirty; |
926 | 927 |
} |
927 |
|
|
928 |
|
|
928 | 929 |
/** |
929 | 930 |
* Marks the result as dirty so editors or others will know the TXMResult needs to be recomputed. |
930 | 931 |
* This method is also recursively called on all the children branch to mark them as dirty. |
... | ... | |
932 | 933 |
public void setDirty() { |
933 | 934 |
this.setDirty(true); |
934 | 935 |
} |
935 |
|
|
936 |
|
|
936 | 937 |
/** |
937 | 938 |
* Sets the result dirty state so editors or others will know the TXMResult needs to be recomputed or not. |
938 | 939 |
* This method is also recursively called on all the children branch sets the new dirty state. |
... | ... | |
947 | 948 |
} |
948 | 949 |
} |
949 | 950 |
} |
950 |
|
|
951 |
|
|
951 | 952 |
/** |
952 | 953 |
* Gets the value of the specified key in parameters, local result node or |
953 | 954 |
* default preferences nodes. |
... | ... | |
958 | 959 |
public int getIntParameterValue(String key) { |
959 | 960 |
return TXMPreferences.getInt(key, this, this.commandPreferencesNodePath); |
960 | 961 |
} |
961 |
|
|
962 |
|
|
962 | 963 |
/** |
963 | 964 |
* Gets the value of the specified key in parameters, local result node or |
964 | 965 |
* default preferences nodes. |
... | ... | |
969 | 970 |
public float getFloatParameterValue(String key) { |
970 | 971 |
return TXMPreferences.getFloat(key, this, this.commandPreferencesNodePath); |
971 | 972 |
} |
972 |
|
|
973 |
|
|
973 | 974 |
/** |
974 | 975 |
* Gets the value of the specified key in parameters, local result node or |
975 | 976 |
* default preferences nodes. |
... | ... | |
980 | 981 |
public double getDoubleParameterValue(String key) { |
981 | 982 |
return TXMPreferences.getDouble(key, this, this.commandPreferencesNodePath); |
982 | 983 |
} |
983 |
|
|
984 |
|
|
984 | 985 |
/** |
985 | 986 |
* Gets the value of the specified key in parameters, local result node or |
986 | 987 |
* default preferences nodes. |
... | ... | |
991 | 992 |
public boolean getBooleanParameterValue(String key) { |
992 | 993 |
return TXMPreferences.getBoolean(key, this, this.commandPreferencesNodePath); |
993 | 994 |
} |
994 |
|
|
995 |
|
|
995 | 996 |
/** |
996 | 997 |
* Gets the value of the specified key in parameters, local result node or |
997 | 998 |
* default preferences nodes. |
... | ... | |
1002 | 1003 |
public long getLongParameterValue(String key) { |
1003 | 1004 |
return TXMPreferences.getLong(key, this, this.commandPreferencesNodePath); |
1004 | 1005 |
} |
1005 |
|
|
1006 |
|
|
1006 | 1007 |
/** |
1007 | 1008 |
* Gets the value of the specified key in parameters, local result node or |
1008 | 1009 |
* default preferences nodes. |
... | ... | |
1013 | 1014 |
public String getStringParameterValue(String key) { |
1014 | 1015 |
return TXMPreferences.getString(key, this, this.commandPreferencesNodePath); |
1015 | 1016 |
} |
1016 |
|
|
1017 |
|
|
1017 | 1018 |
/** |
1018 | 1019 |
* Gets the value of the specified key in parameters, local result node or |
1019 | 1020 |
* default preferences nodes. |
... | ... | |
1024 | 1025 |
public Date getDateParameterValue(String key) { |
1025 | 1026 |
return TXMPreferences.getDate(key, this, this.commandPreferencesNodePath); |
1026 | 1027 |
} |
1027 |
|
|
1028 |
|
|
1028 | 1029 |
/** |
1029 | 1030 |
* Gets the value of the specified key in parameters, local result node or |
1030 | 1031 |
* default preferences nodes. |
... | ... | |
1041 | 1042 |
return null; |
1042 | 1043 |
} |
1043 | 1044 |
} |
1044 |
|
|
1045 |
|
|
1045 |
|
|
1046 |
|
|
1046 | 1047 |
/** |
1047 | 1048 |
* Checks if the specified parameter exists. |
1048 | 1049 |
* |
... | ... | |
1052 | 1053 |
public boolean parameterExists(String key) { |
1053 | 1054 |
return TXMPreferences.keyExists(this.parametersNodePath, key); |
1054 | 1055 |
} |
1055 |
|
|
1056 |
|
|
1056 | 1057 |
/** |
1057 | 1058 |
* Checks if a preference is empty (equals to "") in the command preference node. |
1058 | 1059 |
* An empty preference can be used to disable a functionality for a kind of result |
... | ... | |
1064 | 1065 |
public boolean isEmptyPreference(String key) { |
1065 | 1066 |
return TXMPreferences.isEmpty(this.commandPreferencesNodePath, key); |
1066 | 1067 |
} |
1067 |
|
|
1068 |
|
|
1068 | 1069 |
/** |
1069 | 1070 |
* Stores the specified parameters pairs of key/value in a local node dedicated to the specified result. The node qualifier is generated by the <code>TXMResult.getUUID</code> method. |
1070 | 1071 |
* |
... | ... | |
1074 | 1075 |
public void saveParameter(String key, List<?> values) { |
1075 | 1076 |
this.saveParameter(key, StringUtils.join(values, UNDERSCORE)); |
1076 | 1077 |
} |
1077 |
|
|
1078 |
|
|
1078 |
|
|
1079 |
|
|
1079 | 1080 |
/** |
1080 | 1081 |
* Stores the specified parameters pairs of key/value in a local node dedicated to the specified result. The node qualifier is generated by the <code>TXMResult.getUUID</code> method. |
1081 | 1082 |
* |
... | ... | |
1086 | 1087 |
public void saveParameter(String key, Object value) { |
1087 | 1088 |
// FIXME: debug |
1088 | 1089 |
// Log.info("TXMResult.saveParameter(): saving parameter " + key + " = " + value + " for " + this.getClass() + " (" + value.getClass() + ") to node."); |
1089 |
|
|
1090 |
|
|
1090 | 1091 |
TXMPreferences.putLocal(this, key, value); |
1091 | 1092 |
} |
1092 |
|
|
1093 |
|
|
1093 |
|
|
1094 |
|
|
1094 | 1095 |
/** |
1095 | 1096 |
* Stores the result parameter fields declared by their @Parameter annotation in the persisted result node preferences. |
1096 | 1097 |
* One have to implement saveParameters() to save parameters that are not of primitive types (e.g. Property, List, HashMap...) |
... | ... | |
1099 | 1100 |
* @throws Exception |
1100 | 1101 |
*/ |
1101 | 1102 |
public boolean autoSaveParametersFromAnnotations() throws Exception { |
1102 |
|
|
1103 |
|
|
1103 | 1104 |
Log.finest("TXMResult.autoSaveParametersFromAnnotations(): " + this.getClass().getSimpleName() + ": saving parameters to local node..."); |
1104 |
|
|
1105 |
|
|
1105 | 1106 |
// internal data to save for unserialization |
1106 | 1107 |
if (this.getClass().isAnonymousClass()) { |
1107 | 1108 |
this.saveParameter(TXMPreferences.CLASS, this.getClass().getSuperclass().getName()); // avoid bug later if an anonymous class has been used. |
... | ... | |
1110 | 1111 |
} |
1111 | 1112 |
this.saveParameter(TXMPreferences.RESULT_PARAMETERS_NODE_PATH, this.parametersNodePath); |
1112 | 1113 |
this.saveParameter(TXMPreferences.BUNDLE_ID, FrameworkUtil.getBundle(getClass()).getSymbolicName()); |
1113 |
|
|
1114 |
|
|
1114 |
|
|
1115 |
|
|
1115 | 1116 |
if (this.parent != null) { |
1116 | 1117 |
this.saveParameter(TXMPreferences.PARENT_PARAMETERS_NODE_PATH, this.parent.getParametersNodePath()); |
1117 | 1118 |
} |
1118 |
|
|
1119 |
|
|
1119 | 1120 |
if (hasBeenComputedOnce()) { |
1120 | 1121 |
this.lazyName = this.getSimpleName(); |
1121 | 1122 |
} |
1122 |
|
|
1123 |
|
|
1123 | 1124 |
List<Field> fields = BeanParameters.getAllFields(this); |
1124 |
|
|
1125 |
|
|
1125 | 1126 |
for (Field f : fields) { |
1126 | 1127 |
Parameter parameter = f.getAnnotation(Parameter.class); |
1127 | 1128 |
if (parameter == null) { |
... | ... | |
1131 | 1132 |
if (key.isEmpty()) { |
1132 | 1133 |
continue; // no preference key defined |
1133 | 1134 |
} |
1134 |
|
|
1135 |
|
|
1135 | 1136 |
if (f.getType().isAssignableFrom(int.class) || f.getType().isAssignableFrom(Integer.class) || |
1136 | 1137 |
f.getType().isAssignableFrom(double.class) || f.getType().isAssignableFrom(Double.class) || |
1137 | 1138 |
f.getType().isAssignableFrom(float.class) || f.getType().isAssignableFrom(Float.class) || |
1138 | 1139 |
f.getType().isAssignableFrom(boolean.class) || f.getType().isAssignableFrom(Boolean.class) || |
1139 | 1140 |
f.getType().isAssignableFrom(String.class) || f.getType().isAssignableFrom(File.class) |
1140 |
|
|
1141 |
// FIXME: do not pass a Serializable for now |
|
1142 |
// || !f.getType().isAssignableFrom(Serializable.class) |
|
1143 |
// || !Serializable.class.isInstance(f) |
|
1144 |
|
|
1145 |
) { |
|
1146 |
|
|
1147 |
|
|
1141 |
|
|
1142 |
// FIXME: do not pass a Serializable for now
|
|
1143 |
// || !f.getType().isAssignableFrom(Serializable.class)
|
|
1144 |
// || !Serializable.class.isInstance(f)
|
|
1145 |
|
|
1146 |
) {
|
|
1147 |
|
|
1148 |
|
|
1148 | 1149 |
f.setAccessible(true); // set accessible to test the field values |
1149 | 1150 |
try { |
1150 | 1151 |
Object value = f.get(this); |
... | ... | |
1171 | 1172 |
} |
1172 | 1173 |
return true; |
1173 | 1174 |
} |
1174 |
|
|
1175 |
|
|
1175 | 1176 |
/** |
1176 | 1177 |
* Dedicated to stores the result parameters in the persisted result node preferences. |
1177 | 1178 |
* One have to implement this method to save parameters that are not of primitive types (e.g. Property, List, HashMap...) |
... | ... | |
1181 | 1182 |
* @throws Exception |
1182 | 1183 |
*/ |
1183 | 1184 |
public abstract boolean saveParameters() throws Exception; |
1184 |
|
|
1185 |
|
|
1185 | 1186 |
/** |
1186 | 1187 |
* calls saveParameters() on this and children if childrenAsWell is set to true |
1187 | 1188 |
* |
... | ... | |
1192 | 1193 |
* @throws Exception |
1193 | 1194 |
*/ |
1194 | 1195 |
public boolean saveParameters(boolean childrenAsWell) throws Exception { |
1195 |
|
|
1196 |
|
|
1196 | 1197 |
boolean ret = true; |
1197 |
|
|
1198 |
|
|
1198 | 1199 |
if (this.mustBePersisted()) { |
1199 | 1200 |
ret = this.saveParameters(); |
1200 | 1201 |
if (childrenAsWell) { |
... | ... | |
1205 | 1206 |
} |
1206 | 1207 |
return ret; |
1207 | 1208 |
} |
1208 |
|
|
1209 |
|
|
1209 | 1210 |
// FIXME: SJ: this method should not call persist on children if childrenAsWell == false? |
1210 | 1211 |
public void persist(boolean childrenAsWell) { |
1211 | 1212 |
if (this.mustBePersisted()) { |
... | ... | |
1215 | 1216 |
} |
1216 | 1217 |
} |
1217 | 1218 |
} |
1218 |
|
|
1219 |
|
|
1219 | 1220 |
/** |
1220 | 1221 |
* load or reload parameters from the preference store node |
1221 | 1222 |
* @return |
... | ... | |
1224 | 1225 |
public boolean autoLoadParametersFromAnnotations() throws Exception { |
1225 | 1226 |
return this.autoLoadParametersFromAnnotations(Parameter.COMPUTING) && this.autoLoadParametersFromAnnotations(Parameter.INTERNAL); |
1226 | 1227 |
} |
1227 |
|
|
1228 |
|
|
1228 | 1229 |
/** |
1229 | 1230 |
* Fills the result parameter fields declared by their @Parameter annotation from the persisted result node or default node of the preferences. |
1230 | 1231 |
* One have to implement loadParameters() to load parameters that are not of primitive types (e.g. Property, List, HashMap...) |
... | ... | |
1233 | 1234 |
* @throws Exception |
1234 | 1235 |
*/ |
1235 | 1236 |
protected boolean autoLoadParametersFromAnnotations(int parameterType) throws Exception { |
1236 |
|
|
1237 |
|
|
1237 | 1238 |
List<Field> fields = BeanParameters.getAllFields(this); |
1238 |
|
|
1239 |
|
|
1239 | 1240 |
for (Field f : fields) { |
1240 |
|
|
1241 |
|
|
1241 | 1242 |
Parameter parameter = f.getAnnotation(Parameter.class); |
1242 | 1243 |
if (parameter == null || parameter.type() != parameterType) { |
1243 | 1244 |
continue; |
1244 | 1245 |
} |
1245 |
|
|
1246 |
|
|
1246 | 1247 |
String key = parameter.key(); |
1247 |
|
|
1248 |
|
|
1248 | 1249 |
if (key.isEmpty()) { |
1249 | 1250 |
continue; // no preference key defined for the parameter so it can't be filled with default value or result persistence value from preferences nodes |
1250 | 1251 |
} |
1251 | 1252 |
try { |
1252 | 1253 |
f.setAccessible(true); // set accessible to test the field values |
1253 |
|
|
1254 |
|
|
1254 | 1255 |
Object value = null; |
1255 |
|
|
1256 |
|
|
1256 | 1257 |
// only manage primitive types |
1257 | 1258 |
if (f.getType().isAssignableFrom(String.class)) { |
1258 | 1259 |
value = this.getStringParameterValue(key); |
... | ... | |
1284 | 1285 |
// SJ: or better, when the abstraction of Property, etc. will be done, we could implement some extensions as in ChartCreator model to other engines, eg. SearchEngine, that will return |
1285 | 1286 |
// the right class here |
1286 | 1287 |
f.set(this, value); |
1287 |
|
|
1288 |
|
|
1288 | 1289 |
// FIXME: Debug |
1289 | 1290 |
Log.finest("TXMResult.autoLoadParametersFromAnnotations(): setting parameter " + key + " = " + value + "\t[" + this.getClass() + "]"); |
1290 |
|
|
1291 |
|
|
1291 | 1292 |
} |
1292 | 1293 |
catch (Exception e) { |
1293 | 1294 |
e.printStackTrace(); |
... | ... | |
1295 | 1296 |
} |
1296 | 1297 |
return true; |
1297 | 1298 |
} |
1298 |
|
|
1299 |
|
|
1299 | 1300 |
/** |
1300 | 1301 |
* Method dedicated to manually create and load non primitive parameters from strings stored in preference nodes in subclasses. |
1301 | 1302 |
* This method is called by the constructor of the class TXMResult. |
... | ... | |
1305 | 1306 |
* @throws Exception |
1306 | 1307 |
*/ |
1307 | 1308 |
public abstract boolean loadParameters() throws Exception; |
1308 |
|
|
1309 |
|
|
1309 | 1310 |
/** |
1310 | 1311 |
* Initializes the @Parameter class members objects |
1311 | 1312 |
* |
... | ... | |
1313 | 1314 |
* @return |
1314 | 1315 |
*/ |
1315 | 1316 |
public abstract boolean setParameters(TXMParameters parameters) throws Exception; |
1316 |
|
|
1317 |
|
|
1317 | 1318 |
/** |
1318 | 1319 |
* Initializes the @Parameter class members objects |
1319 | 1320 |
* |
... | ... | |
1324 | 1325 |
public final boolean setParameters(HashMap<String, Object> parameters) throws Exception { |
1325 | 1326 |
return setParameters(new TXMParameters(parameters)); |
1326 | 1327 |
} |
1327 |
|
|
1328 |
|
|
1328 | 1329 |
/** |
1329 | 1330 |
* Sets a parameter from its parameter annotation "key". |
1330 | 1331 |
* |
... | ... | |
1336 | 1337 |
public boolean setParameter(String key, Object value) throws Exception { |
1337 | 1338 |
return setParameter(key, value, false); |
1338 | 1339 |
} |
1339 |
|
|
1340 |
|
|
1340 | 1341 |
/** |
1341 | 1342 |
* Sets a parameter from its parameter annotation "key". |
1342 | 1343 |
* |
... | ... | |
1348 | 1349 |
* @throws Exception |
1349 | 1350 |
*/ |
1350 | 1351 |
public boolean setParameter(String key, Object value, boolean propagateToParent) throws Exception { |
1351 |
|
|
1352 |
|
|
1352 | 1353 |
Field targetField = BeanParameters.getField(this, key); |
1353 |
|
|
1354 |
|
|
1354 | 1355 |
if (targetField != null) { |
1355 | 1356 |
targetField.setAccessible(true); |
1356 | 1357 |
targetField.set(this, value); |
1357 |
|
|
1358 |
|
|
1358 | 1359 |
// Log |
1359 | 1360 |
String message = "TXMResult.setParameter(): " + this.getClass().getSimpleName() + ": setting parameter " + key + " = " + value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
1360 | 1361 |
Log.finest(message); |
1361 |
|
|
1362 |
|
|
1362 | 1363 |
} |
1363 | 1364 |
else if (this.parent != null && propagateToParent) { |
1364 | 1365 |
this.parent.setParameter(key, value, propagateToParent); |
1365 | 1366 |
} |
1366 |
|
|
1367 |
|
|
1367 | 1368 |
return true; |
1368 | 1369 |
} |
1369 |
|
|
1370 |
|
|
1370 | 1371 |
/** |
1371 | 1372 |
* Deletes the object from its parent, also deletes the children. The <code>TXMResult.clean()</code> methods of this result and children results are applied before the deletion. |
1372 | 1373 |
* default behavior is not silent |
... | ... | |
1376 | 1377 |
public final boolean delete() { |
1377 | 1378 |
return delete(false); |
1378 | 1379 |
} |
1379 |
|
|
1380 |
|
|
1380 | 1381 |
/** |
1381 | 1382 |
* Deletes the object from its parent, also deletes the children. The <code>TXMResult.clean()</code> methods of this result and children results are applied before the deletion. |
1382 | 1383 |
* |
... | ... | |
1384 | 1385 |
* @return |
1385 | 1386 |
*/ |
1386 | 1387 |
public final boolean delete(boolean silent) { |
1387 |
|
|
1388 |
|
|
1388 | 1389 |
try { |
1389 | 1390 |
// FIXME: debug |
1390 | 1391 |
// System.err.println("TXMResult.delete()"); |
1391 |
|
|
1392 |
|
|
1392 | 1393 |
// START WITH CHILDREN |
1393 |
|
|
1394 |
|
|
1394 | 1395 |
// remove children and clean resources |
1395 | 1396 |
while (this.children.size() > 0) { |
1396 | 1397 |
TXMResult c = this.children.get(0); |
... | ... | |
1398 | 1399 |
this.children.remove(c); // but should be done already... |
1399 | 1400 |
} |
1400 | 1401 |
this.children.clear(); |
1401 |
|
|
1402 |
|
|
1402 | 1403 |
// THEN FINISH WITH THIS |
1403 | 1404 |
// delete the local node |
1404 | 1405 |
TXMPreferences.delete(this); |
1405 |
|
|
1406 |
|
|
1406 | 1407 |
// specific cleaning |
1407 | 1408 |
this.clean(); |
1408 |
|
|
1409 |
|
|
1409 | 1410 |
// log |
1410 |
if ((this.isVisible() |
|
1411 |
&& !silent) || Log.isLoggingFineLevel()) { |
|
1411 |
if ((this.isVisible() && !silent) || Log.isLoggingFineLevel()) { |
|
1412 | 1412 |
Log.info(TXMCoreMessages.bind(TXMCoreMessages.info_p0P1Deleted, this.getResultType(), this.getSimpleName())); |
1413 | 1413 |
} |
1414 |
|
|
1414 |
|
|
1415 | 1415 |
// removes the parent only after the log since getSimpleName() can use it |
1416 | 1416 |
if (this.parent != null) { |
1417 | 1417 |
this.parent.removeChild(this); |
1418 | 1418 |
} |
1419 |
|
|
1419 |
|
|
1420 | 1420 |
return true; |
1421 | 1421 |
} |
1422 | 1422 |
catch (Exception e) { |
1423 | 1423 |
e.printStackTrace(); |
1424 | 1424 |
} |
1425 |
|
|
1425 |
|
|
1426 | 1426 |
return false; |
1427 | 1427 |
} |
1428 |
|
|
1428 |
|
|
1429 | 1429 |
/** |
1430 | 1430 |
* Deletes all non persistent results and saves the results to persist. |
1431 | 1431 |
*/ |
... | ... | |
1444 | 1444 |
} |
1445 | 1445 |
} |
1446 | 1446 |
} |
1447 |
|
|
1448 |
|
|
1447 |
|
|
1448 |
|
|
1449 | 1449 |
/** |
1450 | 1450 |
* Gets a child specified by its index in the children list. |
1451 | 1451 |
* |
... | ... | |
1460 | 1460 |
return null; |
1461 | 1461 |
} |
1462 | 1462 |
} |
1463 |
|
|
1463 |
|
|
1464 | 1464 |
/** |
1465 | 1465 |
* Adds a child result to this result. |
1466 | 1466 |
* If the child already have a parent, the child will be remove from its old parent children. |
... | ... | |
1472 | 1472 |
try { |
1473 | 1473 |
// remove from current parent if exists |
1474 | 1474 |
child.removeFromParent(); |
1475 |
|
|
1475 |
|
|
1476 | 1476 |
child.setParent(this); |
1477 | 1477 |
if (!this.children.contains(child)) { |
1478 | 1478 |
return this.children.add(child); |
... | ... | |
1484 | 1484 |
} |
1485 | 1485 |
return false; |
1486 | 1486 |
} |
1487 |
|
|
1487 |
|
|
1488 | 1488 |
/** |
1489 | 1489 |
* Inserts a child result in this result children list at the specified position. |
1490 | 1490 |
* |
... | ... | |
1504 | 1504 |
} |
1505 | 1505 |
return false; |
1506 | 1506 |
} |
1507 |
|
|
1507 |
|
|
1508 | 1508 |
/** |
1509 | 1509 |
* Removes the specified child result. |
1510 | 1510 |
* |
... | ... | |
1520 | 1520 |
} |
1521 | 1521 |
return false; |
1522 | 1522 |
} |
1523 |
|
|
1523 |
|
|
1524 | 1524 |
/** |
1525 | 1525 |
* Removes the child result specified by its index. |
1526 | 1526 |
* |
... | ... | |
1532 | 1532 |
return this.removeChild(this.children.get(index)); |
1533 | 1533 |
} |
1534 | 1534 |
catch (Exception e) { |
1535 |
|
|
1535 |
|
|
1536 | 1536 |
} |
1537 | 1537 |
return false; |
1538 | 1538 |
} |
1539 |
|
|
1539 |
|
|
1540 | 1540 |
/** |
1541 | 1541 |
* Removes the result from its parent: call the parent's removeResult method. |
1542 | 1542 |
* |
... | ... | |
1547 | 1547 |
return this.parent.removeChild(this); |
1548 | 1548 |
} |
1549 | 1549 |
catch (Exception e) { |
1550 |
|
|
1550 |
|
|
1551 | 1551 |
} |
1552 | 1552 |
return false; |
1553 | 1553 |
} |
1554 |
|
|
1555 |
|
|
1554 |
|
|
1555 |
|
|
1556 | 1556 |
/** |
1557 | 1557 |
* Checks if the result has at least one child visible. |
1558 | 1558 |
* |
... | ... | |
1561 | 1561 |
public boolean hasVisibleChild() { |
1562 | 1562 |
return !this.getChildren(true).isEmpty(); |
1563 | 1563 |
} |
1564 |
|
|
1565 |
|
|
1564 |
|
|
1565 |
|
|
1566 | 1566 |
/** |
1567 | 1567 |
* Gets all the children results (not a clone). |
1568 | 1568 |
* |
... | ... | |
1571 | 1571 |
public List<TXMResult> getChildren() { |
1572 | 1572 |
return this.children; |
1573 | 1573 |
} |
1574 |
|
|
1574 |
|
|
1575 | 1575 |
/** |
1576 | 1576 |
* Gets the children results. |
1577 | 1577 |
* |
... | ... | |
1580 | 1580 |
public List<TXMResult> getChildren(boolean onlyVisible) { |
1581 | 1581 |
return this.getChildren(null, onlyVisible); |
1582 | 1582 |
} |
1583 |
|
|
1583 |
|
|
1584 | 1584 |
/** |
1585 | 1585 |
* Gets the children results specified by their class. |
1586 | 1586 |
* |
... | ... | |
1590 | 1590 |
public <T extends TXMResult> List<T> getChildren(Class<T> clazz) { |
1591 | 1591 |
return TXMResult.getNodes(this.children, clazz, false); |
1592 | 1592 |
} |
1593 |
|
|
1593 |
|
|
1594 | 1594 |
/** |
1595 | 1595 |
* Gets the children results specified by their class. |
1596 | 1596 |
* |
... | ... | |
1600 | 1600 |
public <T extends TXMResult> List<T> getChildren(Class<T> clazz, boolean onlyVisible) { |
1601 | 1601 |
return TXMResult.getNodes(this.children, clazz, onlyVisible); |
1602 | 1602 |
} |
1603 |
|
|
1603 |
|
|
1604 | 1604 |
/** |
1605 | 1605 |
* Gets the first child result specified by its class. |
1606 | 1606 |
* |
... | ... | |
1616 | 1616 |
return null; |
1617 | 1617 |
} |
1618 | 1618 |
} |
1619 |
|
|
1619 |
|
|
1620 | 1620 |
/** |
1621 | 1621 |
* Deletes all the children |
1622 | 1622 |
* |
... | ... | |
1625 | 1625 |
public void deleteChildren() { |
1626 | 1626 |
deleteChildren(null); |
1627 | 1627 |
} |
1628 |
|
|
1628 |
|
|
1629 | 1629 |
/** |
1630 | 1630 |
* Deletes the children of the specified class. |
1631 | 1631 |
* |
... | ... | |
1638 | 1638 |
children.get(i).delete(); |
1639 | 1639 |
} |
1640 | 1640 |
} |
1641 |
|
|
1642 |
|
|
1643 |
|
|
1641 |
|
|
1642 |
|
|
1643 |
|
|
1644 | 1644 |
/** |
1645 | 1645 |
* Gets the children of all the branch of the specified node in a flat list according to their specified class. |
1646 | 1646 |
* |
... | ... | |
1650 | 1650 |
*/ |
1651 | 1651 |
@SuppressWarnings("unchecked") |
1652 | 1652 |
protected static <T extends TXMResult> List<T> getDeepChildren(TXMResult parent, Class<T> clazz) { |
1653 |
|
|
1653 |
|
|
1654 | 1654 |
List<T> results = new ArrayList<>(); |
1655 | 1655 |
List<TXMResult> children = parent.getChildren(); |
1656 |
|
|
1656 |
|
|
1657 | 1657 |
for (int i = 0; i < children.size(); i++) { |
1658 | 1658 |
TXMResult child = children.get(i); |
1659 | 1659 |
if (clazz == null || child.getClass().isAssignableFrom(clazz)) { |
... | ... | |
1663 | 1663 |
} |
1664 | 1664 |
return results; |
1665 | 1665 |
} |
1666 |
|
|
1666 |
|
|
1667 | 1667 |
/** |
1668 | 1668 |
* Gets the children of all the branch in a flat list. |
1669 | 1669 |
* |
... | ... | |
1672 | 1672 |
public <T extends TXMResult> List<T> getDeepChildren(Class<T> clazz) { |
1673 | 1673 |
return TXMResult.getDeepChildren(this, clazz); |
1674 | 1674 |
} |
1675 |
|
|
1675 |
|
|
1676 | 1676 |
/** |
1677 | 1677 |
* Gets the children of all the branch in a flat list. |
1678 | 1678 |
* |
... | ... | |
1681 | 1681 |
public static List<TXMResult> getDeepChildren(TXMResult result) { |
1682 | 1682 |
return TXMResult.getDeepChildren(result, null); |
1683 | 1683 |
} |
1684 |
|
|
1684 |
|
|
1685 | 1685 |
/** |
1686 | 1686 |
* Gets the children of all the branch in a flat list. |
1687 | 1687 |
* |
... | ... | |
1690 | 1690 |
public List<TXMResult> getDeepChildren() { |
1691 | 1691 |
return TXMResult.getDeepChildren(this); |
1692 | 1692 |
} |
1693 |
|
|
1693 |
|
|
1694 | 1694 |
/** |
1695 | 1695 |
* Gets the TXMResult specified by its node path (UUID) in the children of the specified root result. |
1696 | 1696 |
* Returns the root itself if the specified node path is equal to the root node path. |
... | ... | |
1700 | 1700 |
* @return |
Formats disponibles : Unified diff