| 79 |
79 |
* Results counter to create unique ids.
|
| 80 |
80 |
*/
|
| 81 |
81 |
private static int next = 0;
|
| 82 |
|
|
|
82 |
|
| 83 |
83 |
/**
|
| 84 |
84 |
* Editor can use this to test if the result has been computed once.
|
| 85 |
85 |
*/
|
| ... | ... | |
| 95 |
95 |
* like after updating parameters
|
| 96 |
96 |
*/
|
| 97 |
97 |
protected boolean dirty = true;
|
| 98 |
|
|
|
98 |
|
| 99 |
99 |
/**
|
| 100 |
100 |
* if a method changed the internal data without **recomputing** the result, the result must be marked "altered"
|
| 101 |
101 |
*/
|
| ... | ... | |
| 137 |
137 |
* Also permits to optimize computing by testing if a specific parameter value has changed since last computing and skip or not some computing steps.
|
| 138 |
138 |
*/
|
| 139 |
139 |
protected ArrayList<HashMap<String, Object>> parametersHistory = new ArrayList<HashMap<String, Object>>();
|
| 140 |
|
|
|
140 |
|
| 141 |
141 |
/**
|
| 142 |
142 |
* Internal persistable state.
|
| 143 |
143 |
*/
|
| ... | ... | |
| 179 |
179 |
*/
|
| 180 |
180 |
@Parameter(key=TXMPreferences.CREATION_DATE, type=Parameter.INTERNAL)
|
| 181 |
181 |
private Date creationDate;
|
| 182 |
|
|
|
182 |
|
| 183 |
183 |
/**
|
| 184 |
184 |
* If locked, the result is not updated when computed.
|
| 185 |
185 |
*/
|
| 186 |
186 |
@Parameter(key=TXMPreferences.LOCK, type=Parameter.INTERNAL)
|
| 187 |
|
protected boolean locked = false;
|
| 188 |
|
|
|
187 |
protected Boolean locked = false;
|
|
188 |
|
| 189 |
189 |
/**
|
| 190 |
190 |
* Current computing state.
|
| 191 |
191 |
* True if the result is in the process of computing (is in compute(,) method)
|
| ... | ... | |
| 226 |
226 |
}
|
| 227 |
227 |
|
| 228 |
228 |
// no parametersNodePath -> new result
|
| 229 |
|
|
|
229 |
|
| 230 |
230 |
if (parametersNodePath == null) { // new object
|
| 231 |
231 |
if (this.getProject() != null) {
|
| 232 |
232 |
parametersNodePath = this.getProject().getParametersNodeRootPath();
|
| ... | ... | |
| 234 |
234 |
else {
|
| 235 |
235 |
parametersNodePath = ""; //$NON-NLS-1$;
|
| 236 |
236 |
}
|
| 237 |
|
|
|
237 |
|
| 238 |
238 |
this.parametersNodePath = parametersNodePath + createUUID() + "_" + this.getClass().getSimpleName(); //$NON-NLS-1$;
|
| 239 |
239 |
}
|
| 240 |
240 |
else {
|
| ... | ... | |
| 265 |
265 |
parent == null &&
|
| 266 |
266 |
this.parametersNodePath != null &&
|
| 267 |
267 |
!parentNodePath.isEmpty()) {
|
| 268 |
|
|
|
268 |
|
| 269 |
269 |
Log.finest("Searching parent with UUID " + parentNodePath + "..."); //$NON-NLS-1$ //$NON-NLS-2$
|
| 270 |
|
|
|
270 |
|
| 271 |
271 |
//TODO this is quite CPU expensive because 'retrievedParent' is researched in all projects
|
| 272 |
272 |
TXMResult retrievedParent = TXMResult.getResult(parentNodePath);
|
| 273 |
273 |
if (retrievedParent != null) {
|
| ... | ... | |
| 280 |
280 |
TBXPreferences.delete(this);
|
| 281 |
281 |
}
|
| 282 |
282 |
catch(Exception e) {
|
| 283 |
|
|
|
283 |
|
| 284 |
284 |
}
|
| 285 |
285 |
return;
|
| 286 |
286 |
}
|
| ... | ... | |
| 290 |
290 |
try {
|
| 291 |
291 |
this.autoLoadParametersFromAnnotations(); // auto fill from Parameter annotations
|
| 292 |
292 |
this.loadParameters(); // subclasses manual settings
|
| 293 |
|
|
|
293 |
|
| 294 |
294 |
try {
|
| 295 |
295 |
if (creationDate == null) {
|
| 296 |
296 |
creationDate = Calendar.getInstance().getTime();
|
| ... | ... | |
| 325 |
325 |
public boolean isAltered() {
|
| 326 |
326 |
return altered;
|
| 327 |
327 |
}
|
| 328 |
|
|
|
328 |
|
| 329 |
329 |
/**
|
| 330 |
330 |
* Mark the result as altered -> modifications are lost after a re-compute
|
| 331 |
331 |
*/
|
| 332 |
332 |
public void setAltered() {
|
| 333 |
333 |
this.altered = true;
|
| 334 |
334 |
}
|
| 335 |
|
|
|
335 |
|
| 336 |
336 |
/**
|
|
337 |
* Do something when project is closed
|
|
338 |
*/
|
|
339 |
public void onProjectClose() {
|
|
340 |
|
|
341 |
}
|
|
342 |
|
|
343 |
/**
|
|
344 |
* Do something when project is opened
|
|
345 |
*/
|
|
346 |
public void onProjectOpen() {
|
|
347 |
|
|
348 |
}
|
|
349 |
|
|
350 |
/**
|
| 337 |
351 |
* Locks/unlocks the result.
|
| 338 |
352 |
*/
|
| 339 |
353 |
public void setLocked(boolean state) {
|
| 340 |
354 |
this.locked = state;
|
| 341 |
|
|
|
355 |
|
| 342 |
356 |
if (this.locked && this.parent != null) {
|
| 343 |
357 |
this.parent.setLocked(true);
|
| 344 |
358 |
}
|
| ... | ... | |
| 348 |
362 |
}
|
| 349 |
363 |
}
|
| 350 |
364 |
}
|
| 351 |
|
|
|
365 |
|
| 352 |
366 |
/**
|
| 353 |
367 |
* @return true if the result is locked
|
| 354 |
368 |
*/
|
| 355 |
369 |
public boolean isLocked() {
|
| 356 |
370 |
return this.locked;
|
| 357 |
371 |
}
|
| 358 |
|
|
|
372 |
|
| 359 |
373 |
/**
|
| 360 |
374 |
* Creates an UUID dedicated to persistence of this result.
|
| 361 |
375 |
* @return
|
| ... | ... | |
| 365 |
379 |
//this.uniqueID = this.getClass().getName() + '@' + ID_TIME_FORMAT.format(new Date(System.currentTimeMillis())) + "_" + UUID.randomUUID();
|
| 366 |
380 |
return UUID_PREFIX + ID_TIME_FORMAT.format(new Date(System.currentTimeMillis())) + "_" + nextInt();
|
| 367 |
381 |
}
|
| 368 |
|
|
|
382 |
|
| 369 |
383 |
/**
|
| 370 |
384 |
*
|
| 371 |
385 |
* @return the next integer in the current session of TXM
|
| ... | ... | |
| 557 |
571 |
}
|
| 558 |
572 |
}
|
| 559 |
573 |
|
| 560 |
|
|
|
574 |
|
| 561 |
575 |
try {
|
| 562 |
576 |
if(this.getLastParametersFromHistory().isEmpty()) {
|
| 563 |
577 |
this.parametersHistory.remove(this.parametersHistory.size() - 1);
|
| ... | ... | |
| 586 |
600 |
* @return
|
| 587 |
601 |
*/
|
| 588 |
602 |
public boolean hasParameterChanged(String key, HashMap<String, Object> lastParameters) {
|
| 589 |
|
|
|
603 |
|
| 590 |
604 |
if(lastParameters == null) {
|
| 591 |
605 |
return true;
|
| 592 |
606 |
}
|
| 593 |
|
|
|
607 |
|
| 594 |
608 |
if (key.isEmpty()) {
|
| 595 |
609 |
return false;
|
| 596 |
610 |
}
|
| ... | ... | |
| 624 |
638 |
}
|
| 625 |
639 |
|
| 626 |
640 |
boolean hasParameterChanged = false;
|
| 627 |
|
|
|
641 |
|
| 628 |
642 |
List<Field> fields = this.getAllFields();
|
| 629 |
|
|
|
643 |
|
| 630 |
644 |
for (Field f : fields) {
|
| 631 |
645 |
Parameter parameter = f.getAnnotation(Parameter.class);
|
| 632 |
646 |
if (parameter == null || parameter.type() != parameterType) {
|
| ... | ... | |
| 643 |
657 |
f.setAccessible(true); // to be able to test the field values
|
| 644 |
658 |
|
| 645 |
659 |
hasParameterChanged = this.hasParameterChanged(name, lastParameters);
|
| 646 |
|
|
|
660 |
|
| 647 |
661 |
if (hasParameterChanged) {
|
| 648 |
662 |
Log.finest("TXMResult.hasParameterChanged(): " + this.getClass().getSimpleName() + ": parameter " + name + " has changed.");
|
| 649 |
663 |
break;
|
| 650 |
664 |
}
|
| 651 |
665 |
}
|
| 652 |
|
|
|
666 |
|
| 653 |
667 |
return hasParameterChanged;
|
| 654 |
668 |
}
|
| 655 |
669 |
|
| 656 |
|
|
|
670 |
|
| 657 |
671 |
/**
|
| 658 |
672 |
* Checks if at least one computing parameter value has changed since last computing.
|
| 659 |
673 |
* @return
|
| ... | ... | |
| 662 |
676 |
public boolean hasParameterChanged() throws Exception {
|
| 663 |
677 |
return this.hasParameterChanged(this.getLastParametersFromHistory(), Parameter.COMPUTING);
|
| 664 |
678 |
}
|
| 665 |
|
|
| 666 |
|
|
|
679 |
|
|
680 |
|
| 667 |
681 |
/**
|
| 668 |
682 |
* Dumps the command and default preferences of the result preferences node qualifier.
|
| 669 |
683 |
* @return
|
| ... | ... | |
| 746 |
760 |
|
| 747 |
761 |
|
| 748 |
762 |
|
| 749 |
|
// /**
|
| 750 |
|
// * Updates the dirty state by comparing an old parameter with a new one.
|
| 751 |
|
// *
|
| 752 |
|
// * @param lastValue may be null
|
| 753 |
|
// * @param newValue may be null
|
| 754 |
|
// */
|
| 755 |
|
// protected void updateDirty(Object lastValue, Object newValue) {
|
| 756 |
|
// if(lastValue == null && newValue == null) {
|
| 757 |
|
// return;
|
| 758 |
|
// }
|
| 759 |
|
// if (lastValue == null || !lastValue.equals(newValue)) {
|
| 760 |
|
// Log.info("TXMResult.updateDirty(): " + this.getClass().getSimpleName() + ": setting dirty to true: last = "+ lastValue + " / new = " + newValue);
|
| 761 |
|
// this.setDirty();
|
| 762 |
|
// }
|
| 763 |
|
// }
|
|
763 |
// /**
|
|
764 |
// * Updates the dirty state by comparing an old parameter with a new one.
|
|
765 |
// *
|
|
766 |
// * @param lastValue may be null
|
|
767 |
// * @param newValue may be null
|
|
768 |
// */
|
|
769 |
// protected void updateDirty(Object lastValue, Object newValue) {
|
|
770 |
// if(lastValue == null && newValue == null) {
|
|
771 |
// return;
|
|
772 |
// }
|
|
773 |
// if (lastValue == null || !lastValue.equals(newValue)) {
|
|
774 |
// Log.info("TXMResult.updateDirty(): " + this.getClass().getSimpleName() + ": setting dirty to true: last = "+ lastValue + " / new = " + newValue);
|
|
775 |
// this.setDirty();
|
|
776 |
// }
|
|
777 |
// }
|
| 764 |
778 |
|
| 765 |
779 |
/**
|
| 766 |
780 |
* Sets the dirty state to true if a parameter has changed since last computing.
|
| ... | ... | |
| 768 |
782 |
* @throws Exception
|
| 769 |
783 |
*/
|
| 770 |
784 |
public void updateDirtyFromHistory() throws Exception {
|
| 771 |
|
//
|
| 772 |
|
//// // result has never been computed
|
| 773 |
|
//// if(this.getLastParametersFromHistory() == null) {
|
| 774 |
|
//// this.dirty = true;
|
| 775 |
|
//// return true;
|
| 776 |
|
//// }
|
| 777 |
|
////
|
| 778 |
|
//// List<Field> fields = this.getAllFields();
|
| 779 |
|
////
|
| 780 |
|
//// for (Field f : fields) {
|
| 781 |
|
//// Parameter parameter = f.getAnnotation(Parameter.class);
|
| 782 |
|
//// if (parameter == null
|
| 783 |
|
//// || parameter.type() == Parameter.INTERNAL
|
| 784 |
|
//// //|| parameter.type() != Parameter.COMPUTING
|
| 785 |
|
//// ) {
|
| 786 |
|
//// continue;
|
| 787 |
|
//// }
|
| 788 |
|
//// String name;
|
| 789 |
|
//// if (!parameter.key().isEmpty()) {
|
| 790 |
|
//// name = parameter.key();
|
| 791 |
|
//// }
|
| 792 |
|
//// else {
|
| 793 |
|
//// name = f.getName();
|
| 794 |
|
//// }
|
| 795 |
|
////
|
| 796 |
|
//// f.setAccessible(true); // to be able to test the field values
|
| 797 |
|
////
|
| 798 |
|
//// Object previousValue = this.getLastParametersFromHistory().get(name);
|
| 799 |
|
//// Object newValue = f.get(this);
|
| 800 |
|
////
|
| 801 |
|
//// // // FIXME: debug
|
| 802 |
|
//// // Log.finest("TXMResult.isDirtyFromHistory(): checking parameter: " + name);
|
| 803 |
|
////
|
| 804 |
|
//// this.updateDirty(previousValue, newValue);
|
| 805 |
|
//// if (this.dirty) {
|
| 806 |
|
//// Log.finest("TXMResult.isDirtyFromHistory(): " + this.getClass().getSimpleName() + ": parameter " + name + " has changed.");
|
| 807 |
|
//// return this.dirty; // no need to go further
|
| 808 |
|
//// }
|
| 809 |
|
//// }
|
| 810 |
|
//// return this.dirty;
|
| 811 |
|
//
|
| 812 |
|
// this.dirty = this.hasParameterChanged();
|
| 813 |
|
//// if (this.chartDirty) {
|
| 814 |
|
//// // FIXME: debug
|
| 815 |
|
//// Log.finest("ChartResult.isChartDirtyFromHistory(): parameter " + name + " has changed.");
|
| 816 |
|
//// return this.chartDirty; // no need to go further
|
| 817 |
|
//// }
|
| 818 |
|
//// return this.dirty;
|
| 819 |
|
// if(this.dirty) {
|
| 820 |
|
// return true;
|
| 821 |
|
// }
|
| 822 |
|
// else {
|
| 823 |
|
//return this.hasParameterChanged();
|
| 824 |
|
// }
|
| 825 |
|
|
|
785 |
//
|
|
786 |
//// // result has never been computed
|
|
787 |
//// if(this.getLastParametersFromHistory() == null) {
|
|
788 |
//// this.dirty = true;
|
|
789 |
//// return true;
|
|
790 |
//// }
|
|
791 |
////
|
|
792 |
//// List<Field> fields = this.getAllFields();
|
|
793 |
////
|
|
794 |
//// for (Field f : fields) {
|
|
795 |
//// Parameter parameter = f.getAnnotation(Parameter.class);
|
|
796 |
//// if (parameter == null
|
|
797 |
//// || parameter.type() == Parameter.INTERNAL
|
|
798 |
//// //|| parameter.type() != Parameter.COMPUTING
|
|
799 |
//// ) {
|
|
800 |
//// continue;
|
|
801 |
//// }
|
|
802 |
//// String name;
|
|
803 |
//// if (!parameter.key().isEmpty()) {
|
|
804 |
//// name = parameter.key();
|
|
805 |
//// }
|
|
806 |
//// else {
|
|
807 |
//// name = f.getName();
|
|
808 |
//// }
|
|
809 |
////
|
|
810 |
//// f.setAccessible(true); // to be able to test the field values
|
|
811 |
////
|
|
812 |
//// Object previousValue = this.getLastParametersFromHistory().get(name);
|
|
813 |
//// Object newValue = f.get(this);
|
|
814 |
////
|
|
815 |
//// // // FIXME: debug
|
|
816 |
//// // Log.finest("TXMResult.isDirtyFromHistory(): checking parameter: " + name);
|
|
817 |
////
|
|
818 |
//// this.updateDirty(previousValue, newValue);
|
|
819 |
//// if (this.dirty) {
|
|
820 |
//// Log.finest("TXMResult.isDirtyFromHistory(): " + this.getClass().getSimpleName() + ": parameter " + name + " has changed.");
|
|
821 |
//// return this.dirty; // no need to go further
|
|
822 |
//// }
|
|
823 |
//// }
|
|
824 |
//// return this.dirty;
|
|
825 |
//
|
|
826 |
// this.dirty = this.hasParameterChanged();
|
|
827 |
//// if (this.chartDirty) {
|
|
828 |
//// // FIXME: debug
|
|
829 |
//// Log.finest("ChartResult.isChartDirtyFromHistory(): parameter " + name + " has changed.");
|
|
830 |
//// return this.chartDirty; // no need to go further
|
|
831 |
//// }
|
|
832 |
//// return this.dirty;
|
|
833 |
// if(this.dirty) {
|
|
834 |
// return true;
|
|
835 |
// }
|
|
836 |
// else {
|
|
837 |
//return this.hasParameterChanged();
|
|
838 |
// }
|
|
839 |
|
| 826 |
840 |
if(this.hasParameterChanged()) {
|
| 827 |
841 |
this.dirty = true;
|
| 828 |
842 |
}
|
| 829 |
|
|
|
843 |
|
| 830 |
844 |
}
|
| 831 |
845 |
|
| 832 |
846 |
|
| ... | ... | |
| 867 |
881 |
* @param dirty
|
| 868 |
882 |
*/
|
| 869 |
883 |
public void setDirty(boolean dirty) {
|
|
884 |
setDirty(dirty, true);
|
|
885 |
}
|
|
886 |
|
|
887 |
/**
|
|
888 |
* Sets the result dirty state so editors or others will know the TXMResult needs to be recomputed or not.
|
|
889 |
* This method is also recursively called on all the children branch sets the new dirty state.
|
|
890 |
* @param dirty
|
|
891 |
*/
|
|
892 |
public void setDirty(boolean dirty, boolean propagate) {
|
| 870 |
893 |
this.dirty = dirty;
|
| 871 |
|
for (int i = 0; i < this.children.size(); i++) {
|
| 872 |
|
this.children.get(i).setDirty(dirty);
|
|
894 |
if (propagate) {
|
|
895 |
for (int i = 0; i < this.children.size(); i++) {
|
|
896 |
this.children.get(i).setDirty(dirty);
|
|
897 |
}
|
| 873 |
898 |
}
|
| 874 |
899 |
}
|
| 875 |
|
|
| 876 |
900 |
|
|
901 |
|
| 877 |
902 |
/**
|
| 878 |
903 |
* Gets the value of the specified key in parameters, local result node or
|
| 879 |
904 |
* default preferences nodes.
|
| ... | ... | |
| 939 |
964 |
public String getStringParameterValue(String key) {
|
| 940 |
965 |
return TXMPreferences.getString(key, this, this.commandPreferencesNodePath);
|
| 941 |
966 |
}
|
| 942 |
|
|
|
967 |
|
| 943 |
968 |
/**
|
| 944 |
969 |
* Gets the value of the specified key in parameters, local result node or
|
| 945 |
970 |
* default preferences nodes.
|
| ... | ... | |
| 950 |
975 |
public Date getDateParameterValue(String key) {
|
| 951 |
976 |
return TXMPreferences.getDate(key, this, this.commandPreferencesNodePath);
|
| 952 |
977 |
}
|
|
978 |
|
|
979 |
/**
|
|
980 |
* Gets the value of the specified key in parameters, local result node or
|
|
981 |
* default preferences nodes.
|
|
982 |
*
|
|
983 |
* @param key
|
|
984 |
* @return
|
|
985 |
*/
|
|
986 |
public File getFileParameterValue(String key) {
|
|
987 |
String v = TXMPreferences.getString(key, this, this.commandPreferencesNodePath);
|
|
988 |
if (v != null && v.length() > 0) {
|
|
989 |
return new File(v);
|
|
990 |
} else {
|
|
991 |
return null;
|
|
992 |
}
|
|
993 |
}
|
| 953 |
994 |
|
| 954 |
995 |
|
| 955 |
996 |
/**
|
| ... | ... | |
| 972 |
1013 |
return TXMPreferences.isEmpty(this.commandPreferencesNodePath, key);
|
| 973 |
1014 |
}
|
| 974 |
1015 |
|
| 975 |
|
|
| 976 |
|
|
| 977 |
1016 |
/**
|
| 978 |
1017 |
* 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.
|
| 979 |
1018 |
*
|
| ... | ... | |
| 1013 |
1052 |
this.saveParameter("class", this.getClass().getName()); //$NON-NLS-1$
|
| 1014 |
1053 |
|
| 1015 |
1054 |
this.saveParameter(TXMPreferences.RESULT_PARAMETERS_NODE_PATH, this.parametersNodePath);
|
| 1016 |
|
|
|
1055 |
|
| 1017 |
1056 |
// FIXME: old version that not work well if a bundle has no preference initializer
|
| 1018 |
1057 |
//this.saveParameter(TXMPreferences.BUNDLE_ID, this.commandPreferencesNodePath);
|
| 1019 |
1058 |
// FIXME: new version
|
| 1020 |
1059 |
this.saveParameter(TXMPreferences.BUNDLE_ID, FrameworkUtil.getBundle(getClass()).getSymbolicName());
|
| 1021 |
|
|
| 1022 |
|
|
| 1023 |
|
|
|
1060 |
|
|
1061 |
|
|
1062 |
|
| 1024 |
1063 |
if (this.parent != null) {
|
| 1025 |
1064 |
this.saveParameter(TXMPreferences.PARENT_PARAMETERS_NODE_PATH, this.parent.getParametersNodePath());
|
| 1026 |
1065 |
}
|
| ... | ... | |
| 1045 |
1084 |
f.getType().isAssignableFrom(double.class) || f.getType().isAssignableFrom(Double.class) ||
|
| 1046 |
1085 |
f.getType().isAssignableFrom(float.class) || f.getType().isAssignableFrom(Float.class) ||
|
| 1047 |
1086 |
f.getType().isAssignableFrom(boolean.class) || f.getType().isAssignableFrom(Boolean.class) ||
|
| 1048 |
|
f.getType().isAssignableFrom(String.class)
|
|
1087 |
f.getType().isAssignableFrom(String.class) || f.getType().isAssignableFrom(File.class)
|
| 1049 |
1088 |
|
| 1050 |
1089 |
// FIXME: do not pass a Serializable for now
|
| 1051 |
1090 |
//|| !f.getType().isAssignableFrom(Serializable.class)
|
| ... | ... | |
| 1147 |
1186 |
if (parameter == null || parameter.type() != parameterType) {
|
| 1148 |
1187 |
continue;
|
| 1149 |
1188 |
}
|
| 1150 |
|
|
|
1189 |
|
| 1151 |
1190 |
String key = parameter.key();
|
| 1152 |
1191 |
|
| 1153 |
1192 |
if (key.isEmpty()) {
|
| ... | ... | |
| 1177 |
1216 |
else if (f.getType().isAssignableFrom(Date.class)) {
|
| 1178 |
1217 |
value = this.getDateParameterValue(key);
|
| 1179 |
1218 |
}
|
|
1219 |
else if (f.getType().isAssignableFrom(File.class)) {
|
|
1220 |
value = this.getFileParameterValue(key);
|
|
1221 |
}
|
| 1180 |
1222 |
// FIXME: test to automate other type creation as Property => problem here is that org.txm.core doesn't know the plug-in org.txm.searchengine.cqp.core
|
| 1181 |
1223 |
// could be done using reflection. Get the field runtime class, then get and call the constructor
|
| 1182 |
1224 |
// else if (f.getType().isAssignableFrom(Property.class)) {
|
| ... | ... | |
| 1265 |
1307 |
if (targetField != null) {
|
| 1266 |
1308 |
targetField.setAccessible(true);
|
| 1267 |
1309 |
targetField.set(this, value);
|
| 1268 |
|
|
|
1310 |
|
| 1269 |
1311 |
// Log
|
| 1270 |
1312 |
String message = "TXMResult.setParameter(): " + this.getClass().getSimpleName() + ": setting parameter " + key + " = " + value; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
| 1271 |
1313 |
Log.finest(message);
|
| 1272 |
|
|
|
1314 |
|
| 1273 |
1315 |
}
|
| 1274 |
1316 |
else if (this.parent != null && propagateToParent) {
|
| 1275 |
1317 |
this.parent.setParameter(key, value, propagateToParent);
|
| ... | ... | |
| 1309 |
1351 |
this.clean();
|
| 1310 |
1352 |
|
| 1311 |
1353 |
if (this.parent != null) {
|
| 1312 |
|
|
| 1313 |
|
TXMResult parent = this.parent;
|
| 1314 |
|
|
|
1354 |
|
| 1315 |
1355 |
this.parent.removeChild(this);
|
| 1316 |
|
|
|
1356 |
|
| 1317 |
1357 |
}
|
| 1318 |
1358 |
this.parent = null;
|
| 1319 |
1359 |
return true;
|
| ... | ... | |
| 1327 |
1367 |
/**
|
| 1328 |
1368 |
* Deletes all non persistent results and saves the results to persist.
|
| 1329 |
1369 |
*/
|
| 1330 |
|
public static void deleteAllNonPersistentResults() {
|
| 1331 |
|
List<TXMResult> todo = Toolbox.workspace.getChildren();
|
|
1370 |
public static void deleteAllNonPersistentResults(TXMResult root) {
|
|
1371 |
List<TXMResult> todo = root.getChildren();
|
| 1332 |
1372 |
while (todo.size() > 0) {
|
| 1333 |
1373 |
TXMResult r = null;
|
| 1334 |
|
r = todo.remove(0);
|
| 1335 |
|
todo.addAll(0, r.getChildren());
|
| 1336 |
|
if (r.mustBePersisted()) {
|
| 1337 |
|
TXMPreferences.flush(r);
|
| 1338 |
|
}
|
| 1339 |
|
else {
|
| 1340 |
|
Log.finest("TXMResult.deleteAllNonPersistentResults(): Deleting result " + r.getSimpleName() + " of type " + r.getClass().getSimpleName() + ".");
|
| 1341 |
|
TXMPreferences.delete(r);
|
| 1342 |
|
}
|
|
1374 |
r = todo.remove(0);
|
|
1375 |
todo.addAll(0, r.getChildren());
|
|
1376 |
if (r.mustBePersisted()) {
|
|
1377 |
TXMPreferences.flush(r);
|
|
1378 |
}
|
|
1379 |
else {
|
|
1380 |
Log.finest("TXMResult.deleteAllNonPersistentResults(): Deleting result " + r.getSimpleName() + " of type " + r.getClass().getSimpleName() + ".");
|
|
1381 |
TXMPreferences.delete(r);
|
|
1382 |
}
|
| 1343 |
1383 |
}
|
| 1344 |
1384 |
}
|
| 1345 |
1385 |
|
| ... | ... | |
| 1444 |
1484 |
return false;
|
| 1445 |
1485 |
}
|
| 1446 |
1486 |
|
| 1447 |
|
|
|
1487 |
|
| 1448 |
1488 |
/**
|
| 1449 |
1489 |
* Checks if the result has at least one child visible.
|
| 1450 |
1490 |
* @return true if the result has at least one child visible
|
| ... | ... | |
| 1452 |
1492 |
public boolean hasVisibleChild() {
|
| 1453 |
1493 |
return !this.getChildren(true).isEmpty();
|
| 1454 |
1494 |
}
|
| 1455 |
|
|
| 1456 |
|
|
|
1495 |
|
|
1496 |
|
| 1457 |
1497 |
/**
|
| 1458 |
1498 |
* Gets all the children results (not a clone).
|
| 1459 |
1499 |
*
|
| ... | ... | |
| 1514 |
1554 |
public void deleteChildren() {
|
| 1515 |
1555 |
deleteChildren(null);
|
| 1516 |
1556 |
}
|
| 1517 |
|
|
|
1557 |
|
| 1518 |
1558 |
/**
|
| 1519 |
1559 |
* Deletes the children of the specified class.
|
| 1520 |
1560 |
* @param type
|
| ... | ... | |
| 1566 |
1606 |
public List<TXMResult> getDeepChildren(Class<? extends TXMResult> clazz) {
|
| 1567 |
1607 |
return TXMResult.getDeepChildren(this, clazz);
|
| 1568 |
1608 |
}
|
| 1569 |
|
|
|
1609 |
|
| 1570 |
1610 |
/**
|
| 1571 |
1611 |
* Gets the children of all the branch in a flat list.
|
| 1572 |
1612 |
*
|
| ... | ... | |
| 1575 |
1615 |
public static List<TXMResult> getDeepChildren(TXMResult r) {
|
| 1576 |
1616 |
return TXMResult.getDeepChildren(r, null);
|
| 1577 |
1617 |
}
|
| 1578 |
|
|
|
1618 |
|
| 1579 |
1619 |
/**
|
| 1580 |
1620 |
* Gets the children of all the branch in a flat list.
|
| 1581 |
1621 |
*
|
| ... | ... | |
| 1603 |
1643 |
return results.get(i); // a direct children is the node we are looking for
|
| 1604 |
1644 |
}
|
| 1605 |
1645 |
}
|
| 1606 |
|
|
|
1646 |
|
| 1607 |
1647 |
for (int i = 0; i < results.size(); i++) {
|
| 1608 |
1648 |
TXMResult r = getResult(results.get(i), nodePath);
|
| 1609 |
1649 |
if (r != null) {
|
| ... | ... | |
| 1705 |
1745 |
public boolean isChild(TXMResult child) {
|
| 1706 |
1746 |
return this.getDeepChildren().contains(child);
|
| 1707 |
1747 |
}
|
| 1708 |
|
|
|
1748 |
|
| 1709 |
1749 |
/**
|
| 1710 |
1750 |
* Gets the sibling nodes of this node result.
|
| 1711 |
1751 |
*/
|
| ... | ... | |
| 1738 |
1778 |
public boolean isVisible() {
|
| 1739 |
1779 |
return this.visible;
|
| 1740 |
1780 |
}
|
| 1741 |
|
|
|
1781 |
|
| 1742 |
1782 |
public boolean isParentVisible() {
|
| 1743 |
1783 |
return parent != null && (parent.isVisible() || parent.isInternalPersistable());
|
| 1744 |
1784 |
}
|
| ... | ... | |
| 1795 |
1835 |
*/
|
| 1796 |
1836 |
public abstract String getDetails();
|
| 1797 |
1837 |
|
| 1798 |
|
|
|
1838 |
|
| 1799 |
1839 |
/**
|
| 1800 |
1840 |
* Gets a message indicating the start of computing.
|
| 1801 |
1841 |
* Dedicated to indicate the start of computing and, for example, the parameters used for the computing.
|
| ... | ... | |
| 1806 |
1846 |
public String getComputingStartMessage() {
|
| 1807 |
1847 |
return "Computing "+this.getClass().getSimpleName()+"...";
|
| 1808 |
1848 |
}
|
| 1809 |
|
// public abstract String getComputingStartMessage();
|
|
1849 |
// public abstract String getComputingStartMessage();
|
| 1810 |
1850 |
|
| 1811 |
|
|
|
1851 |
|
| 1812 |
1852 |
/**
|
| 1813 |
1853 |
* Gets a message indicating the computing is done.
|
| 1814 |
1854 |
* Dedicated to indicate the end of computing and, for example, some informations about the result (eg. : 12 matches found, No matches found, etc.).
|
| ... | ... | |
| 1819 |
1859 |
public String getComputingDoneMessage() {
|
| 1820 |
1860 |
return "";
|
| 1821 |
1861 |
}
|
| 1822 |
|
// public abstract String getComputingDoneMessage();
|
|
1862 |
// public abstract String getComputingDoneMessage();
|
| 1823 |
1863 |
|
| 1824 |
|
|
| 1825 |
|
|
| 1826 |
|
|
| 1827 |
|
|
| 1828 |
1864 |
|
| 1829 |
|
|
|
1865 |
|
|
1866 |
|
|
1867 |
|
|
1868 |
|
|
1869 |
|
| 1830 |
1870 |
/**
|
| 1831 |
1871 |
* Gets the user name if exists otherwise, the lazy name if exists, otherwise the simple name.
|
| 1832 |
1872 |
*
|
| ... | ... | |
| 1853 |
1893 |
return "..."; //$NON-NLS-1$
|
| 1854 |
1894 |
}
|
| 1855 |
1895 |
|
| 1856 |
|
// /**
|
| 1857 |
|
// * Returns a string representation of an unique ID for the result.
|
| 1858 |
|
// *
|
| 1859 |
|
// * @return
|
| 1860 |
|
// */
|
| 1861 |
|
// public String getUUID() {
|
| 1862 |
|
// return this.uniqueID;
|
| 1863 |
|
// }
|
|
1896 |
// /**
|
|
1897 |
// * Returns a string representation of an unique ID for the result.
|
|
1898 |
// *
|
|
1899 |
// * @return
|
|
1900 |
// */
|
|
1901 |
// public String getUUID() {
|
|
1902 |
// return this.uniqueID;
|
|
1903 |
// }
|
| 1864 |
1904 |
|
| 1865 |
1905 |
/**
|
| 1866 |
1906 |
* Gets a string representing the result that can be used as a file name (eg. for exporting in file).
|
| ... | ... | |
| 1924 |
1964 |
public TXMResult clone() {
|
| 1925 |
1965 |
return clone(null, true);
|
| 1926 |
1966 |
}
|
| 1927 |
|
|
|
1967 |
|
| 1928 |
1968 |
public TXMResult clone(boolean all) {
|
| 1929 |
1969 |
return clone(null, all);
|
| 1930 |
1970 |
}
|
| ... | ... | |
| 1939 |
1979 |
try {
|
| 1940 |
1980 |
String newNodePath = this.getProject().getParametersNodeRootPath()+ createUUID() + "_" + this.getClass().getSimpleName();
|
| 1941 |
1981 |
TXMPreferences.cloneNode(this.getParametersNodePath(), newNodePath);
|
| 1942 |
|
|
|
1982 |
|
| 1943 |
1983 |
if (newParent != null) { // change the cloned node parent preference
|
| 1944 |
1984 |
TXMPreferences.put(newNodePath, TXMPreferences.PARENT_PARAMETERS_NODE_PATH, newParent.getParametersNodePath());
|
| 1945 |
1985 |
}
|
| 1946 |
1986 |
clone = this.getClass().getDeclaredConstructor(String.class).newInstance(newNodePath);
|
| 1947 |
|
|
|
1987 |
|
| 1948 |
1988 |
if (all) {
|
| 1949 |
1989 |
for (TXMResult child : this.children) {
|
| 1950 |
1990 |
child.clone(clone, all);
|
| ... | ... | |
| 1961 |
2001 |
try {
|
| 1962 |
2002 |
Properties props = new Properties();
|
| 1963 |
2003 |
props.load(IOUtils.getReader(parameters));
|
| 1964 |
|
|
|
2004 |
|
| 1965 |
2005 |
// some tests before...
|
| 1966 |
2006 |
String className = props.getProperty("class");
|
| 1967 |
2007 |
if (className == null || className.length() == 0) {
|
| 1968 |
2008 |
System.out.println("** Error: No class internal parameter set.");
|
| 1969 |
2009 |
return false;
|
| 1970 |
2010 |
}
|
| 1971 |
|
|
|
2011 |
|
| 1972 |
2012 |
if (this.getClass().getName().equals(className)) {
|
| 1973 |
2013 |
for (Object p : props.keySet()) {
|
| 1974 |
2014 |
String ps = p.toString();
|
| ... | ... | |
| 1987 |
2027 |
}
|
| 1988 |
2028 |
return true;
|
| 1989 |
2029 |
}
|
| 1990 |
|
|
|
2030 |
|
| 1991 |
2031 |
/**
|
| 1992 |
2032 |
* import a result from a parameter file
|
| 1993 |
2033 |
* @param allparameters the parameters file
|
| ... | ... | |
| 1997 |
2037 |
try {
|
| 1998 |
2038 |
Properties props = new Properties();
|
| 1999 |
2039 |
props.load(IOUtils.getReader(parameters));
|
| 2000 |
|
|
|
2040 |
|
| 2001 |
2041 |
// some tests before...
|
| 2002 |
2042 |
String className = props.getProperty("class");
|
| 2003 |
2043 |
if (className == null || className.length() == 0) {
|
| 2004 |
2044 |
System.out.println("** Error: No class internal parameter set.");
|
| 2005 |
2045 |
return null;
|
| 2006 |
2046 |
}
|
| 2007 |
|
|
|
2047 |
|
| 2008 |
2048 |
String bundleId = props.getProperty("bundle_id");
|
| 2009 |
2049 |
if (bundleId == null || bundleId.length() == 0) {
|
| 2010 |
2050 |
System.out.println("** Error: No bundle_id internal parameter set.");
|
| 2011 |
2051 |
return null;
|
| 2012 |
2052 |
}
|
| 2013 |
|
|
|
2053 |
|
| 2014 |
2054 |
Bundle bundle = Platform.getBundle(bundleId);
|
| 2015 |
2055 |
if (bundle == null) {
|
| 2016 |
2056 |
Log.finest("** Error: can not restore object with bundle name " + bundleId); //$NON-NLS-1$
|
| 2017 |
2057 |
return null;
|
| 2018 |
2058 |
}
|
| 2019 |
|
|
|
2059 |
|
| 2020 |
2060 |
// copy parameters
|
| 2021 |
2061 |
String newNodePath = this.getProject().getParametersNodeRootPath()+ createUUID() + "_" + className;
|
| 2022 |
2062 |
TXMPreferences.put(newNodePath, TXMPreferences.PARENT_PARAMETERS_NODE_PATH, this.getParametersNodePath());
|
| ... | ... | |
| 2026 |
2066 |
if (TXMPreferences.RESULT_PARAMETERS_NODE_PATH.equals(ps)) continue;
|
| 2027 |
2067 |
TXMPreferences.put(newNodePath, ps, props.getProperty(ps, ""));
|
| 2028 |
2068 |
}
|
| 2029 |
|
|
|
2069 |
|
| 2030 |
2070 |
// create instance
|
| 2031 |
2071 |
Class<?> cl = bundle.loadClass(className);
|
| 2032 |
2072 |
Constructor<?> cons = null;
|
| ... | ... | |
| 2041 |
2081 |
clazz = clazz.getSuperclass();
|
| 2042 |
2082 |
}
|
| 2043 |
2083 |
}
|
| 2044 |
|
|
|
2084 |
|
| 2045 |
2085 |
if (cons == null) {
|
| 2046 |
2086 |
System.out.println(NLS.bind("Cannot import {0} in {1}", parameters, this));
|
| 2047 |
2087 |
} else {
|
| ... | ... | |
| 2050 |
2090 |
System.out.println(NLS.bind("{0} imported", result));
|
| 2051 |
2091 |
return result;
|
| 2052 |
2092 |
}
|
| 2053 |
|
|
|
2093 |
|
| 2054 |
2094 |
} catch (Exception e) {
|
| 2055 |
2095 |
System.out.println(NLS.bind("Fail to import result from {0}: {1}", parameters, e));
|
| 2056 |
2096 |
Log.printStackTrace(e);
|
| 2057 |
2097 |
}
|
| 2058 |
2098 |
return null;
|
| 2059 |
2099 |
}
|
| 2060 |
|
|
|
2100 |
|
| 2061 |
2101 |
/**
|
| 2062 |
2102 |
* Set the TXMResult parameters
|
| 2063 |
2103 |
*
|
| ... | ... | |
| 2143 |
2183 |
return this.compute(monitor, true);
|
| 2144 |
2184 |
}
|
| 2145 |
2185 |
|
| 2146 |
|
|
|
2186 |
|
| 2147 |
2187 |
/**
|
| 2148 |
2188 |
* Computes the result if:
|
| 2149 |
2189 |
* - it can be computed (checking if all mandatory parameters are set)
|
| ... | ... | |
| 2154 |
2194 |
* @return
|
| 2155 |
2195 |
*/
|
| 2156 |
2196 |
protected boolean compute(IProgressMonitor monitor, boolean deepComputing) {
|
| 2157 |
|
|
|
2197 |
|
| 2158 |
2198 |
if (this.computing) {
|
| 2159 |
2199 |
return true;
|
| 2160 |
2200 |
}
|
| 2161 |
|
|
|
2201 |
|
| 2162 |
2202 |
this.computing = true;
|
| 2163 |
|
|
| 2164 |
|
|
|
2203 |
|
|
2204 |
|
| 2165 |
2205 |
// no changes to do
|
| 2166 |
2206 |
// FIXME: SJ: we need to do do some actions even if the object is locked, eg. updating parameters, saving parameters, etc.
|
| 2167 |
2207 |
// FIXME MD: nope the parameters must not move and will be saved in the current state
|
| ... | ... | |
| 2169 |
2209 |
this.computing = false;
|
| 2170 |
2210 |
return true;
|
| 2171 |
2211 |
}
|
| 2172 |
|
|
| 2173 |
|
|
|
2212 |
|
|
2213 |
|
| 2174 |
2214 |
try {
|
| 2175 |
2215 |
|
| 2176 |
2216 |
Log.finest("*** TXMResult.compute(): " + this.getClass().getSimpleName() + ": starting computing process...");
|
| 2177 |
2217 |
|
| 2178 |
|
|
|
2218 |
|
| 2179 |
2219 |
// FIXME: SJ: see if this skipComputing tests is still useful? is it possible to directly return instead?
|
| 2180 |
2220 |
// en fait voir ChartResult.compute() if(super.compute(monitor, true, false)), je pense que le prob vient du fait que si on retourne false dans TXMResult.compute() alors renderChart() ne sera pas appelé
|
| 2181 |
2221 |
// il faudrait retourner un état: skipped, computed, error, etc.
|
| ... | ... | |
| 2197 |
2237 |
|
| 2198 |
2238 |
// update the dirty state from history if a parameter has changed since last computing
|
| 2199 |
2239 |
this.updateDirtyFromHistory();
|
| 2200 |
|
|
|
2240 |
|
| 2201 |
2241 |
// check if the result is dirty
|
| 2202 |
2242 |
if (!this.isDirty()) {
|
| 2203 |
2243 |
Log.finest("--- TXMResult.compute(): " + this.getClass().getSimpleName() + ": result parameters have not changed since last computing, computing skipped.");
|
| ... | ... | |
| 2206 |
2246 |
|
| 2207 |
2247 |
if(!skipComputing) {
|
| 2208 |
2248 |
|
| 2209 |
|
|
|
2249 |
|
| 2210 |
2250 |
// Debug
|
| 2211 |
2251 |
Log.finest("+++ TXMResult.compute(): " + this.getClass().getSimpleName() + ": computing result of type " + this.getClass() + "...");
|
| 2212 |
2252 |
|
| ... | ... | |
| 2219 |
2259 |
|
| 2220 |
2260 |
//Log.info(this.getComputingStartMessage());
|
| 2221 |
2261 |
|
| 2222 |
|
|
|
2262 |
|
|
2263 |
if (monitor != null) monitor.subTask(this.getSimpleName()+"...");
|
| 2223 |
2264 |
// Computing
|
| 2224 |
2265 |
if (!this._compute()) {
|
| 2225 |
2266 |
Log.finest("TXMResult.compute(): " + this.getClass().getSimpleName() + ": computing failed.");
|
| 2226 |
2267 |
this.computing = false;
|
| 2227 |
2268 |
return false;
|
| 2228 |
2269 |
}
|
| 2229 |
|
|
|
2270 |
|
| 2230 |
2271 |
}
|
| 2231 |
2272 |
|
| 2232 |
2273 |
// clear the lazy name, no more needed since the object has been computed and getSimpleName() can now work
|
| ... | ... | |
| 2239 |
2280 |
if(!skipComputing) {
|
| 2240 |
2281 |
|
| 2241 |
2282 |
// store last used parameters
|
| 2242 |
|
// this.updateLastParameters();
|
|
2283 |
// this.updateLastParameters();
|
| 2243 |
2284 |
if (this.hasBeenComputedOnce// don't update the computing date if the object has been lazy loaded
|
| 2244 |
2285 |
|| this.lastComputingDate == null) { // set the update date if never computed once
|
| 2245 |
2286 |
this.lastComputingDate = Calendar.getInstance().getTime(); // update this internal parameter before saving parameters
|
| 2246 |
2287 |
}
|
| 2247 |
|
|
|
2288 |
|
| 2248 |
2289 |
if (!this.autoSaveParametersFromAnnotations()) {
|
| 2249 |
2290 |
Log.severe("TXMResult.compute(): " + this.getClass().getSimpleName() + ": failed to save parameters from annotations for " + this.getName() + ".");
|
| 2250 |
2291 |
}
|
| ... | ... | |
| 2260 |
2301 |
|
| 2261 |
2302 |
this.dirty = false; // the computing was successful, the result is no more dirty
|
| 2262 |
2303 |
this.hasBeenComputedOnce = true;
|
| 2263 |
|
|
|
2304 |
|
| 2264 |
2305 |
if (this.altered) {
|
| 2265 |
2306 |
Log.finest(NLS.bind("TXMResult.compute(): Warning {0} modifications have been lost.", this.getSimpleName()));
|
| 2266 |
2307 |
}
|
| 2267 |
2308 |
this.altered = false;
|
| 2268 |
2309 |
Log.finest("TXMResult.compute(): " + this.getClass().getSimpleName() + ": computing of result type " + this.getClass() + " done.");
|
| 2269 |
|
|
|
2310 |
|
| 2270 |
2311 |
//Log.info(this.getComputingDoneMessage());
|
| 2271 |
2312 |
|
| 2272 |
|
|
|
2313 |
|
| 2273 |
2314 |
}
|
| 2274 |
|
|
| 2275 |
|
|
|
2315 |
|
|
2316 |
|
| 2276 |
2317 |
// Children computing
|
| 2277 |
2318 |
if(!skipComputing
|
| 2278 |
2319 |
|| this.altered // FIXME: SJ: fix for computing LexicalTable children even if the LT is not dirty but only altered, need to define if it's a temporary fix or not
|
| 2279 |
2320 |
) {
|
| 2280 |
|
|
|
2321 |
|
|
2322 |
if (monitor != null && children.size() > 1) monitor.beginTask("Computing children of "+this, children.size());
|
| 2281 |
2323 |
// set the children as dirty since the result has changed
|
| 2282 |
2324 |
for (int i = 0; i < this.children.size(); i++) {
|
| 2283 |
2325 |
this.children.get(i).setDirty();
|
| 2284 |
2326 |
}
|
| 2285 |
|
|
|
2327 |
|
| 2286 |
2328 |
// Children cascade computing (if parent == null then it is the Workspace (Tree root))
|
| 2287 |
2329 |
if (deepComputing && this.parent != null) {
|
| 2288 |
|
|
|
2330 |
|
| 2289 |
2331 |
Log.finest("TXMResult.compute(): " + this.getClass().getSimpleName() + ": cascade computing of " + this.children.size() + " child(ren).");
|
| 2290 |
|
|
|
2332 |
|
| 2291 |
2333 |
for (int i = 0; i < this.children.size(); i++) {
|
| 2292 |
2334 |
this.children.get(i).compute(monitor, deepComputing);
|
|
2335 |
|
|
2336 |
if (monitor != null && children.size() > 1) monitor.worked(1);
|
| 2293 |
2337 |
}
|
| 2294 |
2338 |
}
|
| 2295 |
2339 |
}
|
| 2296 |
|
|
|
2340 |
|
| 2297 |
2341 |
}
|
| 2298 |
2342 |
catch (Exception e) {
|
| 2299 |
2343 |
e.printStackTrace();
|
| ... | ... | |
| 2558 |
2602 |
child.setUserPersistable(userPersistable);
|
| 2559 |
2603 |
}
|
| 2560 |
2604 |
}
|
| 2561 |
|
|
|
2605 |
|
| 2562 |
2606 |
// directly save and flush the preference
|
| 2563 |
2607 |
try {
|
| 2564 |
2608 |
if (this.isUserPersistable()) {
|
| ... | ... | |
| 2606 |
2650 |
public ArrayList<HashMap<String, Object>> getParametersHistory() {
|
| 2607 |
2651 |
return parametersHistory;
|
| 2608 |
2652 |
}
|
| 2609 |
|
|
|
2653 |
|
| 2610 |
2654 |
/**
|
| 2611 |
2655 |
* Gets the last computing date.
|
| 2612 |
2656 |
* @return the last computing date
|
| ... | ... | |
| 2622 |
2666 |
public Date getCreationDate() {
|
| 2623 |
2667 |
return this.creationDate;
|
| 2624 |
2668 |
}
|
| 2625 |
|
|
| 2626 |
2669 |
|
|
2670 |
|
| 2627 |
2671 |
public boolean toParametersFile(File outfile) throws IOException {
|
| 2628 |
2672 |
return TXMPreferences.flush(this, outfile);
|
| 2629 |
2673 |
}
|