001 package jigcell.compare.cellcycle;
002
003 import EDU.oswego.cs.dl.util.concurrent.Sync;
004 import java.awt.Color;
005 import java.awt.Component;
006 import java.beans.PropertyChangeEvent;
007 import java.util.Arrays;
008 import java.util.HashSet;
009 import java.util.Iterator;
010 import java.util.LinkedHashMap;
011 import java.util.List;
012 import java.util.Map;
013 import javax.swing.JComboBox;
014 import javax.swing.JFileChooser;
015 import javax.swing.JTable;
016 import javax.swing.table.TableColumnModel;
017 import jigcell.compare.IConfigEditor;
018 import jigcell.compare.IDataElement;
019 import jigcell.compare.IDataGenerator;
020 import jigcell.compare.IEditableDataGenerator;
021 import jigcell.compare.IMultipleDataSource;
022 import jigcell.compare.ITypeChecker;
023 import jigcell.compare.IWriteableDataSource;
024 import jigcell.compare.data.DataElement;
025 import jigcell.compare.data.DataGenerator;
026 import jigcell.compare.data.DataGeneratorList;
027 import jigcell.compare.data.DataGeneratorMap;
028 import jigcell.compare.data.FlippedDataElement;
029 import jigcell.compare.data.IDataGeneratorCollection;
030 import jigcell.compare.data.IDataGeneratorList;
031 import jigcell.compare.data.IDataGeneratorMap;
032 import jigcell.compare.data.SparseTreeDataElement;
033 import jigcell.compare.data.type.TimeSeriesTypeChecker;
034 import jigcell.compare.data.type.TypeChecker;
035 import jigcell.compare.impl.Compare;
036 import jigcell.compare.impl.DataGeneratorEvaluator;
037 import jigcell.compare.impl.FileDataSource;
038 import jigcell.compare.impl.SuffixFileFilter;
039 import jigcell.compare.plotter.IPlotter;
040 import jigcell.compare.plotter.PlotException;
041 import jigcell.compare.plotter.Plotter;
042 import jigcell.compare.transform.ITransform;
043 import jigcell.compare.transform.ITransformContext;
044 import jigcell.compare.transform.Transform;
045 import jigcell.compare.transform.TransformContext;
046 import jigcell.compare.ui.BasicTable;
047 import jigcell.compare.ui.ConfigEditor;
048 import jigcell.compare.ui.IResultTab;
049 import jigcell.compare.ui.InterfaceBuilder;
050 import jigcell.compare.ui.ListComboBoxModel;
051 import jigcell.compare.ui.ProgressMonitor;
052 import jigcell.compare.ui.ViewerDialog;
053 import jigcell.compare.views.EditableSeriesView;
054 import jigcell.compare.views.EvaluationErrorViewer;
055
056 /**
057 * An editable display for working with model data.
058 *
059 * <p>
060 * This code is licensed under the DARPA BioCOMP Open Source License. See LICENSE for more details.
061 * </p>
062 *
063 * @author Nicholas Allen
064 */
065
066 public class CellCycleTransformView extends EditableSeriesView implements IResultTab, DataGeneratorEvaluator.IProcessor {
067
068 /**
069 * Transform evaluation context for the cellcycle components
070 */
071
072 public final static String TRANSFORMCONTEXT_CELLCYCLE = "jigcell_cellcycle_transformcontext";
073
074 /**
075 * Display value for an unevaluated value
076 */
077
078 protected final static String VALUE_NOTEVALUATED = "Not Evaluated";
079
080 /**
081 * Display value for a non-existent value
082 */
083
084 protected final static String VALUE_NOVALUE = "No Value";
085
086 /**
087 * Error message when load data is invalid
088 */
089
090 protected final static String MESSAGE_LOADDATAERROR = "Unable to attach transform: ";
091
092 /**
093 * Error message when load data contains an unbound transform
094 */
095
096 protected final static String MESSAGE_TARGETNOTFOUNDERROR = "Unable to find experiment: ";
097
098 /**
099 * File filter for transform files
100 */
101
102 protected final static SuffixFileFilter FILTER_TRANSFORM = new SuffixFileFilter (".mss", "Transform Set (*.mss)");
103
104 /**
105 * File filter for transform result set files
106 */
107
108 protected final static SuffixFileFilter FILTER_TRANSFORMRESULT = new SuffixFileFilter (".trs", "Transform Result Set (*.trs)");
109
110 /**
111 * Displays errors encountered during evaluation
112 */
113
114 protected EvaluationErrorViewer errorViewer;
115
116 /**
117 * List of known transforms
118 */
119
120 protected IDataGeneratorList transforms;
121
122 /**
123 * Context for performing transform evaluations
124 */
125
126 protected ITransformContext context;
127
128 /**
129 * Display for list of known transforms
130 */
131
132 protected ListComboBoxModel transformModel;
133
134 /**
135 * Data model of the generators
136 */
137
138 protected TransformModel model;
139
140 /**
141 * Table model for the data in an ModelDataSeriesView.
142 */
143
144 protected class TransformModel extends EditableSeriesModel {
145
146 /**
147 * Prefix for experimental data
148 */
149
150 protected final static String PREFIX_EXPERIMENT = "Experiment- ";
151
152 /**
153 * Prefix for transform data
154 */
155
156 protected final static String PREFIX_TRANSFORM = "Transform- ";
157
158 /**
159 * Error message when plotting a cell with no data
160 */
161
162 protected final static String MESSAGE_PLOTNODATAERROR = "No data to plot";
163
164 /**
165 * Transform value column
166 */
167
168 public final Marker COLUMN_MODELVALUE = new Marker ("TransformModel.transformValue", "Transform Value");
169
170 /**
171 * Transform column
172 */
173
174 public final Marker COLUMN_TRANSFORM = new Marker ("TransformModel.transform", "Transform");
175
176 /**
177 * Type column
178 */
179
180 public final Marker COLUMN_TYPE = new Marker ("TransformModel.type", "Value Type");
181
182 /**
183 * Creates a new table model.
184 */
185
186 public TransformModel () {
187 super ();
188 COLUMN_VALUE.setName ("Experiment Value");
189 setColumnMarkers (new Marker [] {COLUMN_NAME, COLUMN_VALUE, COLUMN_TRANSFORM, COLUMN_MODELVALUE, COLUMN_TYPE, COLUMN_COMMENT});
190 setColumnWeights (new double [] {3.0, 2.0, 3.0, 2.0, 1.0, 3.0});
191 }
192
193 /**
194 * Starts editing a cell in the table.
195 *
196 * @param row Row
197 * @param column Column
198 */
199
200 public void editCellAt (int row, int column) {
201 if (!isCellEditable (row, column))
202 return;
203 if (column == findColumn (COLUMN_TRANSFORM)) {
204 setValueAt (manager.showInputDialog ("Choose a Transform", transforms.toArray (), getValueAt (row, column), "Set"), row, column);
205 return;
206 }
207 super.editCellAt (row, column);
208 }
209
210 /**
211 * Fills along a column.
212 *
213 * @param row Row
214 * @param column Column
215 * @param startRow First row
216 * @param endRow Last row
217 */
218
219 public void fillRangeAt (int row, int column, int startRow, int endRow) {
220 if (column == findColumn (COLUMN_TRANSFORM)) {
221 fillRange (column, startRow, endRow, getTransformForGenerator (row));
222 return;
223 }
224 super.fillRangeAt (row, column, startRow, endRow);
225 }
226
227 /**
228 * A value in the table.
229 *
230 * @param row Row
231 * @param column Column
232 */
233
234 public Object getValueAt (int row, int column) {
235 if (column == findColumn (COLUMN_MODELVALUE)) {
236 ITransform transform = getTransformForGenerator (row);
237 return transform == null ? VALUE_NOVALUE :
238 transform.isCached () ? DataElement.toString (transform.getElement (), true, textCutoff) : VALUE_NOTEVALUATED;
239 }
240 if (column == findColumn (COLUMN_TRANSFORM)) {
241 ITransform transform = getTransformForGenerator (row);
242 return transform == null ? (Object) VALUE_NOVALUE : transform;
243 }
244 if (column == findColumn (COLUMN_TYPE))
245 return ((IDataGenerator) generators.get (row)).getAttribute (ITypeChecker.ATTRIBUTE_TYPE);
246 return super.getValueAt (row, column);
247 }
248
249 /**
250 * Whether a value in the table is editable.
251 *
252 * @param row Row
253 * @param column Column
254 */
255
256 public boolean isCellEditable (int row, int column) {
257 return row >= 0 && row < getRowCount () && generators.get (row) instanceof IEditableDataGenerator &&
258 (column == findColumn (COLUMN_COMMENT) || column == findColumn (COLUMN_TRANSFORM));
259 }
260
261 /**
262 * Sets a value in the table.
263 *
264 * @param value Value
265 * @param row Row
266 * @param column Column
267 */
268
269 public void setValueAt (Object value, int row, int column) {
270 if (!isCellEditable (row, column))
271 return;
272 if (column == findColumn (COLUMN_TRANSFORM)) {
273 if (value == null || !(value instanceof ITransform))
274 return;
275 IEditableDataGenerator generator = (IEditableDataGenerator) generators.get (row);
276 generator.addOption (ITransform.OPTION_TRANSFORM, IDataGenerator.Option.COPYONLY);
277 generator.setOption (ITransform.OPTION_TRANSFORM, (ITransform) value);
278 model.fireTableDataChanged ();
279 return;
280 }
281 super.setValueAt (value, row, column);
282 }
283
284 /**
285 * Starts viewing a cell in the table but does not allow editing.
286 *
287 * @param row Row
288 * @param column Column
289 */
290
291 public void viewCellAt (int row, int column) {
292 if (column == findColumn (COLUMN_VALUE) || column == findColumn (COLUMN_MODELVALUE)) {
293 IDataGenerator generator = (IDataGenerator) generators.get (row);
294 if (generator.getElement ().isScalar ())
295 new ViewerDialog (compare, generator.getName (), row, column, model).setVisible (true);
296 else
297 new CellCycleDataDialog (compare, generator, row, column, model).setVisible (true);
298 return;
299 }
300 super.viewCellAt (row, column);
301 }
302
303 /**
304 * Plots the data contained in a table cell.
305 *
306 * @param row Row
307 * @param column Column
308 */
309
310 protected void plotCellAt (int row, int column) throws PlotException {
311 IDataGenerator experiment = (IDataGenerator) generators.get (row);
312 ITransform transform = Transform.getTransformForGenerator (experiment);
313 if (transform == null || !transform.isCached ())
314 throw new PlotException (MESSAGE_PLOTNODATAERROR);
315 IDataElement experimentElement = FlippedDataElement.flip (experiment.getElement ());
316 long experimentCount = experimentElement.getLength () - 1;
317 if (experimentCount == -1)
318 throw new PlotException (MESSAGE_PLOTNODATAERROR);
319 experimentElement = Plotter.splitMultipleSeries (experimentElement);
320 IDataElement transformElement = FlippedDataElement.flip (transform.getElement ());
321 long transformCount = transformElement.getLength () - 1;
322 if (transformCount == -1)
323 throw new PlotException (MESSAGE_PLOTNODATAERROR);
324 transformElement = Plotter.splitMultipleSeries (transformElement);
325 TimeSeriesTypeChecker type = computeTypeForPlot (experiment);
326 plotter.setData (new SparseTreeDataElement ());
327 plotter.setSeriesName (1, type.getName (1));
328 for (int experimentIndex = 1; experimentIndex <= experimentCount; experimentIndex++) {
329 plotter.setSeries (experimentIndex, experimentElement.getListValue (experimentIndex));
330 plotter.setSeriesName (experimentIndex + 1, PREFIX_EXPERIMENT + type.getName (experimentIndex + 1));
331 }
332 for (int transformIndex = 1; transformIndex <= transformCount; transformIndex++) {
333 plotter.setSeries (experimentCount + transformIndex, transformElement.getListValue (transformIndex));
334 plotter.setSeriesName (experimentCount + transformIndex + 1, PREFIX_TRANSFORM + type.getName (transformIndex + 1));
335 }
336 plotter.setSeriesCombine (IPlotter.Combine.NONE);
337 plotter.setTitle (experiment.getName ());
338 plotter.plot ();
339 }
340 }
341
342 /**
343 * Colors cells when a type error is detected.
344 */
345
346 protected class TransformViewRenderer extends BasicTable.BasicRenderer {
347
348 /**
349 * Creates a new view renderer.
350 */
351
352 public TransformViewRenderer () {
353 super (CellCycleTransformView.this);
354 }
355
356 public Component getTableCellRendererComponent (JTable table, Object value, boolean selected, boolean focus, int row, int column) {
357 Component cell = super.getTableCellRendererComponent (table, value, selected, focus, row, column);
358 IDataGenerator generator = (IDataGenerator) generators.get (row);
359 ITransform transform = Transform.getTransformForGenerator (generator);
360 ITypeChecker checker = TypeChecker.getTypeCheckerForGenerator (generator);
361 ITypeChecker transformChecker = transform == null ? null : transform.getOutputTypeChecker ();
362 if (!TypeChecker.validate (checker, generator) || !TypeChecker.validate (transformChecker, generator) ||
363 !TypeChecker.isCompatible (transformChecker, checker))
364 cell.setBackground (getColor ("CellCycleTransformView.backgroundTypeError"));
365 return cell;
366 }
367
368 /**
369 * {@inheritDoc}
370 */
371
372 public void readConfiguration (String state) {
373 super.readConfiguration (state);
374 putColor ("CellCycleTransformView.backgroundTypeError", getColorFromConfig (CellCycleExperimentView.CONFIG_BACKGROUNDTYPEERROR,
375 CellCycleExperimentView.DEFAULT_BACKGROUNDTYPEERROR));
376 }
377 }
378
379 /**
380 * Flushes a transform.
381 *
382 * @param transform Transform
383 */
384
385 protected static void flushTransform (ITransform transform) {
386 if (transform == null)
387 return;
388 Sync sync = transform.getEvaluationLock ();
389 if (!Compare.attemptSync (sync))
390 return;
391 try {
392 transform.flush ();
393 } finally {
394 sync.release ();
395 }
396 }
397
398 /**
399 * Creates a new table view with the ability to display model and experiment data.
400 *
401 * @param compare Comparator backend to interface with
402 * @param configMarker Marker for retrieving configuration information from Comparator backend
403 */
404
405 public CellCycleTransformView (Compare compare, String configMarker) {
406 super (compare, configMarker);
407 setSelectionGroup (CellCycleExperimentView.SELECTIONGROUP_CELLCYCLE);
408 context = new TransformContext ();
409 if (!compare.addResource (TRANSFORMCONTEXT_CELLCYCLE, context))
410 context = (ITransformContext) compare.getResource (TRANSFORMCONTEXT_CELLCYCLE);
411 errorViewer = new EvaluationErrorViewer (compare, this);
412 errorViewer.add (context);
413 }
414
415 /**
416 * {@inheritDoc}
417 */
418
419 public void addRow () {
420 throw new UnsupportedOperationException ();
421 }
422
423 /**
424 * {@inheritDoc}
425 */
426
427 public void addRows (int count) {
428 throw new UnsupportedOperationException ();
429 }
430
431 /**
432 * {@inheritDoc}
433 */
434
435 public void clear () {
436 for (Iterator iterator = generators.iterator (); iterator.hasNext (); )
437 ((IEditableDataGenerator) iterator.next ()).setOption (ITransform.OPTION_TRANSFORM, null);
438 List list = (List) compare.getResourceMap (ITransform.RESOURCE_TRANSFORMS).get (this);
439 if (list != null)
440 list.clear ();
441 model.fireTableDataChanged ();
442 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
443 compare.firePropertyChange (ITransform.RESOURCE_TRANSFORMS);
444 }
445
446 /**
447 * {@inheritDoc}
448 */
449
450 public void clipboardCut () {
451 throw new UnsupportedOperationException ();
452 }
453
454 /**
455 * {@inheritDoc}
456 */
457
458 public void clipboardPaste () {
459 throw new UnsupportedOperationException ();
460 }
461
462 /**
463 * {@inheritDoc}
464 */
465
466 public IConfigEditor createConfigEditor () {
467 IConfigEditor editor = new ConfigEditor (compare, this, configMarkers, getConfigForView ());
468 editor.addOption (CONFIG_TABNAME, "Name", String.class);
469 editor.addOption (CONFIG_RECENTSOURCECOUNT, "File History Size", Integer.class);
470 editor.addOption (CONFIG_PLOTTER, "Plotter", Class.class);
471 editor.addOption (CONFIG_TEXTCUTOFF, "Text Display Cutoff", Integer.class);
472 editor.addOption (BasicTable.BasicRenderer.CONFIG_BACKGROUNDEDITABLE, "Editable Cell Background Color", Color.class);
473 editor.addOption (BasicTable.BasicRenderer.CONFIG_BACKGROUNDUNEDITABLE, "Uneditable Cell Background Color", Color.class);
474 editor.addOption (BasicTable.BasicEditor.CONFIG_FOREGROUNDMODIFIED, "Modified Cell Foreground Color", Color.class);
475 editor.addOption (CellCycleExperimentView.CONFIG_BACKGROUNDTYPEERROR, "Type Error Background Color", Color.class);
476 return editor;
477 }
478
479 /**
480 * {@inheritDoc}
481 */
482
483 public void deleteRow (int row) {
484 ((IEditableDataGenerator) generators.get (row)).setOption (ITransform.OPTION_TRANSFORM, null);
485 model.fireTableDataChanged ();
486 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
487 }
488
489 /**
490 * {@inheritDoc}
491 */
492
493 public void deleteRows (int rows []) {
494 if (rows.length == 0)
495 return;
496 Arrays.sort (rows);
497 for (int i = rows.length - 1; i >= 0; i--)
498 ((IEditableDataGenerator) generators.get (rows [i])).setOption (ITransform.OPTION_TRANSFORM, null);
499 model.fireTableDataChanged ();
500 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
501 }
502
503 /**
504 * {@inheritDoc}
505 */
506
507 public void evaluate () {
508 evaluate (generators.toArray ());
509 }
510
511 /**
512 * {@inheritDoc}
513 */
514
515 public void evaluate (int rows []) {
516 int l = rows.length;
517 IDataGenerator tasks [] = new IDataGenerator [l];
518 for (int i = 0; i < l; i++)
519 tasks [i] = (IDataGenerator) generators.get (rows [i]);
520 evaluate (tasks);
521 }
522
523 /**
524 * {@inheritDoc}
525 */
526
527 public void insertRow (int row) {
528 throw new UnsupportedOperationException ();
529 }
530
531 /**
532 * {@inheritDoc}
533 */
534
535 public void insertRows (int row, int count) {
536 throw new UnsupportedOperationException ();
537 }
538
539 /**
540 * {@inheritDoc}
541 */
542
543 public void moveRowsDown (int rows []) {
544 throw new UnsupportedOperationException ();
545 }
546
547 /**
548 * {@inheritDoc}
549 */
550
551 public void moveRowsUp (int rows []) {
552 throw new UnsupportedOperationException ();
553 }
554
555 /**
556 * {@inheritDoc}
557 */
558
559 public IDataGenerator processGenerator (IDataGenerator generator) {
560 ITransform transform = Transform.getTransformForGenerator (generator);
561 if (transform == null)
562 return null;
563 Sync sync = transform.getEvaluationLock ();
564 if (!Compare.attemptSync (sync))
565 return null;
566 try {
567 transform.setEvaluationContext (context);
568 transform.addOption (DataGeneratorEvaluator.OPTION_EVALUATIONNAME, IDataGenerator.Option.COPYONLY);
569 transform.setOption (DataGeneratorEvaluator.OPTION_EVALUATIONNAME, generator.getName ());
570 transform.addOption (DataGeneratorEvaluator.OPTION_EVALUATIONTARGET, IDataGenerator.Option.COPYONLY);
571 transform.setOption (DataGeneratorEvaluator.OPTION_EVALUATIONTARGET, generator);
572 } finally {
573 sync.release ();
574 }
575 return transform;
576 }
577
578 public void propertyChange (PropertyChangeEvent e) {
579 String name = e.getPropertyName ();
580 if (IDataGenerator.RESOURCE_GENERATORS.equals (name)) {
581 generators.clear ();
582 generators.addAll (createGenerators ());
583 model.fireTableDataChanged ();
584 } else if (IDataGenerator.PROPERTY_GENERATOR_EDIT.equals (name))
585 model.fireTableDataChanged ();
586 else if (ITransform.RESOURCE_TRANSFORMS.equals (name) || ITransform.PROPERTY_TRANSFORM_EDIT.equals (name)) {
587 transforms.clear ();
588 transforms.addAll (createTransforms ());
589 transforms.sort (DataGenerator.COMPARATOR_NAME);
590 transformModel.replaceAll (transforms.asList ());
591 for (Iterator iterator = transforms.iterator (); iterator.hasNext (); ) {
592 ITransform transform = (ITransform) iterator.next ();
593 if (transform.getEvaluationContext () != context)
594 transform.setEvaluationContext (context);
595 }
596 model.fireTableDataChanged ();
597 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
598 } else if (DataGeneratorEvaluator.PROPERTY_EVALUATIONUPDATE.equals (name))
599 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
600 else if (DataGeneratorEvaluator.PROPERTY_EVALUATIONFINISHED.equals (name))
601 ((DataGeneratorEvaluator) e.getSource ()).removePropertyChangeListener (this);
602 else
603 super.propertyChange (e);
604 }
605
606 /**
607 * {@inheritDoc}
608 */
609
610 public void readConfiguration (String state) {
611 super.readConfiguration (state);
612 if (state == STATE_INITIALIZE)
613 JigCellRunManagerTransform.initializeSimulators (compare.getConfig ());
614 }
615
616 /**
617 * {@inheritDoc}
618 */
619
620 public void reset () {
621 for (Iterator iterator = generators.iterator (); iterator.hasNext (); )
622 flushTransform (Transform.getTransformForGenerator ((IDataGenerator) iterator.next ()));
623 model.fireTableDataChanged ();
624 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
625 }
626
627 /**
628 * {@inheritDoc}
629 */
630
631 public void reset (int rows []) {
632 int l = rows.length;
633 if (l == 0)
634 return;
635 for (int i = 0; i < l; i++)
636 flushTransform (getTransformForGenerator (rows [i]));
637 model.fireTableDataChanged ();
638 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
639 }
640
641 /**
642 * {@inheritDoc}
643 */
644
645 public void saveResults (IWriteableDataSource source) {
646 if (source instanceof FileDataSource) {
647 FileDataSource fileSource = (FileDataSource) source;
648 fileSource.setExceptionListenerOption (exception);
649 fileSource.setFileChooserOption (createFileChooserResults ());
650 fileSource.setFileChooserSelectOption (OPTION_CHOOSERSAVE);
651 }
652 try {
653 if (!source.configure ())
654 return;
655 saveResultsDirect (source);
656 } catch (Exception e) {
657 compare.shellHandleException (Compare.MESSAGE_ERROR, MESSAGE_SAVEERROR + e.getMessage (), e);
658 }
659 }
660
661 /**
662 * {@inheritDoc}
663 */
664
665 public void saveResultsDirect (IWriteableDataSource source) {
666 try {
667 writeResults (source);
668 } catch (Exception e) {
669 compare.shellHandleException (Compare.MESSAGE_ERROR, MESSAGE_SAVEERROR + e.getMessage (), e);
670 } finally {
671 if (source instanceof IMultipleDataSource)
672 ((IMultipleDataSource) source).finish ();
673 }
674 }
675
676 /**
677 * {@inheritDoc}
678 */
679
680 protected JFileChooser createFileChooser () {
681 return InterfaceBuilder.createFileChooser (FILTER_TRANSFORM);
682 }
683
684 /**
685 * A file chooser specialized for the view results.
686 */
687
688 protected JFileChooser createFileChooserResults () {
689 return InterfaceBuilder.createFileChooser (FILTER_TRANSFORMRESULT);
690 }
691
692 /**
693 * {@inheritDoc}
694 */
695
696 protected IDataGeneratorList createGenerators () {
697 return DataGeneratorList.createList (compare.scanResourceCatalog (IDataGenerator.RESOURCE_GENERATORS));
698 }
699
700 /**
701 * A list of transforms for the view.
702 */
703
704 protected List createTransforms () {
705 return compare.scanResourceCatalog (ITransform.RESOURCE_TRANSFORMS);
706 }
707
708 /**
709 * {@inheritDoc}
710 */
711
712 protected void createUI () {
713 createUI (new TransformModel ());
714 }
715
716 /**
717 * @see jigcell.compare.views.BasicTableView#createUI(jigcell.compare.ui.BasicTable.BasicTableModel)
718 */
719
720 protected void createUI (TransformModel model) {
721 super.createUI (model);
722 this.model = model;
723 transformModel = new ListComboBoxModel (transforms.asList ());
724 TableColumnModel columnModel = table.getColumnModel ();
725 columnModel.getColumn (table.findColumn (model.COLUMN_TRANSFORM)).setCellEditor (new BasicTable.BasicEditor (this,
726 new JComboBox (transformModel)));
727 columnModel.getColumn (table.findColumn (model.COLUMN_TYPE)).setCellRenderer (new TransformViewRenderer ());
728 }
729
730 /**
731 * Evaluates a collection of data generators on a separate thread.
732 *
733 * @param generators Data generators to evaluate
734 */
735
736 protected void evaluate (IDataGenerator generators []) {
737 ProgressMonitor progress = new ProgressMonitor (compare.getDisplayFrame (), "Not started", 0, generators.length);
738 DataGeneratorEvaluator evaluator = new DataGeneratorEvaluator (generators, this);
739 evaluator.addPropertyChangeListener (this);
740 evaluator.addPropertyChangeListener (progress);
741 progress.addPropertyChangeListener (evaluator);
742 evaluator.execute ();
743 }
744
745 /**
746 * The transform of a generator.
747 *
748 * @param index Index of generator in generator list
749 */
750
751 protected ITransform getTransformForGenerator (int index) {
752 return Transform.getTransformForGenerator ((IDataGenerator) generators.get (index));
753 }
754
755 /**
756 * {@inheritDoc}
757 */
758
759 protected void initializeData () {
760 generators = createGenerators ();
761 transforms = new DataGeneratorList ();
762 }
763
764 /**
765 * {@inheritDoc}
766 */
767
768 protected void readInternal (Object readResult) throws Exception {
769 Iterator iterator = DataGeneratorMap.createMap (readResult).iterator ();
770 transforms.clear ();
771 HashSet used = new HashSet ();
772 generators.createIndex ();
773 try {
774 while (iterator.hasNext ())
775 try {
776 Map.Entry entry = (Map.Entry) iterator.next ();
777 ITransform transform = (ITransform) entry.getValue ();
778 ITransform original = transform.isCopy () ? (ITransform) transform.getCopiedFrom () : transform;
779 if (used.add (original))
780 transforms.add (original);
781 IDataGeneratorCollection.Key key = (IDataGeneratorCollection.Key) entry.getKey ();
782 IDataGenerator target = generators.get (key);
783 if (target == null) {
784 compare.shellHandleException (Compare.MESSAGE_WARNING, MESSAGE_TARGETNOTFOUNDERROR + key);
785 continue;
786 }
787 target.addOption (ITransform.OPTION_TRANSFORM, IDataGenerator.Option.COPYONLY);
788 target.setOption (ITransform.OPTION_TRANSFORM, original);
789 } catch (Exception e) {
790 compare.shellHandleException (Compare.MESSAGE_WARNING, MESSAGE_LOADDATAERROR + e.getMessage (), e);
791 }
792 } finally {
793 generators.flushIndex ();
794 }
795 compare.updateResourceMap (ITransform.RESOURCE_TRANSFORMS, this, ((IDataGeneratorList) transforms.clone ()).asList ());
796 compare.firePropertyChange (ITransform.RESOURCE_TRANSFORMS);
797 }
798
799 /**
800 * {@inheritDoc}
801 */
802
803 protected void readNotify () {
804 model.fireTableDataChanged ();
805 compare.firePropertyChange (IDataGenerator.PROPERTY_GENERATOR_EDIT);
806 }
807
808 /**
809 * {@inheritDoc}
810 */
811
812 protected void write (IWriteableDataSource source) throws Exception {
813 IDataGeneratorMap map = new DataGeneratorMap (1 + (transforms.size () << 2), 1);
814 for (Iterator iterator = generators.iterator (); iterator.hasNext (); ) {
815 IDataGenerator generator = (IDataGenerator) iterator.next ();
816 ITransform transform = Transform.getTransformForGenerator (generator);
817 if (transform != null)
818 map.put (generator.getName (), generator.getAttribute (IDataGenerator.ATTRIBUTE_GUID), transform);
819 }
820 source.write (map);
821 }
822
823 /**
824 * Writes results data to some external source.
825 *
826 * @param source Data source to write to
827 */
828
829 protected void writeResults (IWriteableDataSource source) throws Exception {
830 Map map = new LinkedHashMap (1 + (transforms.size () << 2), 1);
831 for (Iterator iterator = generators.iterator (); iterator.hasNext (); ) {
832 IDataGenerator generator = (IDataGenerator) iterator.next ();
833 ITransform transform = Transform.getTransformForGenerator (generator);
834 if (transform != null && transform.isCached ())
835 map.put (generator.getName (), String.valueOf (transform.getElement ()));
836 }
837 source.write (map);
838 }
839 }