Changeset 364


Ignore:
Timestamp:
Apr 10, 2012, 6:54:03 PM (5 years ago)
Author:
tim.te.beek@…
Message:

Transfer some change listeners to ParserSettingsModel? instead of ParsingTableModel?
Add initial implementation of assimilate() in PTM
Alter when what events are fired from parseFile
Update SaveableSettings? implementation to take an ParserSettingsModel? as argument
For persistence use ParsingTableModel? as argument rather than ParserSettingsModel?
Re-enable persistence tests

Location:
branches/alttableimport-model-rewrite
Files:
1 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • branches/alttableimport-model-rewrite/pom.xml

    r321 r364  
    3333                        <scope>provided</scope>
    3434                </dependency>
     35                <dependency>
     36                        <groupId>commons-lang</groupId>
     37                        <artifactId>commons-lang</artifactId>
     38                        <version>2.4</version>
     39                </dependency>           
    3540       
    3641                <!-- Actual packaged dependencies -->
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/AlternativeTableImportPlugin.java

    r360 r364  
    2020import cytoscape.view.CyHelpBroker;
    2121
    22 import nl.nbic.brs.alttableimport.models.ParserSettingsModel;
     22import nl.nbic.brs.alttableimport.models.ParsingTableModel;
     23import nl.nbic.brs.alttableimport.persistence.SaveableSettings;
    2324import nl.nbic.brs.alttableimport.persistence.SettingsPersistence;
    2425import nl.nbic.brs.alttableimport.views.TableImportDialog;
     
    7273                                                        if (profile != null && profile.canRead() && 0 < profile.length())
    7374                                                                try {
    74                                                                         ParserSettingsModel settings = SettingsPersistence.loadSettings(profile);
     75                                                                        SaveableSettings loadedSettings = SettingsPersistence.loadSettings(profile);
    7576                                                                        // But only if we can read whatever file was used last:
    7677                                                                        // we don't want to open the dialog with an error
    77                                                                         if (settings.getTableFile().canRead()) {
    78                                                                                 ;// TODO tableImportDialog.replaceSettings(settings);
     78                                                                        if (loadedSettings.getTableFile().canRead()) {
     79                                                                                tableImportDialog.getTableModel().assimilate(loadedSettings);
    7980
    8081                                                                                // Show LoggerDialog if any warnings were logged in setting the previous profile
     
    122123                // Save current settings to a plugin specific settings file
    123124                File profile = CytoscapeInit.getConfigFile(SETTINGS_PROFILE);
    124                 ParserSettingsModel settings = tableImportDialog.getSettings();
     125                ParsingTableModel tableModel = tableImportDialog.getTableModel();
    125126                try {
    126                         SettingsPersistence.saveSettings(profile, settings);
     127                        SettingsPersistence.saveSettings(profile, tableModel);
    127128                }
    128129                catch (IOException e) {
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/NetworkCreator.java

    r360 r364  
    3434         */
    3535        public static CyNetwork createNetwork(final ParserSettingsModel settings) throws IOException {
     36                // Parse file
    3637                ParsingTableModel tableModel = new ParsingTableModel(settings);
    37                 // Parse file
    38                 tableModel.parseTableFile();
    3938
    4039                // Create a new network named after the originating file
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/models/ParserSettingsModel.java

    r360 r364  
    11package nl.nbic.brs.alttableimport.models;
    22
     3import java.awt.event.ItemEvent;
     4import java.awt.event.ItemListener;
    35import java.io.File;
    46import java.util.ArrayList;
     
    1214import javax.swing.event.ChangeEvent;
    1315import javax.swing.event.ChangeListener;
     16import javax.swing.event.TableModelEvent;
     17import javax.swing.table.AbstractTableModel;
    1418
    1519import lombok.Getter;
     
    2428 */
    2529@Getter
    26 public class ParserSettingsModel {
     30public class ParserSettingsModel implements ChangeListener, ItemListener {
    2731        private File                                                    tableFile                       = null;
    2832        private SimplePlainDocument                             networkName                     = new SimplePlainDocument();
     
    5256                firstRowHeader.setSelected(true);
    5357                guessDataTypes.setSelected(true);
    54         }
    55 
    56         /**
    57          * Previously selected interactions, attributes and interpretations should be reset.
     58
     59                // Add ourself as listener to models to in turn notify our own listeners through a single unified interface
     60
     61                // Whenever the first line to parse or the number of lines to parse updates, we should reset rows & columnNames
     62                startFrom.addChangeListener(this);
     63                linesToParse.addChangeListener(this);
     64                // Whenever comment character changes, we should reset rows & columnNames
     65                comment.addDocumentListener(new DocumentListenerToChangableAdapter(this));
     66
     67                // Whenever guessing of datatypes or first row as header are toggled, we should reset rows & columnNames
     68                firstRowHeader.addItemListener(this);
     69                guessDataTypes.addItemListener(this);
     70                // When the delimiter changes, we reset rows & columnNames
     71                delimiter.addItemListener(this);
     72        }
     73
     74        /**
     75         * Listen for startFrom, linesToParse and comment events.
     76         */
     77        @Override
     78        public void itemStateChanged(final ItemEvent e) {
     79                fireSettingsChanged();
     80        }
     81
     82        /**
     83         * Listen for firstRowHeader, guessDataTypes & delimiter events.
     84         */
     85        @Override
     86        public void stateChanged(final ChangeEvent e) {
     87                fireSettingsChanged();
     88        }
     89
     90        List<ChangeListener>    listeners       = new ArrayList<ChangeListener>();
     91
     92        public void addChangeListener(final ChangeListener listener) {
     93                listeners.add(listener);
     94        }
     95
     96        public void removeChangeListener(final ChangeListener listener) {
     97                listeners.remove(listener);
     98        }
     99
     100        /**
     101         * {@code true} if the selection is undergoing a series of changes.
     102         */
     103        private volatile boolean        valueAdjusting;
     104
     105        /**
     106         * Calls {@link AbstractTableModel#fireTableChanged(TableModelEvent)} only if #valueAdjusting is false.<BR/>
     107         * <BR/>
     108         * This allows us to temporarily prevent listener notification while we are adjusting a lot of settings in one go.
     109         */
     110        private void fireSettingsChanged() {
     111                if (valueAdjusting)
     112                        return;
     113
     114                ChangeEvent changeEvent = new ChangeEvent(this);
     115                for (ChangeListener listener : listeners)
     116                        listener.stateChanged(changeEvent);
     117        }
     118
     119        /**
     120         * Set {@link #valueAdjusting} to argument. NOOP if {@link #valueAdjusting} value matches argument.
     121         * If argument is false {@link #fireTableStructureChanged()} is called to notify listeners.
     122         *
     123         * @param _valueAdjusting
     124         */
     125        protected void setValueAdjusting(final boolean _valueAdjusting) {
     126                if (valueAdjusting == _valueAdjusting)
     127                        return;
     128                valueAdjusting = _valueAdjusting;
     129                if (!valueAdjusting)
     130                        // Notify listeners now that we've completed changes
     131                        fireSettingsChanged();
     132        }
     133
     134        // ----- Interpretation handling
     135
     136        /**
     137         * Mark columnIndex for interpretation as clazz, using new Clazz(String value) constructor when retrieving values.
     138         *
     139         * @param columnIndex
     140         * @param clazz
     141         */
     142        public void addInterpretation(final Integer columnIndex, final Class<?> clazz) {
     143                // XXX Use the return values of remove & put rather than checking preconditions
     144                if (clazz == String.class) {
     145                        // String is the default: Remove current interpretation from map
     146                        interpretation.remove(columnIndex);
     147                        fireSettingsChanged();
     148                        return;
     149                }
     150
     151                // Assert clazz is of a valid type for Cytoscape attributes
     152                if (clazz != Double.class && clazz != Integer.class && clazz != Boolean.class)
     153                        throw new IllegalArgumentException(clazz.getCanonicalName());
     154
     155                // Put interpretation only if it changes things
     156                if (interpretation.get(columnIndex) != clazz) {
     157                        interpretation.put(columnIndex, clazz);
     158                        fireSettingsChanged();
     159                }
     160        }
     161
     162        /**
     163         * Method to retrieve interpretation for a certain column.
     164         *
     165         * @param columnIndex
     166         * @return class used to interpret columnIndex (String by default)
     167         */
     168        public Class<?> getInterpretation(final int columnIndex) {
     169                if (interpretation.containsKey(columnIndex))
     170                        return interpretation.get(columnIndex);
     171                return String.class;
     172        }
     173
     174        /**
     175         * Discourage anyone from using this map directly, as we need the fireSettingsChanged to trigger through the
     176         * addInterpretation method.
     177         *
     178         * @return mapping of column indices to their Class interpretations
     179         */
     180        @Deprecated
     181        public Map<Integer, Class<?>> getInterpretation() {
     182                return interpretation;
     183        }
     184
     185        // ----- Table file handling
     186
     187        /**
     188         * Setter for table file that also resets interactions, attributes and interpretations and also notifies listeners.
    58189         *
    59190         * @param tableFile
    60191         */
    61         private void resetSettings() {
     192        public void setTableFile(final File tableFile) {
     193                if (this.tableFile == tableFile)
     194                        return;
     195                this.tableFile = tableFile;
     196
     197                // Batch events triggered by the below event by temporarily disabling listener notification
     198                setValueAdjusting(true);
     199                resetSettings();
     200                // Notify listeners now that we're done changing settings
     201                setValueAdjusting(false);
     202        }
     203
     204        /**
     205         * Previously selected interactions, attributes and interpretations should be reset when a new file is loaded.
     206         *
     207         * @param tableFile
     208         */
     209        protected void resetSettings() {
    62210                // Initialize networkName to the name of the imported file, if available
    63211                if (tableFile != null)
    64212                        networkName.setText(tableFile.getName());
     213
    65214                // Reset interactions, attributes and interpretations: These are unlikely to carry over between files
    66215                sourceInteraction.setSelectedItem(null);
     
    73222        }
    74223
    75         // Listener instances should remain private to this instance, and should not be accessible to the JSON serialization
    76         List<ChangeListener>    listeners       = new ArrayList<ChangeListener>();
    77 
    78         public void addChangeListener(final ChangeListener listener) {
    79                 listeners.add(listener);
    80         }
    81 
    82         public void removeChangeListener(final ChangeListener listener) {
    83                 listeners.remove(listener);
    84         }
    85 
    86         private void fireSettingsChanged() {
    87                 ChangeEvent changeEvent = new ChangeEvent(this);
    88                 for (ChangeListener listener : listeners)
    89                         listener.stateChanged(changeEvent);
    90         }
    91 
    92         /**
    93          * Mark columnIndex for interpretation as clazz, using new Clazz(String value) constructor when retrieving values.
    94          *
    95          * @param columnIndex
    96          * @param clazz
    97          */
    98         public void addInterpretation(final Integer columnIndex, final Class<?> clazz) {
    99                 if (clazz == String.class) {
    100                         // String is the default: Remove current interpretation from map
    101                         interpretation.remove(columnIndex);
    102                         fireSettingsChanged();
    103                         return;
    104                 }
    105 
    106                 // Assert clazz is of a valid type for Cytoscape attributes
    107                 if (clazz != Double.class && clazz != Integer.class && clazz != Boolean.class)
    108                         throw new IllegalArgumentException(clazz.getCanonicalName());
    109 
    110                 // Put interpretation only if it changes things
    111                 if (interpretation.get(columnIndex) != clazz) {
    112                         interpretation.put(columnIndex, clazz);
    113                         fireSettingsChanged();
    114                 }
    115         }
    116 
    117         /**
    118          * Method to retrieve interpretation for a certain column.
    119          *
    120          * @param columnIndex
    121          * @return class used to interpret columnIndex (String by default)
    122          */
    123         public Class<?> getInterpretation(final int columnIndex) {
    124                 if (interpretation.containsKey(columnIndex))
    125                         return interpretation.get(columnIndex);
    126                 return String.class;
    127         }
    128 
    129         /**
    130          * Discourage anyone from using this map directly, as we need the fireSettingsChanged to trigger through the
    131          * addInterpretation method.
    132          *
    133          * @return mapping of column indices to their Class interpretations
    134          */
    135         @Deprecated
    136         public Map<Integer, Class<?>> getInterpretation() {
    137                 return interpretation;
    138         }
    139 
    140         // ---- Setters that call fireSettingsChanged when changed
    141 
    142         public void setTableFile(final File tableFile) {
    143                 if (this.tableFile == tableFile)
    144                         return;
    145                 this.tableFile = tableFile;
    146                 resetSettings();
    147                 fireSettingsChanged();
    148         }
    149 
    150224        class GuessDatatypesModel extends ToggleButtonModel {
    151225                @Override
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/models/ParsingTableModel.java

    r361 r364  
    1010import java.util.ArrayList;
    1111import java.util.Arrays;
     12import java.util.Collection;
    1213import java.util.Iterator;
    1314import java.util.List;
    1415import java.util.Map;
     16import java.util.TreeSet;
    1517import java.util.regex.Pattern;
    1618
     
    1820import javax.swing.event.ChangeEvent;
    1921import javax.swing.event.ChangeListener;
     22import javax.swing.event.ListDataEvent;
     23import javax.swing.event.ListDataListener;
    2024import javax.swing.table.AbstractTableModel;
    2125
    2226import lombok.Getter;
     27
     28import org.apache.commons.lang.ArrayUtils;
     29
    2330import au.com.bytecode.opencsv.CSVParser;
    2431import au.com.bytecode.opencsv.CSVReader;
     
    3239 * A TableModel that parses an underlying data file using a ParserSettingsModel instance to provide table contents.
    3340 */
    34 public class ParsingTableModel extends AbstractTableModel implements ChangeListener, ItemListener {
     41public class ParsingTableModel extends AbstractTableModel implements ChangeListener {
    3542        @Getter
    36         private ParserSettingsModel                     settings;
     43        private ParserSettingsModel                     settings                = new ParserSettingsModel();
    3744
    3845        private String[]                                        columnNames             = null;
     
    4552        private TableColumnSelectionModel       selectionModel  = new TableColumnSelectionModel();
    4653
    47         public ParsingTableModel(final ParserSettingsModel settings) {
    48                 this.settings = settings;
    49 
     54        public ParsingTableModel() {
    5055                registerListeners();
    5156        }
    5257
    53         public void assimilate(final SaveableSettings saveableSettings) {
    54                 // TODO Auto-generated method stub
    55 
     58        /**
     59         * Only intended to be used from NetworkCreator
     60         *
     61         * @param _settings
     62         * @throws IOException
     63         */
     64        public ParsingTableModel(final ParserSettingsModel _settings) throws IOException {
     65                settings = _settings;
     66                parseTableFile();
     67                registerListeners();
    5668        }
    5769
     
    6072                settings.addChangeListener(this);
    6173
    62                 // Whenever the first line to parse or the number of lines to parse updates, we should reset rows & columnNames
    63                 settings.getStartFrom().addChangeListener(this);
    64                 settings.getLinesToParse().addChangeListener(this);
    65 
    66                 // Whenever guessing of datatypes or first row as header are toggled, we should reset rows & columnNames
    67                 settings.getFirstRowHeader().addItemListener(this);
    68                 settings.getGuessDataTypes().addItemListener(this);
    69                 // When the delimiter changes, we reset rows & columnNames
    70                 settings.getDelimiter().addItemListener(this);
     74                // Some events in settings do not require a reparse of tableFile, but only a UI refresh. This handler does that
     75                PassAlongEventHandler passAlongHandler = new PassAlongEventHandler() {
     76                        @Override
     77                        void handleEvent() {
     78                                // FIXME we were triggering tableEvents in response to table events: That's a nice way to blow the stack
     79                                // fireTableStructureChanged();
     80                        }
     81                };
    7182
    7283                // Whenever interactions change, we should notify our own listeners to update preview table colors
    73                 settings.getSourceInteraction().addItemListener(this);
    74                 settings.getEdgeInteraction().addItemListener(this);
    75                 settings.getTargetInteraction().addItemListener(this);
     84                settings.getSourceInteraction().addItemListener(passAlongHandler);
     85                settings.getEdgeInteraction().addItemListener(passAlongHandler);
     86                settings.getTargetInteraction().addItemListener(passAlongHandler);
     87
    7688                // Whenever additional attributes change, colors of columns in table preview should refresh
    77                 settings.getSourceAttributes().addListDataListener(new ListDataListenerToChangableAdapter(this));
    78                 settings.getEdgeAttributes().addListDataListener(new ListDataListenerToChangableAdapter(this));
    79                 settings.getTargetAttributes().addListDataListener(new ListDataListenerToChangableAdapter(this));
    80 
    81                 // Whenever comment character changes, we should reset rows & columnNames
    82                 settings.getComment().addDocumentListener(new DocumentListenerToChangableAdapter(this));
     89                settings.getSourceAttributes().addListDataListener(passAlongHandler);
     90                settings.getEdgeAttributes().addListDataListener(passAlongHandler);
     91                settings.getTargetAttributes().addListDataListener(passAlongHandler);
    8392
    8493                // When the number of columns or the column names change, the interaction comboboxes should be updated
     
    92101        }
    93102
     103        @SuppressWarnings("unused")
     104        // TODO remove suppressing of warnings
     105        public void assimilate(final SaveableSettings saveableSettings) throws IOException {
     106                // We're going to change a lot of values, but do not want to notify listeners for each individual change
     107                settings.setValueAdjusting(true);
     108
     109                // Clear interactions, attributes & interpretations
     110                settings.resetSettings();
     111
     112                // Transfer values
     113                settings.setTableFile(saveableSettings.getTableFile());
     114                settings.getNetworkName().setText(saveableSettings.getNetworkName());
     115
     116                settings.getDelimiter().setCharacter(saveableSettings.getDelimiter());
     117                settings.getComment().setCharacter(saveableSettings.getComment());
     118                settings.getStartFrom().setValue(saveableSettings.getStartFrom());
     119                settings.getLinesToParse().setValue(saveableSettings.getLinesToParse());
     120                settings.getFirstRowHeader().setSelected(saveableSettings.isFirstRowHeader());
     121                settings.getGuessDataTypes().setSelected(saveableSettings.isGuessDataTypes());
     122
     123                // Parse tableFile for the first time, to get the columnNames for conversion of column names to column indices
     124                parseTableFile();
     125
     126                // For interaction, attributes and interpretation: Convert column indices to column names to prevent shifting
     127                // XXX ColumnName lookup can not handle duplicate column names well, so update help documentation to reflect
     128                CyLogger logger = CyLogger.getLogger(AlternativeTableImportPlugin.class);
     129
     130                // Interactions
     131                String sourceInteractionName = saveableSettings.getSourceInteraction();
     132                int sourceIntIndex = ArrayUtils.indexOf(columnNames, sourceInteractionName);
     133                settings.getSourceInteraction().setSelectedItem(sourceIntIndex == ArrayUtils.INDEX_NOT_FOUND ? null : sourceIntIndex);
     134
     135                String edgeInteractionName = saveableSettings.getSourceInteraction();
     136                int edgeIntIndex = ArrayUtils.indexOf(columnNames, sourceInteractionName);
     137                settings.getEdgeInteraction().setSelectedItem(edgeIntIndex == ArrayUtils.INDEX_NOT_FOUND ? null : edgeIntIndex);
     138
     139                String targetInteractionName = saveableSettings.getSourceInteraction();
     140                int targetIntIndex = ArrayUtils.indexOf(columnNames, sourceInteractionName);
     141                settings.getTargetInteraction().setSelectedItem(targetIntIndex == ArrayUtils.INDEX_NOT_FOUND ? null : targetIntIndex);
     142
     143                // Additional attributes
     144                Collection<Integer> sourceAttributeIndices = new TreeSet<Integer>();
     145                for (String columnName : saveableSettings.getSourceAttributes()) {
     146                        int columnIndex = ArrayUtils.indexOf(columnNames, columnName);
     147                        if (columnIndex != ArrayUtils.INDEX_NOT_FOUND)
     148                                sourceAttributeIndices.add(columnIndex);
     149                        else
     150                                logger.warn("Could not find Additional Source attribute " + columnName);
     151                }
     152                settings.getSourceAttributes().addAll(sourceAttributeIndices);
     153
     154                Collection<Integer> edgeAttributeIndices = new TreeSet<Integer>();
     155                for (String columnName : saveableSettings.getEdgeAttributes()) {
     156                        int columnIndex = ArrayUtils.indexOf(columnNames, columnName);
     157                        if (columnIndex != ArrayUtils.INDEX_NOT_FOUND)
     158                                edgeAttributeIndices.add(columnIndex);
     159                        else
     160                                logger.warn("Could not find Additional Edge attribute " + columnName);
     161                }
     162                settings.getEdgeAttributes().addAll(edgeAttributeIndices);
     163
     164                Collection<Integer> targetAttributeIndices = new TreeSet<Integer>();
     165                for (String columnName : saveableSettings.getTargetAttributes()) {
     166                        int columnIndex = ArrayUtils.indexOf(columnNames, columnName);
     167                        if (columnIndex != ArrayUtils.INDEX_NOT_FOUND)
     168                                targetAttributeIndices.add(columnIndex);
     169                        else
     170                                logger.warn("Could not find Additional Target attribute " + columnName);
     171                }
     172                settings.getTargetAttributes().addAll(targetAttributeIndices);
     173
     174                // TODO Interpretation
     175                Map<String, Class<?>> namedInterpretations = saveableSettings.getInterpretation();
     176                @SuppressWarnings("deprecation")
     177                Map<Integer, Class<?>> indexInterpretations = settings.getInterpretation();
     178
     179                // We're done changing settings: Notify listeners
     180                settings.setValueAdjusting(false);
     181        }
     182
    94183        /**
    95          * Listen for changes in startFrom and linesToParse, comment document and additional attributes (through adapters).
     184         * Listen for any change in settings.
    96185         */
    97186        @Override
     
    101190
    102191        /**
    103          * Listen for changes to firstRowAsHeader, guessDatatypes and interactions.
     192         * Should only be called from EDT, as it shows a pop-up when any errors occur.
    104193         */
    105         @Override
    106         public void itemStateChanged(final ItemEvent e) {
    107                 anyEventHandler();
    108         }
    109 
    110         public void anyEventHandler() {
     194        private void anyEventHandler() {
    111195                try {
    112196                        // XXX File parsing still happens on EDT
     
    124208
    125209        public void parseTableFile() throws IOException {
     210                // TODO Remove printing when parsing a file
     211                System.out.println("Parsing: " + settings.getTableFile());
     212
    126213                // Save previous columnNames, so we can see if they changed and propagate accordingly
    127214                String[] previousColumnNames = columnNames;
     
    245332                        // Our underlying data structure changed: Notify listeners
    246333                        fireTableStructureChanged();
    247                         fireTableDataChanged();
    248334
    249335                        // Rethrow exception: Let the caller handle it
     
    293379                        fireTableStructureChanged();
    294380                }
    295                 // Regardless of whether the columns changed, the data will have changed
    296                 fireTableDataChanged();
     381                else
     382                        // Regardless of whether the columns changed, the data will have changed
     383                        fireTableDataChanged();
    297384        }
    298385
     
    318405        @Override
    319406        public Class<?> getColumnClass(final int columnIndex) {
    320                 if (settings.interpretation.containsKey(columnIndex))
    321                         return settings.interpretation.get(columnIndex);
     407                @SuppressWarnings("deprecation")
     408                Map<Integer, Class<?>> interpretation = settings.getInterpretation();
     409                if (interpretation.containsKey(columnIndex))
     410                        return interpretation.get(columnIndex);
    322411                return String.class;
    323412        }
     
    383472        }
    384473}
     474
     475abstract class PassAlongEventHandler implements ItemListener, ListDataListener {
     476        abstract void handleEvent();
     477
     478        @Override
     479        public void intervalAdded(final ListDataEvent e) {
     480                handleEvent();
     481        }
     482
     483        @Override
     484        public void intervalRemoved(final ListDataEvent e) {
     485                handleEvent();
     486        }
     487
     488        @Override
     489        public void contentsChanged(final ListDataEvent e) {
     490                handleEvent();
     491        }
     492
     493        @Override
     494        public void itemStateChanged(final ItemEvent e) {
     495                handleEvent();
     496        }
     497}
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/persistence/SaveableSettings.java

    r360 r364  
    22
    33import java.io.File;
    4 import java.util.ArrayList;
    5 import java.util.List;
    64import java.util.Map;
     5import java.util.Map.Entry;
     6import java.util.Set;
    77import java.util.SortedSet;
    88import java.util.TreeMap;
    99import java.util.TreeSet;
    10 
    11 import javax.swing.event.ChangeEvent;
    12 import javax.swing.event.ChangeListener;
    1310
    1411import lombok.AccessLevel;
     
    1613import lombok.Setter;
    1714
    18 import org.codehaus.jackson.annotate.JsonIgnore;
    1915import org.codehaus.jackson.map.annotate.JsonSerialize;
    2016
     17import nl.nbic.brs.alttableimport.models.ParserSettingsModel;
     18import nl.nbic.brs.alttableimport.models.ParsingTableModel;
     19
    2120/**
    22  * Settings for parsing a structured text table file, and methods to alter these settings. Notifies listeners upon any
    23  * change that alters the way in which the text table file might be parsed.
    24  *
    25  * Includes some JSON serialization instructions.
     21 * A settings class that includes JSON serialization instructions used when persisting or loading values.
    2622 */
    2723@Data
    28 // We need our setters to fireSettingsChanged(), so do not generate them automatically
    2924@Setter(AccessLevel.NONE)
    3025@SuppressWarnings("unused")
    3126public class SaveableSettings implements Cloneable {
    3227        @JsonSerialize(as = File.class)
    33         private File                            tableFile                       = null;
    34         private String                          networkName;
     28        private File                                    tableFile;
     29        private String                                  networkName;
    3530
    36         private char                            delimiter                       = ',';
    37         private Character                       comment                         = null;
    38         private int                                     startFrom                       = 0;
    39         private int                                     linesToParse            = 30;
    40         private boolean                         firstRowHeader          = true;
    41         private boolean                         guessDataTypes          = true;
     31        private char                                    delimiter;
     32        private Character                               comment;
     33        private int                                             startFrom;
     34        private int                                             linesToParse;
     35        private boolean                                 firstRowHeader;
     36        private boolean                                 guessDataTypes;
    4237
    43         // Keep an index rather than name to handle firstRowHandle toggling
    44         private Integer                         sourceInteraction       = null;
    45         private Integer                         edgeInteraction         = null;
    46         private Integer                         targetInteraction       = null;
     38        // Store column names here to prevent shifting
     39        private String                                  sourceInteraction;
     40        private String                                  edgeInteraction;
     41        private String                                  targetInteraction;
    4742
    4843        // Lists with additional attributes per source node, target node or edge
    49         private SortedSet<Integer>      sourceAttributes        = new TreeSet<Integer>();
    50         private SortedSet<Integer>      edgeAttributes          = new TreeSet<Integer>();
    51         private SortedSet<Integer>      targetAttributes        = new TreeSet<Integer>();
     44        private SortedSet<String>               sourceAttributes        = new TreeSet<String>();
     45        private SortedSet<String>               edgeAttributes          = new TreeSet<String>();
     46        private SortedSet<String>               targetAttributes        = new TreeSet<String>();
    5247
    53         // Do not grant access to the underlying map, so we can restrict addition to addInterpretation & fireSettingsChanged
     48        // The datatypes for each of the columns, if not the standard String
    5449        @JsonSerialize
    55         Map<Integer, Class<?>>          interpretation          = new TreeMap<Integer, Class<?>>();
    56 
    57         // Listener instances should remain private to this instance, and should not be accessible to the JSON serialization
    58         @JsonIgnore
    59         List<ChangeListener>            listeners                       = new ArrayList<ChangeListener>();
    60 
    61         public void addChangeListener(final ChangeListener listener) {
    62                 listeners.add(listener);
    63         }
    64 
    65         public void removeChangeListener(final ChangeListener listener) {
    66                 listeners.remove(listener);
    67         }
    68 
    69         private void fireSettingsChanged() {
    70                 ChangeEvent changeEvent = new ChangeEvent(this);
    71                 ChangeListener[] safeArray = listeners.toArray(new ChangeListener[listeners.size()]);
    72                 for (ChangeListener listener : safeArray)
    73                         listener.stateChanged(changeEvent);
    74         }
     50        private Map<String, Class<?>>   interpretation          = new TreeMap<String, Class<?>>();
    7551
    7652        /**
    77          * Mark columnIndex for interpretation as clazz, using new Clazz(String value) constructor when retrieving values.
    78          *
    79          * @param columnIndex
    80          * @param clazz
     53         * Constructor only intended to be used by JSON serialization process.
    8154         */
    82         public void addInterpretation(final Integer columnIndex, final Class<?> clazz) {
    83                 if (clazz == String.class) {
    84                         // String is the default: Remove current interpretation from map
    85                         interpretation.remove(columnIndex);
    86                         fireSettingsChanged();
    87                         return;
    88                 }
     55        @Deprecated
     56        private SaveableSettings() {/* JSON Serialization only */}
    8957
    90                 // Assert clazz is of a valid type for Cytoscape attributes
    91                 if (clazz != Double.class && clazz != Integer.class && clazz != Boolean.class)
    92                         throw new IllegalArgumentException(clazz.getCanonicalName());
     58        public SaveableSettings(final ParsingTableModel parsingTableModel) {
     59                ParserSettingsModel settings = parsingTableModel.getSettings();
     60                tableFile = settings.getTableFile();
     61                networkName = settings.getNetworkName().getText();
    9362
    94                 // Put interpretation only if it changes things
    95                 if (interpretation.get(columnIndex) != clazz) {
    96                         interpretation.put(columnIndex, clazz);
    97                         fireSettingsChanged();
     63                delimiter = settings.getDelimiter().getCharacter();
     64                comment = settings.getComment().getCharacter();
     65                startFrom = settings.getStartFrom().getNumber().intValue();
     66                linesToParse = settings.getLinesToParse().getNumber().intValue();
     67                firstRowHeader = settings.getFirstRowHeader().isSelected();
     68                guessDataTypes = settings.getGuessDataTypes().isSelected();
     69
     70                // For interaction, attributes and interpretation: Convert column indices to column names to prevent shifting
     71
     72                // Interactions
     73                Integer sourceIntIndex = settings.getSourceInteraction().getSelectedItem();
     74                sourceInteraction = sourceIntIndex == null ? null : parsingTableModel.getColumnName(sourceIntIndex);
     75                Integer edgeIntIndex = settings.getEdgeInteraction().getSelectedItem();
     76                edgeInteraction = edgeIntIndex == null ? null : parsingTableModel.getColumnName(edgeIntIndex);
     77                Integer targetIntIndex = settings.getTargetInteraction().getSelectedItem();
     78                targetInteraction = targetIntIndex == null ? null : parsingTableModel.getColumnName(targetIntIndex);
     79
     80                // Additional attributes
     81                int[] sourceAttrIndices = settings.getSourceAttributes().getIndices();
     82                for (int columnIndex : sourceAttrIndices)
     83                        sourceAttributes.add(parsingTableModel.getColumnName(columnIndex));
     84                int[] edgeAttrIndices = settings.getSourceAttributes().getIndices();
     85                for (int columnIndex : edgeAttrIndices)
     86                        edgeAttributes.add(parsingTableModel.getColumnName(columnIndex));
     87                int[] targetAttrIndices = settings.getSourceAttributes().getIndices();
     88                for (int columnIndex : targetAttrIndices)
     89                        targetAttributes.add(parsingTableModel.getColumnName(columnIndex));
     90
     91                // Interpretation
     92                @SuppressWarnings("deprecation")
     93                Set<Entry<Integer, Class<?>>> interpretationKeyValueSet = settings.getInterpretation().entrySet();
     94                for (Entry<Integer, Class<?>> columnInterpretation : interpretationKeyValueSet) {
     95                        String columnName = parsingTableModel.getColumnName(columnInterpretation.getKey());
     96                        interpretation.put(columnName, columnInterpretation.getValue());
    9897                }
    9998        }
    100 
    101         /**
    102          * Method to retrieve interpretation for a certain column.
    103          *
    104          * @param columnIndex
    105          * @return class used to interpret columnIndex (String by default)
    106          */
    107         public Class<?> getInterpretation(final int columnIndex) {
    108                 if (interpretation.containsKey(columnIndex))
    109                         return interpretation.get(columnIndex);
    110                 return String.class;
    111         }
    112 
    113         /**
    114          * JSON Serialization using Jackson requires a public getter method, but discourage anyone from using it directly
    115          *
    116          * @return mapping of column indices to their Class interpretations
    117          */
    118         @Deprecated
    119         public Map<Integer, Class<?>> getInterpretation() {
    120                 return interpretation;
    121         }
    122 
    123         /**
    124          * Support cloning of ParserSettingsModel to get an instance to change without notifying listeners.
    125          */
    126         @Override
    127         @SuppressWarnings("unchecked")
    128         public SaveableSettings clone() throws CloneNotSupportedException {
    129                 SaveableSettings clone = (SaveableSettings) super.clone();
    130                 // Do not copy listeners
    131                 clone.listeners = new ArrayList<ChangeListener>();
    132                 return clone;
    133         }
    134 
    135         // ---- Setters that call fireSettingsChanged when changed
    136 
    137         public void setTableFile(final File tableFile) {
    138                 if (this.tableFile == tableFile)
    139                         return;
    140                 this.tableFile = tableFile;
    141                 // Also set networkName
    142                 networkName = tableFile.getName();
    143                 fireSettingsChanged();
    144         }
    145 
    146         public void setNetworkName(final String networkName) {
    147                 this.networkName = networkName;
    148                 // Do not fire settings changed: Only called from UI element itself
    149                 // Because setNetworkName is triggered when tableFile changes, fireSettingsChanged would trigger parsing twice
    150         }
    151 
    152         public void setDelimiter(final char delimiter) {
    153                 if (this.delimiter == delimiter)
    154                         return;
    155                 this.delimiter = delimiter;
    156                 fireSettingsChanged();
    157         }
    158 
    159         public void setComment(final Character _comment) {
    160                 // Bit more logic to allow for setting null
    161                 if (_comment == null && comment == null)
    162                         return;
    163                 if (_comment != null && _comment.equals(comment))
    164                         return;
    165                 comment = _comment;
    166                 fireSettingsChanged();
    167         }
    168 
    169         public void setStartFrom(final int startFrom) {
    170                 if (this.startFrom == startFrom)
    171                         return;
    172                 this.startFrom = startFrom;
    173                 fireSettingsChanged();
    174         }
    175 
    176         public void setLinesToParse(final int linesToParse) {
    177                 if (this.linesToParse == linesToParse)
    178                         return;
    179                 this.linesToParse = linesToParse;
    180                 fireSettingsChanged();
    181         }
    182 
    183         public void setFirstRowHeader(final boolean firstRowHeader) {
    184                 if (this.firstRowHeader == firstRowHeader)
    185                         return;
    186                 this.firstRowHeader = firstRowHeader;
    187                 fireSettingsChanged();
    188         }
    189 
    190         public void setGuessDataTypes(final boolean guessDataTypes) {
    191                 if (this.guessDataTypes == guessDataTypes)
    192                         return;
    193                 this.guessDataTypes = guessDataTypes;
    194 
    195                 // Reset all interpretations so the previous guesses will not interfere with future manually set interpretations
    196                 if (!guessDataTypes)
    197                         interpretation.clear();
    198 
    199                 fireSettingsChanged();
    200         }
    201 
    202         // Special extra step for source, edge and target attributes: They can only be Strings
    203         public void setSourceInteraction(final Integer sourceAttrIndex) {
    204                 // NOOP when value does not change
    205                 if (sourceInteraction == null && sourceAttrIndex == null)
    206                         return;
    207                 if (sourceAttrIndex != null && sourceAttrIndex.equals(sourceInteraction))
    208                         return;
    209 
    210                 // Assign new value
    211                 sourceInteraction = sourceAttrIndex;
    212                 fireSettingsChanged();
    213         }
    214 
    215         public void setEdgeInteraction(final Integer edgeAttrIndex) {
    216                 // NOOP when value does not change
    217                 if (edgeInteraction == null && edgeAttrIndex == null)
    218                         return;
    219                 if (edgeAttrIndex != null && edgeAttrIndex.equals(edgeInteraction))
    220                         return;
    221 
    222                 // Assign new value
    223                 edgeInteraction = edgeAttrIndex;
    224                 fireSettingsChanged();
    225         }
    226 
    227         public void setTargetInteraction(final Integer targetAttrIndex) {
    228                 // NOOP when value does not change
    229                 if (targetInteraction == null && targetAttrIndex == null)
    230                         return;
    231                 if (targetAttrIndex != null && targetAttrIndex.equals(targetInteraction))
    232                         return;
    233 
    234                 // Assign new value
    235                 targetInteraction = targetAttrIndex;
    236                 fireSettingsChanged();
    237         }
    238 
    239         // Allow for externally modifiable collections here: There are no other developers to muck this up
    240         public void setSourceAttributes(final SortedSet<Integer> sourceAttributes) {
    241                 // When this method is called, one should really fireStructureChanged on the tableModel as well
    242                 this.sourceAttributes = sourceAttributes;
    243                 fireSettingsChanged();
    244         }
    245 
    246         public void setEdgeAttributes(final SortedSet<Integer> edgeAttributes) {
    247                 this.edgeAttributes = edgeAttributes;
    248                 fireSettingsChanged();
    249         }
    250 
    251         public void setTargetAttributes(final SortedSet<Integer> targetAttributes) {
    252                 this.targetAttributes = targetAttributes;
    253                 fireSettingsChanged();
    254         }
    25599}
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/persistence/SettingsPersistence.java

    r354 r364  
    1111import org.codehaus.jackson.map.ObjectWriter;
    1212
    13 import nl.nbic.brs.alttableimport.models.ParserSettingsModel;
     13import nl.nbic.brs.alttableimport.models.ParsingTableModel;
    1414
    1515/**
     
    1919        private static ObjectMapper     mapper                  = new ObjectMapper();
    2020        private static ObjectWriter     prettyWriter    = mapper.writerWithDefaultPrettyPrinter();
    21         private static ObjectReader     settingsReader  = mapper.reader(ParserSettingsModel.class);
     21        private static ObjectReader     settingsReader  = mapper.reader(SaveableSettings.class);
    2222
    2323        /**
     
    2525         *
    2626         * @param file
    27          * @param settings
     27         * @param parsingTableModel
    2828         * @throws JsonGenerationException
    2929         * @throws JsonMappingException
    3030         * @throws IOException
    3131         */
    32         public static void saveSettings(final File file, final ParserSettingsModel settings) throws JsonGenerationException, JsonMappingException, IOException {
    33                 // TODO Saving column numbers instead of names is fragile: columns can shift to break the indices and import
    34                 prettyWriter.writeValue(file, settings);
     32        public static void saveSettings(final File file, final ParsingTableModel parsingTableModel) throws JsonGenerationException, JsonMappingException, IOException {
     33                SaveableSettings saveableSettings = new SaveableSettings(parsingTableModel);
     34                prettyWriter.writeValue(file, saveableSettings);
    3535        }
    3636
     
    4343         * @throws IOException
    4444         */
    45         public static ParserSettingsModel loadSettings(final File file) throws JsonProcessingException, IOException {
    46                 return settingsReader.readValue(file);
     45        public static SaveableSettings loadSettings(final File file) throws JsonProcessingException, IOException {
     46                SaveableSettings readValue = settingsReader.readValue(file);
     47                return readValue;
    4748        }
    4849}
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/views/ButtonPanel.java

    r360 r364  
    3333import nl.nbic.brs.alttableimport.models.ParserSettingsModel;
    3434import nl.nbic.brs.alttableimport.models.ParsingTableModel;
     35import nl.nbic.brs.alttableimport.persistence.SaveableSettings;
    3536import nl.nbic.brs.alttableimport.persistence.SettingsPersistence;
    3637
     
    7273                                // Save settings to selected file
    7374                                try {
    74                                         SettingsPersistence.saveSettings(fileToSave, tableModel.getSettings());
     75                                        SettingsPersistence.saveSettings(fileToSave, tableModel);
    7576                                }
    7677                                catch (IOException ioe) {
     
    9697                                        return;
    9798
    98                                 // Load settings from selected file
    99                                 ParserSettingsModel loadedSettings = null;
    10099                                try {
    101                                         loadedSettings = SettingsPersistence.loadSettings(fileToLoad);
     100                                        // Load settings from selected file
     101                                        SaveableSettings saveableSettings = SettingsPersistence.loadSettings(fileToLoad);
     102                                        tableModel.assimilate(saveableSettings);
    102103                                }
    103104                                catch (IOException ioe) {
     
    107108                                        // Warn user
    108109                                        String title = "Could not load settings from file";
    109                                         String msg = "Serializer reported: \"" + ioe.getMessage() + "\"";
     110                                        String msg = "Deserializer reported: \"" + ioe.getMessage() + "\"";
    110111                                        JOptionPane.showMessageDialog(null, msg, title, JOptionPane.ERROR_MESSAGE);
    111112                                        return;
    112113                                }
    113 
    114                                 // Set new settings on tableModel
    115                                 ;// TODO tableModel.replaceSettings(loadedSettings);
    116114                        }
    117115                });
  • branches/alttableimport-model-rewrite/src/main/java/nl/nbic/brs/alttableimport/views/TableImportDialog.java

    r360 r364  
    99import javax.swing.JDialog;
    1010
    11 import nl.nbic.brs.alttableimport.models.ParserSettingsModel;
     11import lombok.Getter;
     12
    1213import nl.nbic.brs.alttableimport.models.ParsingTableModel;
    1314
     
    1718public class TableImportDialog extends JDialog {
    1819        // Model
    19         private ParsingTableModel       tableModel;
     20        @Getter
     21        private ParsingTableModel       tableModel      = new ParsingTableModel();
    2022
    2123        // Panels
     
    3436                super(parent);
    3537
    36                 // Create models
    37                 ParserSettingsModel settings = new ParserSettingsModel();
    38                 tableModel = new ParsingTableModel(settings);
    39 
    4038                // Create panels
    4139                parseOptionsPanel = new ParseOptionsPanel(tableModel);
     
    5149                // Layout components on page
    5250                layoutComponents();
    53         }
    54 
    55         /**
    56          * @return settings stored within tableModel
    57          */
    58         public ParserSettingsModel getSettings() {
    59                 return tableModel.getSettings();
    6051        }
    6152
  • branches/alttableimport-model-rewrite/src/test/java/nl/nbic/brs/alttableimport/models/TestParsingTableModel.java

    r358 r364  
    99        @Test
    1010        public void testParseFile() {
    11                 ParserSettingsModel settings = new ParserSettingsModel();
    12                 settings.getDelimiter().getSemicolonButtonModel().setSelected(true);
    13 
    1411                // Create table model with partial settings
    15                 ParsingTableModel tableParser = new ParsingTableModel(settings);
     12                ParsingTableModel tableParser = new ParsingTableModel();
     13                ParserSettingsModel settings = tableParser.getSettings();
    1614
    1715                // Proof that we can update the settings later
     16                settings.getDelimiter().getSemicolonButtonModel().setSelected(true);
    1817                settings.addInterpretation(5, Double.class);
    1918                settings.setTableFile(new File("src/test/resources/transacties_-345280419.csv"));
  • branches/alttableimport-model-rewrite/src/test/java/nl/nbic/brs/alttableimport/models/TestSettingsPersistence.java

    r360 r364  
    77import java.util.Scanner;
    88import java.util.TreeMap;
    9 import java.util.TreeSet;
    109
    1110import org.junit.Assert;
    12 import org.junit.Ignore;
    1311import org.junit.Rule;
    1412import org.junit.Test;
    1513import org.junit.rules.TemporaryFolder;
    1614
     15import nl.nbic.brs.alttableimport.persistence.SaveableSettings;
    1716import nl.nbic.brs.alttableimport.persistence.SettingsPersistence;
    1817
    19 @Ignore
    20 // TODO Remove ignoring persistence tests
    2118public class TestSettingsPersistence {
    2219        @Rule
     
    2926        @Test
    3027        public void testSaving() throws Exception {
     28                ParsingTableModel parsingTableModel = new ParsingTableModel();
    3129                // Build settings object
    32                 ParserSettingsModel settings = new ParserSettingsModel();
     30                ParserSettingsModel settings = parsingTableModel.getSettings();
    3331                settings.setTableFile(transactionsTable);
    3432                settings.getNetworkName().setText("MyFirstNetwork");
     
    4644                // Persist to temporary file
    4745                File settingsFile = tempFolder.newFile("settings.json");
    48                 SettingsPersistence.saveSettings(settingsFile, settings);
     46                SettingsPersistence.saveSettings(settingsFile, parsingTableModel);
    4947
    5048                // Compare contents
     
    6967        public void testLoading() throws Exception {
    7068                // Load
    71                 ParserSettingsModel settings = SettingsPersistence.loadSettings(transactionsProfile);
     69                SaveableSettings saveableSettings = SettingsPersistence.loadSettings(transactionsProfile);
     70                ParsingTableModel parsingTableModel = new ParsingTableModel();
     71                ParserSettingsModel settings = parsingTableModel.getSettings();
     72                parsingTableModel.assimilate(saveableSettings);
    7273
    7374                // Check simple fields
    74                 Assert.assertEquals(';', settings.getDelimiter());
     75                Assert.assertEquals(';', settings.getDelimiter().getCharacter());
    7576                Assert.assertEquals(null, settings.getComment().getCharacter());
    76                 Assert.assertEquals(0, settings.getStartFrom());
    77                 Assert.assertEquals(30, settings.getLinesToParse());
     77                Assert.assertEquals(0, settings.getStartFrom().getNumber().intValue());
     78                Assert.assertEquals(30, settings.getLinesToParse().getNumber().intValue());
    7879                Assert.assertEquals(true, settings.getFirstRowHeader().isSelected());
    7980                Assert.assertEquals(2, settings.getSourceInteraction().getSelectedItem().intValue());
    80                 Assert.assertEquals(null, settings.getEdgeInteraction());
     81                Assert.assertEquals(null, settings.getEdgeInteraction().getSelectedItem());
    8182                Assert.assertEquals(4, settings.getTargetInteraction().getSelectedItem().intValue());
    8283
    8384                // Check collections
    84                 Assert.assertEquals(new TreeSet<Integer>(Arrays.asList(2)), settings.getSourceAttributes());
    85                 Assert.assertEquals(new TreeSet<Integer>(Arrays.asList(0, 5)), settings.getEdgeAttributes());
    86                 Assert.assertEquals(new TreeSet<Integer>(Arrays.asList(4)), settings.getTargetAttributes());
     85                Assert.assertArrayEquals(new int[] { 2 }, settings.getSourceAttributes().getIndices());
     86                Assert.assertArrayEquals(new int[] { 0, 5 }, settings.getEdgeAttributes().getIndices());
     87                Assert.assertArrayEquals(new int[] { 4 }, settings.getTargetAttributes().getIndices());
    8788
    8889                // Check interpretation
     
    101102        @Test
    102103        public void testRoundTripPersistence() throws Exception {
    103                 ParserSettingsModel savedSettings = new ParserSettingsModel();
     104                ParsingTableModel savedTableModel = new ParsingTableModel();
     105                ParserSettingsModel savedSettings = savedTableModel.getSettings();
     106                // Store some settings
    104107                savedSettings.getDelimiter().getSemicolonButtonModel().setSelected(true);
    105 
    106                 // Create a table model that'll listen to these settings, to see how listeners are handled
    107                 @SuppressWarnings("unused")
    108                 ParsingTableModel parsingTableModel = new ParsingTableModel(savedSettings);
    109 
    110                 // Add even more settings
    111108                savedSettings.addInterpretation(5, Double.class);
    112109                savedSettings.setTableFile(transactionsTable.getAbsoluteFile());
     
    115112                // Save settings to file
    116113                File settingsFile = tempFolder.newFile("settings.json");
    117                 SettingsPersistence.saveSettings(settingsFile, savedSettings);
     114                SettingsPersistence.saveSettings(settingsFile, savedTableModel);
    118115
    119116                // Some assertions after writing the file
     
    126123
    127124                // Load settings from file
    128                 ParserSettingsModel loadedSettings = SettingsPersistence.loadSettings(settingsFile);
     125                ParsingTableModel loadedTableModel = new ParsingTableModel();
     126                loadedTableModel.assimilate(SettingsPersistence.loadSettings(settingsFile));
    129127
    130                 // Listeners are not persisted, so set listeners loadedSettings to savedSettings.listeners
    131                 loadedSettings.listeners = savedSettings.listeners;
    132128                // The instances should now be equal according to the generated equals method
    133                 Assert.assertEquals(savedSettings, loadedSettings);
     129                Assert.assertEquals(new SaveableSettings(savedTableModel), new SaveableSettings(loadedTableModel));
    134130
    135131                // Assert tableFile is of type file
    136                 Assert.assertEquals(File.class, loadedSettings.getTableFile().getClass());
     132                Assert.assertEquals(File.class, loadedTableModel.getSettings().getTableFile().getClass());
    137133        }
    138134}
Note: See TracChangeset for help on using the changeset viewer.