Ignore:
Timestamp:
2017-08-26T01:59:33+02:00 (7 years ago)
Author:
donvip
Message:

fix deprecation warnings

Location:
applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecPlugin.java

    r32404 r33525  
    22package org.openstreetmap.josm.plugins.osmrec;
    33
    4 import org.openstreetmap.josm.Main;
     4import org.openstreetmap.josm.gui.MainApplication;
    55import org.openstreetmap.josm.gui.MapFrame;
    66import org.openstreetmap.josm.plugins.Plugin;
     
    1313public class OSMRecPlugin extends Plugin {
    1414
    15     private final MenuExportAction menuExportAction;
    16     private static MapFrame mapFrame;
    17     public OSMRecPlugin plugin;
     15        private final MenuExportAction menuExportAction;
     16        private static MapFrame mapFrame;
     17        public OSMRecPlugin plugin;
    1818
    19     public OSMRecPlugin(PluginInformation info) { // NO_UCD (unused code)
    20         super(info);
    21         menuExportAction = new MenuExportAction();
    22         Main.main.menu.toolsMenu.add(menuExportAction);
    23     }
     19        public OSMRecPlugin(PluginInformation info) { // NO_UCD (unused code)
     20                super(info);
     21                menuExportAction = new MenuExportAction();
     22                MainApplication.getMenu().toolsMenu.add(menuExportAction);
     23        }
    2424
    25     @Override
    26     public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
    27         if (oldFrame == null && newFrame != null) { // map frame added
    28             setCurrentMapFrame(newFrame);
    29             setState(this);
    30         }
    31     }
     25        @Override
     26        public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
     27                if (oldFrame == null && newFrame != null) { // map frame added
     28                        setCurrentMapFrame(newFrame);
     29                        setState(this);
     30                }
     31        }
    3232
    33     private void setCurrentMapFrame(MapFrame newFrame) {
    34         OSMRecPlugin.mapFrame = newFrame;
    35     }
     33        private void setCurrentMapFrame(MapFrame newFrame) {
     34                OSMRecPlugin.mapFrame = newFrame;
     35        }
    3636
    37     public static MapFrame getCurrentMapFrame() {
    38         return mapFrame;
    39     }
     37        public static MapFrame getCurrentMapFrame() {
     38                return mapFrame;
     39        }
    4040
    41     private void setState(OSMRecPlugin plugin) {
    42         this.plugin = plugin;
    43     }
     41        private void setState(OSMRecPlugin plugin) {
     42                this.plugin = plugin;
     43        }
    4444
    45     public OSMRecPlugin getState() {
    46         return plugin;
    47     }
     45        public OSMRecPlugin getState() {
     46                return plugin;
     47        }
    4848
    49     //    @Override
    50     //    public PreferenceSetting getPreferenceSetting() {
    51     //        return new PreferenceEditor();
    52     //    }
     49        //    @Override
     50        //    public PreferenceSetting getPreferenceSetting() {
     51        //        return new PreferenceEditor();
     52        //    }
    5353}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecPluginHelper.java

    r32404 r33525  
    100100import org.openstreetmap.josm.data.preferences.IntegerProperty;
    101101import org.openstreetmap.josm.gui.ExtendedDialog;
     102import org.openstreetmap.josm.gui.MainApplication;
    102103import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
    103104import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingComboBox;
     
    122123import org.openstreetmap.josm.plugins.osmrec.personalization.UserDataExtractAndTrainWorker;
    123124import org.openstreetmap.josm.tools.GBC;
     125import org.openstreetmap.josm.tools.Logging;
    124126import org.openstreetmap.josm.tools.Shortcut;
    125127import org.openstreetmap.josm.tools.WindowGeometry;
     
    144146class OSMRecPluginHelper {
    145147
    146     private final DefaultTableModel tagData;
    147     private static Collection<String> fileHistory;
    148     private Map<File, Double> filesAndWeights = new HashMap<>();
    149     private boolean useCombinedModel;
    150 
    151     //the most recent file from history.
    152     //all necessary files will reside in a directory of this file
    153     private static String MAIN_PATH;
    154     private static String MODEL_PATH;
    155     private static String TEXTUAL_LIST_PATH;
    156     private static Map<String, List<String>> indirectClasses;
    157     private static Map<String, Integer> indirectClassesWithIDs;
    158     private static LanguageDetector languageDetector;
    159     private static String bestModelPath;
    160     private boolean modelWithClasses;
    161     private final String modelWithClassesPath;
    162     private boolean useCustomSVMModel = false;
    163     private String customSVMModelPath;
    164     private final String combinedModelClasses;
    165     private final String combinedModel;
    166 
    167     // Selection that we are editing by using both dialogs
    168     Collection<OsmPrimitive> sel;
    169 
    170     private String changedKey;
    171 
    172     Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
    173         @Override
    174         public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
    175             return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
    176         }
    177     };
    178 
    179     private String lastAddKey = null;
    180     private String lastAddValue = null;
    181 
    182     public static final int DEFAULT_LRU_TAGS_NUMBER = 5;
    183     public static final int MAX_LRU_TAGS_NUMBER = 30;
    184 
    185     // LRU cache for recently added tags (http://java-planet.blogspot.com/2005/08/how-to-set-up-simple-lru-cache-using.html)
    186     private final Map<Tag, Void> recentTags = new LinkedHashMap<Tag, Void>(MAX_LRU_TAGS_NUMBER+1, 1.1f, true) {
    187         @Override
    188         protected boolean removeEldestEntry(Map.Entry<Tag, Void> eldest) {
    189             return size() > MAX_LRU_TAGS_NUMBER;
    190         }
    191     };
    192 
    193     OSMRecPluginHelper(DefaultTableModel propertyData, Map<String, Map<String, Integer>> valueCount) {
    194         this.tagData = propertyData;
    195         fileHistory = Main.pref.getCollection("file-open.history");
    196         if (!fileHistory.isEmpty()) {
    197             MAIN_PATH = (String) fileHistory.toArray()[0];
    198         } else {
    199             MAIN_PATH = System.getProperty("user.home");
    200         }
    201         MODEL_PATH = new File(MAIN_PATH).getParentFile() + "/OSMRec_models";
    202         TEXTUAL_LIST_PATH = MODEL_PATH + "/textualList.txt";
    203         combinedModelClasses = MODEL_PATH + "/combinedModel.1";
    204         combinedModel = MODEL_PATH + "/combinedModel.0";
    205         bestModelPath = MODEL_PATH + "/best_model";
    206         customSVMModelPath = bestModelPath;
    207         modelWithClassesPath = MODEL_PATH + "/model_with_classes";
    208         languageDetector = LanguageDetector.getInstance(MODEL_PATH + "/profiles");
    209 
    210         SampleModelsExtractor sampleModelsExtractor = new SampleModelsExtractor();
    211 
    212         sampleModelsExtractor.extractSampleSVMmodel("best_model", bestModelPath);
    213         sampleModelsExtractor.extractSampleSVMmodel("model_with_classes", modelWithClassesPath);
    214     }
    215 
    216     /**
    217     * Open the add selection dialog and add a new key/value to the table (and to the dataset, of course).
    218     */
    219     public void addTag() {
    220         changedKey = null;
    221         sel = Main.main.getInProgressSelection();
    222         if (sel == null || sel.isEmpty()) return;
    223 
    224         final AddTagsDialog addDialog = new AddTagsDialog();
    225 
    226         addDialog.showDialog();
    227 
    228         addDialog.destroyActions();
    229         if (addDialog.getValue() == 1)
    230             addDialog.performTagAdding();
    231         else
    232             addDialog.undoAllTagsAdding();
    233     }
    234 
    235     /**
    236     * Edit the value in the tags table row.
    237     * @param row The row of the table from which the value is edited.
    238     * @param focusOnKey Determines if the initial focus should be set on key instead of value
    239     * @since 5653
    240     */
    241     public void editTag(final int row, boolean focusOnKey) {
    242         changedKey = null;
    243         sel = Main.main.getInProgressSelection();
    244         String key = "";
    245 
    246         @SuppressWarnings("unchecked")
    247         Map<String, Integer> dumPar = new HashMap<>();
    248         dumPar.put(" ", -1);
    249         final TrainingDialog editDialog = new TrainingDialog(key, row,
    250                 dumPar, focusOnKey);
    251         editDialog.showDialog();
    252     }
    253 
    254     /**
    255     * If during last editProperty call user changed the key name, this key will be returned
    256     * Elsewhere, returns null.
    257     * @return The modified key, or {@code null}
    258     */
    259     public String getChangedKey() {
    260         return changedKey;
    261     }
    262 
    263     /**
    264     * For a given key k, return a list of keys which are used as keys for
    265     * auto-completing values to increase the search space.
    266     * @param key the key k
    267     * @return a list of keys
    268     */
    269     private static List<String> getAutocompletionKeys(String key) {
    270         if ("name".equals(key) || "addr:street".equals(key))
    271             return Arrays.asList("addr:street", "name");
    272         else
    273             return Arrays.asList(key);
    274     }
    275 
    276     /**
    277     * Load recently used tags from preferences if needed.
    278     */
    279     public void loadTagsIfNeeded() {
    280         if (PROPERTY_REMEMBER_TAGS.get() && recentTags.isEmpty()) {
    281             recentTags.clear();
    282             Collection<String> c = Main.pref.getCollection("properties.recent-tags");
    283             Iterator<String> it = c.iterator();
    284             String key, value;
    285             while (it.hasNext()) {
    286                 key = it.next();
    287                 value = it.next();
    288                 recentTags.put(new Tag(key, value), null);
    289             }
    290         }
    291     }
    292 
    293     /**
    294     * Store recently used tags in preferences if needed.
    295     */
    296     public void saveTagsIfNeeded() {
    297         if (PROPERTY_REMEMBER_TAGS.get() && !recentTags.isEmpty()) {
    298             List<String> c = new ArrayList<>(recentTags.size()*2);
    299             for (Tag t: recentTags.keySet()) {
    300                 c.add(t.getKey());
    301                 c.add(t.getValue());
    302             }
    303             Main.pref.putCollection("properties.recent-tags", c);
    304         }
    305     }
    306 
    307     /**
    308     * Warns user about a key being overwritten.
    309     * @param action The action done by the user. Must state what key is changed
    310     * @param togglePref  The preference to save the checkbox state to
    311     * @return {@code true} if the user accepts to overwrite key, {@code false} otherwise
    312     */
    313     private boolean warnOverwriteKey(String action, String togglePref) {
    314         ExtendedDialog ed = new ExtendedDialog(
    315                 Main.parent,
    316                 tr("Overwrite key"),
    317                 new String[]{tr("Replace"), tr("Cancel")});
    318         ed.setButtonIcons(new String[]{"purge", "cancel"});
    319         ed.setContent(action+"\n"+ tr("The new key is already used, overwrite values?"));
    320         ed.setCancelButton(2);
    321         ed.toggleEnable(togglePref);
    322         ed.showDialog();
    323 
    324         return ed.getValue() == 1;
    325     }
    326 
    327     public final class TrainingDialog extends AbstractTagsDialog {
    328 
    329         private static final int FIELD_COLUMNS = 4;
    330         private final JTextField inputFileField;
    331         private final JLabel inputFileLabel;
    332         private final JTextField topKField;
    333         private final JTextField cParameterField;
    334         private final JTextField frequencyField;
    335 
    336         private final JButton fileBrowseButton;
    337         private final JButton acceptConfigButton;
    338         private JRadioButton frequencyButton;
    339         private JRadioButton topKButton;
    340         private JCheckBox cParameterCheckBox;
    341         private final JButton resetConfigButton;
    342         private String inputFileValue;
    343         private Double cParameterValue = 0.0;
    344         private Integer topKvalue = 0;
    345         private Integer frequencyValue = 0;
    346         private boolean crossValidateFlag;
    347         private final JButton startTrainingButton;
    348         private final JLabel cErrorMessageLabel;
    349         private final JLabel topKErrorMessageLabel;
    350         private final JLabel inputFileErrorMessageLabel;
    351         private final JLabel frequencyErrorMessageLabel;
    352         private final JProgressBar trainingProgressBar;
    353         private final JRadioButton byAreaRadioButton;
    354         private final JRadioButton byTimeRadioButton;
    355         private final JLabel userNameLabel;
    356         private final JTextField userNameField;
    357         private final JTextField daysField;
    358         private final JLabel daysLabel;
    359         private final JCheckBox trainFromUserCheckBox;
    360         private final JPanel userHistoryPanel;
    361         private Integer daysValue;
    362         private String usernameValue;
    363         private TrainWorker trainWorker;
    364         private UserDataExtractAndTrainWorker userDataExtractAndTrainWorker;
    365 
    366         private TrainingDialog(String key, int row, Map<String, Integer> map, final boolean initialFocusOnKey) {
    367             super(Main.parent, tr("Training process configuration"), new String[] {tr("Cancel")});
    368 
    369             setButtonIcons(new String[] {"ok", "cancel"});
    370             setCancelButton(2);
    371 
    372             JPanel mainPanel = new JPanel(new BorderLayout(10, 10));   //6,6
    373             JPanel configPanel = new JPanel(new BorderLayout(10, 10));  //6,6    //at NORTH of mainPanel
    374             JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //NORTH at config panel
    375             JPanel paramPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //WEST at config panel //config panel has EAST free
    376 
    377             JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //SOUTH at config panel
    378             userHistoryPanel = new JPanel(); //CENTER of config
    379 
    380             trainingProgressBar = new JProgressBar(0, 100);
    381 
    382             ButtonGroup paramGroup = new ButtonGroup();
    383             ButtonGroup userGroup = new ButtonGroup();
    384             inputFileLabel = new JLabel();
    385             inputFileField = new JTextField();
    386             cParameterField = new JTextField();
    387             topKField = new JTextField();
    388             frequencyField = new JTextField();
    389 
    390             cParameterCheckBox = new JCheckBox("Define C parameter");
    391             topKButton = new JRadioButton("Top-K terms");
    392             frequencyButton = new JRadioButton("Max-Frequency");
    393             fileBrowseButton = new JButton();
    394             acceptConfigButton = new JButton("Accept Configuration");
    395             resetConfigButton = new JButton("Reset Configuration/Cancel training");
    396             startTrainingButton = new JButton("Train Model");
    397 
    398             inputFileErrorMessageLabel = new JLabel("");
    399             cErrorMessageLabel = new JLabel("");
    400             topKErrorMessageLabel = new JLabel("");
    401             frequencyErrorMessageLabel = new JLabel("");
    402 
    403             trainFromUserCheckBox = new JCheckBox("Train Model From User");
    404             byAreaRadioButton = new JRadioButton("By Area");
    405             byTimeRadioButton = new JRadioButton("By Time");
    406             userNameLabel = new JLabel("Username:");
    407             userNameField = new JTextField();
    408 
    409             daysLabel = new JLabel("Days: ");
    410             daysField = new JTextField();
    411 
    412             cParameterCheckBox.setSelected(true);
    413             userHistoryPanel.setEnabled(false);
    414             byAreaRadioButton.setEnabled(false);
    415             byAreaRadioButton.setSelected(true);
    416             byTimeRadioButton.setEnabled(false);
    417             userNameLabel.setEnabled(false);
    418             userNameField.setEnabled(false);
    419             daysLabel.setEnabled(false);
    420             daysField.setEnabled(false);
    421             userNameField.setColumns(FIELD_COLUMNS);
    422             daysField.setColumns(FIELD_COLUMNS);
    423 
    424             Collection<String> fileHistory = Main.pref.getCollection("file-open.history");
    425             if (!fileHistory.isEmpty()) {
    426                 inputFileField.setText(MAIN_PATH);
    427             }
    428 
    429             fileBrowseButton.setText("...");
    430             inputFileLabel.setText("OSM filepath: ");
    431             inputFileErrorMessageLabel.setForeground(Color.RED);
    432             inputFileErrorMessageLabel.setText("");
    433             topKField.setText("50");
    434             frequencyField.setText("200");
    435             cParameterField.setText("0.01");
    436 
    437             cParameterField.setColumns(FIELD_COLUMNS);
    438             cParameterField.setEditable(false);
    439             cParameterField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    440             cErrorMessageLabel.setForeground(Color.RED);
    441             cErrorMessageLabel.setMinimumSize(new Dimension(150, 10));
    442 
    443             topKButton.setSelected(true);
    444             topKField.setColumns(FIELD_COLUMNS);
    445             topKField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    446             topKErrorMessageLabel.setForeground(Color.RED);
    447 
    448             frequencyField.setEditable(false);
    449             frequencyField.setColumns(FIELD_COLUMNS);
    450             frequencyField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    451             frequencyErrorMessageLabel.setForeground(Color.RED);
    452 
    453             fileBrowseButton.addActionListener(new java.awt.event.ActionListener() {
    454                 @Override
    455                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    456                     inputFileChooserButtonActionPerformed(evt);
    457                 }
    458             });
    459             topKButton.addActionListener(new java.awt.event.ActionListener() {
    460                 @Override
    461                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    462                     if (topKButton.isSelected()) {
    463                         frequencyField.setEditable(false);
    464                         topKField.setEditable(true);
    465                     } else {
    466                         frequencyField.setEditable(true);
    467                         topKField.setEditable(false);
    468                     }
    469                 }
    470             });
    471             frequencyButton.addActionListener(new java.awt.event.ActionListener() {
    472                 @Override
    473                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    474                     if (frequencyButton.isSelected()) {
    475                         topKField.setEditable(false);
    476                         frequencyField.setEditable(true);
    477                     } else {
    478                         topKField.setEditable(true);
    479                         frequencyField.setEditable(false);
    480                     }
    481                 }
    482             });
    483             cParameterCheckBox.addActionListener(new java.awt.event.ActionListener() {
    484                 @Override
    485                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    486                     if (cParameterCheckBox.isSelected()) {
    487                         cParameterField.setEditable(true);
    488                     } else {
    489                         cParameterField.setEditable(false);
    490                     }
    491                 }
    492             });
    493             acceptConfigButton.addActionListener(new java.awt.event.ActionListener() {
    494                 @Override
    495                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    496                     acceptConfigButtonActionPerformed(evt);
    497                 }
    498             });
    499             resetConfigButton.addActionListener(new java.awt.event.ActionListener() {
    500                 @Override
    501                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    502                     resetConfigButtonActionPerformed();
    503                 }
    504             });
    505 
    506             startTrainingButton.addActionListener(new java.awt.event.ActionListener() {
    507                 @Override
    508                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    509                     if (!acceptConfigButton.isEnabled()) {
    510                         startTraining();
    511                     } else {
    512                         System.out.println("Set values first!");
    513                     }
    514                 }
    515             });
    516 
    517             trainFromUserCheckBox.addActionListener(new java.awt.event.ActionListener() {
    518                 @Override
    519                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    520                     if (trainFromUserCheckBox.isSelected()) {
    521                         userHistoryPanel.setEnabled(true);
    522                         byAreaRadioButton.setEnabled(true);
    523                         byTimeRadioButton.setEnabled(true);
    524                         userNameLabel.setEnabled(true);
    525                         userNameField.setEnabled(true);
    526                         daysLabel.setEnabled(true);
    527                         daysField.setEnabled(true);
    528                     } else {
    529                         userHistoryPanel.setEnabled(false);
    530                         byAreaRadioButton.setEnabled(false);
    531                         byTimeRadioButton.setEnabled(false);
    532                         userNameLabel.setEnabled(false);
    533                         userNameField.setEnabled(false);
    534                         daysLabel.setEnabled(false);
    535                         daysField.setEnabled(false);
    536                     }
    537                 }
    538             });
    539 
    540             byAreaRadioButton.addActionListener(new java.awt.event.ActionListener() {
    541                 @Override
    542                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    543                     if (byAreaRadioButton.isSelected()) {
    544                         daysField.setEditable(false);
    545                     } else {
    546                         daysField.setEditable(true);
    547                     }
    548                 }
    549             });
    550 
    551             byTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
    552                 @Override
    553                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    554                     if (byTimeRadioButton.isSelected()) {
    555                         daysField.setEditable(true);
    556                     } else {
    557                         daysField.setEditable(false);
    558                     }
    559                 }
    560             });
    561 
    562             //grouplayout for input panel
    563             buildInputPanelGroupLayout(inputPanel);
    564 
    565             //grouplayout for param panel
    566             buildParamPanelGroupLayout(paramPanel);
    567 
    568             inputPanel.add(inputFileLabel);
    569             inputPanel.add(inputFileField);
    570             inputPanel.add(fileBrowseButton);
    571             inputPanel.add(inputFileErrorMessageLabel);
    572 
    573             paramGroup.add(topKButton);
    574             paramGroup.add(frequencyButton);
    575 
    576             paramPanel.add(cParameterCheckBox);
    577             paramPanel.add(cParameterField);
    578             paramPanel.add(cErrorMessageLabel);
    579             paramPanel.add(topKButton);
    580             paramPanel.add(topKField);
    581             paramPanel.add(topKErrorMessageLabel);
    582             paramPanel.add(frequencyButton);
    583             paramPanel.add(frequencyField);
    584             paramPanel.add(frequencyErrorMessageLabel);
    585 
    586             southPanel.add(acceptConfigButton);
    587             southPanel.add(resetConfigButton);
    588             southPanel.add(trainFromUserCheckBox);
    589 
    590             userGroup.add(byAreaRadioButton);
    591             userGroup.add(byTimeRadioButton);
    592             userHistoryPanel.add(byAreaRadioButton);
    593             userHistoryPanel.add(byTimeRadioButton);
    594             userHistoryPanel.add(daysLabel);
    595             userHistoryPanel.add(daysField);
    596             userHistoryPanel.add(userNameLabel);
    597             userHistoryPanel.add(userNameField);
    598 
    599             //grouplayout for user history panel
    600             /*
     148        private final DefaultTableModel tagData;
     149        private static Collection<String> fileHistory;
     150        private Map<File, Double> filesAndWeights = new HashMap<>();
     151        private boolean useCombinedModel;
     152
     153        //the most recent file from history.
     154        //all necessary files will reside in a directory of this file
     155        private static String MAIN_PATH;
     156        private static String MODEL_PATH;
     157        private static String TEXTUAL_LIST_PATH;
     158        private static Map<String, List<String>> indirectClasses;
     159        private static Map<String, Integer> indirectClassesWithIDs;
     160        private static LanguageDetector languageDetector;
     161        private static String bestModelPath;
     162        private boolean modelWithClasses;
     163        private final String modelWithClassesPath;
     164        private boolean useCustomSVMModel = false;
     165        private String customSVMModelPath;
     166        private final String combinedModelClasses;
     167        private final String combinedModel;
     168
     169        // Selection that we are editing by using both dialogs
     170        Collection<OsmPrimitive> sel;
     171
     172        private String changedKey;
     173
     174        Comparator<AutoCompletionListItem> defaultACItemComparator = new Comparator<AutoCompletionListItem>() {
     175                @Override
     176                public int compare(AutoCompletionListItem o1, AutoCompletionListItem o2) {
     177                        return String.CASE_INSENSITIVE_ORDER.compare(o1.getValue(), o2.getValue());
     178                }
     179        };
     180
     181        private String lastAddKey = null;
     182        private String lastAddValue = null;
     183
     184        public static final int DEFAULT_LRU_TAGS_NUMBER = 5;
     185        public static final int MAX_LRU_TAGS_NUMBER = 30;
     186
     187        // LRU cache for recently added tags (http://java-planet.blogspot.com/2005/08/how-to-set-up-simple-lru-cache-using.html)
     188        private final Map<Tag, Void> recentTags = new LinkedHashMap<Tag, Void>(MAX_LRU_TAGS_NUMBER+1, 1.1f, true) {
     189                @Override
     190                protected boolean removeEldestEntry(Map.Entry<Tag, Void> eldest) {
     191                        return size() > MAX_LRU_TAGS_NUMBER;
     192                }
     193        };
     194
     195        OSMRecPluginHelper(DefaultTableModel propertyData, Map<String, Map<String, Integer>> valueCount) {
     196                this.tagData = propertyData;
     197                fileHistory = Main.pref.getCollection("file-open.history");
     198                if (!fileHistory.isEmpty()) {
     199                        MAIN_PATH = (String) fileHistory.toArray()[0];
     200                } else {
     201                        MAIN_PATH = System.getProperty("user.home");
     202                }
     203                MODEL_PATH = new File(MAIN_PATH).getParentFile() + "/OSMRec_models";
     204                TEXTUAL_LIST_PATH = MODEL_PATH + "/textualList.txt";
     205                combinedModelClasses = MODEL_PATH + "/combinedModel.1";
     206                combinedModel = MODEL_PATH + "/combinedModel.0";
     207                bestModelPath = MODEL_PATH + "/best_model";
     208                customSVMModelPath = bestModelPath;
     209                modelWithClassesPath = MODEL_PATH + "/model_with_classes";
     210                languageDetector = LanguageDetector.getInstance(MODEL_PATH + "/profiles");
     211
     212                SampleModelsExtractor sampleModelsExtractor = new SampleModelsExtractor();
     213
     214                sampleModelsExtractor.extractSampleSVMmodel("best_model", bestModelPath);
     215                sampleModelsExtractor.extractSampleSVMmodel("model_with_classes", modelWithClassesPath);
     216        }
     217
     218        /**
     219        * Open the add selection dialog and add a new key/value to the table (and to the dataset, of course).
     220        */
     221        public void addTag() {
     222                changedKey = null;
     223                sel = Main.main.getInProgressSelection();
     224                if (sel == null || sel.isEmpty()) return;
     225
     226                final AddTagsDialog addDialog = new AddTagsDialog();
     227
     228                addDialog.showDialog();
     229
     230                addDialog.destroyActions();
     231                if (addDialog.getValue() == 1)
     232                        addDialog.performTagAdding();
     233                else
     234                        addDialog.undoAllTagsAdding();
     235        }
     236
     237        /**
     238        * Edit the value in the tags table row.
     239        * @param row The row of the table from which the value is edited.
     240        * @param focusOnKey Determines if the initial focus should be set on key instead of value
     241        * @since 5653
     242        */
     243        public void editTag(final int row, boolean focusOnKey) {
     244                changedKey = null;
     245                sel = Main.main.getInProgressSelection();
     246                String key = "";
     247
     248                @SuppressWarnings("unchecked")
     249                Map<String, Integer> dumPar = new HashMap<>();
     250                dumPar.put(" ", -1);
     251                final TrainingDialog editDialog = new TrainingDialog(key, row,
     252                                dumPar, focusOnKey);
     253                editDialog.showDialog();
     254        }
     255
     256        /**
     257        * If during last editProperty call user changed the key name, this key will be returned
     258        * Elsewhere, returns null.
     259        * @return The modified key, or {@code null}
     260        */
     261        public String getChangedKey() {
     262                return changedKey;
     263        }
     264
     265        /**
     266        * For a given key k, return a list of keys which are used as keys for
     267        * auto-completing values to increase the search space.
     268        * @param key the key k
     269        * @return a list of keys
     270        */
     271        private static List<String> getAutocompletionKeys(String key) {
     272                if ("name".equals(key) || "addr:street".equals(key))
     273                        return Arrays.asList("addr:street", "name");
     274                else
     275                        return Arrays.asList(key);
     276        }
     277
     278        /**
     279        * Load recently used tags from preferences if needed.
     280        */
     281        public void loadTagsIfNeeded() {
     282                if (PROPERTY_REMEMBER_TAGS.get() && recentTags.isEmpty()) {
     283                        recentTags.clear();
     284                        Collection<String> c = Main.pref.getCollection("properties.recent-tags");
     285                        Iterator<String> it = c.iterator();
     286                        String key, value;
     287                        while (it.hasNext()) {
     288                                key = it.next();
     289                                value = it.next();
     290                                recentTags.put(new Tag(key, value), null);
     291                        }
     292                }
     293        }
     294
     295        /**
     296        * Store recently used tags in preferences if needed.
     297        */
     298        public void saveTagsIfNeeded() {
     299                if (PROPERTY_REMEMBER_TAGS.get() && !recentTags.isEmpty()) {
     300                        List<String> c = new ArrayList<>(recentTags.size()*2);
     301                        for (Tag t: recentTags.keySet()) {
     302                                c.add(t.getKey());
     303                                c.add(t.getValue());
     304                        }
     305                        Main.pref.putCollection("properties.recent-tags", c);
     306                }
     307        }
     308
     309        /**
     310        * Warns user about a key being overwritten.
     311        * @param action The action done by the user. Must state what key is changed
     312        * @param togglePref  The preference to save the checkbox state to
     313        * @return {@code true} if the user accepts to overwrite key, {@code false} otherwise
     314        */
     315        private boolean warnOverwriteKey(String action, String togglePref) {
     316                ExtendedDialog ed = new ExtendedDialog(
     317                                Main.parent,
     318                                tr("Overwrite key"),
     319                                new String[]{tr("Replace"), tr("Cancel")});
     320                ed.setButtonIcons(new String[]{"purge", "cancel"});
     321                ed.setContent(action+"\n"+ tr("The new key is already used, overwrite values?"));
     322                ed.setCancelButton(2);
     323                ed.toggleEnable(togglePref);
     324                ed.showDialog();
     325
     326                return ed.getValue() == 1;
     327        }
     328
     329        public final class TrainingDialog extends AbstractTagsDialog {
     330
     331                private static final int FIELD_COLUMNS = 4;
     332                private final JTextField inputFileField;
     333                private final JLabel inputFileLabel;
     334                private final JTextField topKField;
     335                private final JTextField cParameterField;
     336                private final JTextField frequencyField;
     337
     338                private final JButton fileBrowseButton;
     339                private final JButton acceptConfigButton;
     340                private JRadioButton frequencyButton;
     341                private JRadioButton topKButton;
     342                private JCheckBox cParameterCheckBox;
     343                private final JButton resetConfigButton;
     344                private String inputFileValue;
     345                private Double cParameterValue = 0.0;
     346                private Integer topKvalue = 0;
     347                private Integer frequencyValue = 0;
     348                private boolean crossValidateFlag;
     349                private final JButton startTrainingButton;
     350                private final JLabel cErrorMessageLabel;
     351                private final JLabel topKErrorMessageLabel;
     352                private final JLabel inputFileErrorMessageLabel;
     353                private final JLabel frequencyErrorMessageLabel;
     354                private final JProgressBar trainingProgressBar;
     355                private final JRadioButton byAreaRadioButton;
     356                private final JRadioButton byTimeRadioButton;
     357                private final JLabel userNameLabel;
     358                private final JTextField userNameField;
     359                private final JTextField daysField;
     360                private final JLabel daysLabel;
     361                private final JCheckBox trainFromUserCheckBox;
     362                private final JPanel userHistoryPanel;
     363                private Integer daysValue;
     364                private String usernameValue;
     365                private TrainWorker trainWorker;
     366                private UserDataExtractAndTrainWorker userDataExtractAndTrainWorker;
     367
     368                private TrainingDialog(String key, int row, Map<String, Integer> map, final boolean initialFocusOnKey) {
     369                        super(Main.parent, tr("Training process configuration"), new String[] {tr("Cancel")});
     370
     371                        setButtonIcons(new String[] {"ok", "cancel"});
     372                        setCancelButton(2);
     373
     374                        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));   //6,6
     375                        JPanel configPanel = new JPanel(new BorderLayout(10, 10));  //6,6    //at NORTH of mainPanel
     376                        JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //NORTH at config panel
     377                        JPanel paramPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //WEST at config panel //config panel has EAST free
     378
     379                        JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));    //SOUTH at config panel
     380                        userHistoryPanel = new JPanel(); //CENTER of config
     381
     382                        trainingProgressBar = new JProgressBar(0, 100);
     383
     384                        ButtonGroup paramGroup = new ButtonGroup();
     385                        ButtonGroup userGroup = new ButtonGroup();
     386                        inputFileLabel = new JLabel();
     387                        inputFileField = new JTextField();
     388                        cParameterField = new JTextField();
     389                        topKField = new JTextField();
     390                        frequencyField = new JTextField();
     391
     392                        cParameterCheckBox = new JCheckBox("Define C parameter");
     393                        topKButton = new JRadioButton("Top-K terms");
     394                        frequencyButton = new JRadioButton("Max-Frequency");
     395                        fileBrowseButton = new JButton();
     396                        acceptConfigButton = new JButton("Accept Configuration");
     397                        resetConfigButton = new JButton("Reset Configuration/Cancel training");
     398                        startTrainingButton = new JButton("Train Model");
     399
     400                        inputFileErrorMessageLabel = new JLabel("");
     401                        cErrorMessageLabel = new JLabel("");
     402                        topKErrorMessageLabel = new JLabel("");
     403                        frequencyErrorMessageLabel = new JLabel("");
     404
     405                        trainFromUserCheckBox = new JCheckBox("Train Model From User");
     406                        byAreaRadioButton = new JRadioButton("By Area");
     407                        byTimeRadioButton = new JRadioButton("By Time");
     408                        userNameLabel = new JLabel("Username:");
     409                        userNameField = new JTextField();
     410
     411                        daysLabel = new JLabel("Days: ");
     412                        daysField = new JTextField();
     413
     414                        cParameterCheckBox.setSelected(true);
     415                        userHistoryPanel.setEnabled(false);
     416                        byAreaRadioButton.setEnabled(false);
     417                        byAreaRadioButton.setSelected(true);
     418                        byTimeRadioButton.setEnabled(false);
     419                        userNameLabel.setEnabled(false);
     420                        userNameField.setEnabled(false);
     421                        daysLabel.setEnabled(false);
     422                        daysField.setEnabled(false);
     423                        userNameField.setColumns(FIELD_COLUMNS);
     424                        daysField.setColumns(FIELD_COLUMNS);
     425
     426                        Collection<String> fileHistory = Main.pref.getCollection("file-open.history");
     427                        if (!fileHistory.isEmpty()) {
     428                                inputFileField.setText(MAIN_PATH);
     429                        }
     430
     431                        fileBrowseButton.setText("...");
     432                        inputFileLabel.setText("OSM filepath: ");
     433                        inputFileErrorMessageLabel.setForeground(Color.RED);
     434                        inputFileErrorMessageLabel.setText("");
     435                        topKField.setText("50");
     436                        frequencyField.setText("200");
     437                        cParameterField.setText("0.01");
     438
     439                        cParameterField.setColumns(FIELD_COLUMNS);
     440                        cParameterField.setEditable(false);
     441                        cParameterField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
     442                        cErrorMessageLabel.setForeground(Color.RED);
     443                        cErrorMessageLabel.setMinimumSize(new Dimension(150, 10));
     444
     445                        topKButton.setSelected(true);
     446                        topKField.setColumns(FIELD_COLUMNS);
     447                        topKField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
     448                        topKErrorMessageLabel.setForeground(Color.RED);
     449
     450                        frequencyField.setEditable(false);
     451                        frequencyField.setColumns(FIELD_COLUMNS);
     452                        frequencyField.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
     453                        frequencyErrorMessageLabel.setForeground(Color.RED);
     454
     455                        fileBrowseButton.addActionListener(new java.awt.event.ActionListener() {
     456                                @Override
     457                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     458                                        inputFileChooserButtonActionPerformed(evt);
     459                                }
     460                        });
     461                        topKButton.addActionListener(new java.awt.event.ActionListener() {
     462                                @Override
     463                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     464                                        if (topKButton.isSelected()) {
     465                                                frequencyField.setEditable(false);
     466                                                topKField.setEditable(true);
     467                                        } else {
     468                                                frequencyField.setEditable(true);
     469                                                topKField.setEditable(false);
     470                                        }
     471                                }
     472                        });
     473                        frequencyButton.addActionListener(new java.awt.event.ActionListener() {
     474                                @Override
     475                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     476                                        if (frequencyButton.isSelected()) {
     477                                                topKField.setEditable(false);
     478                                                frequencyField.setEditable(true);
     479                                        } else {
     480                                                topKField.setEditable(true);
     481                                                frequencyField.setEditable(false);
     482                                        }
     483                                }
     484                        });
     485                        cParameterCheckBox.addActionListener(new java.awt.event.ActionListener() {
     486                                @Override
     487                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     488                                        if (cParameterCheckBox.isSelected()) {
     489                                                cParameterField.setEditable(true);
     490                                        } else {
     491                                                cParameterField.setEditable(false);
     492                                        }
     493                                }
     494                        });
     495                        acceptConfigButton.addActionListener(new java.awt.event.ActionListener() {
     496                                @Override
     497                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     498                                        acceptConfigButtonActionPerformed(evt);
     499                                }
     500                        });
     501                        resetConfigButton.addActionListener(new java.awt.event.ActionListener() {
     502                                @Override
     503                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     504                                        resetConfigButtonActionPerformed();
     505                                }
     506                        });
     507
     508                        startTrainingButton.addActionListener(new java.awt.event.ActionListener() {
     509                                @Override
     510                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     511                                        if (!acceptConfigButton.isEnabled()) {
     512                                                startTraining();
     513                                        } else {
     514                                                System.out.println("Set values first!");
     515                                        }
     516                                }
     517                        });
     518
     519                        trainFromUserCheckBox.addActionListener(new java.awt.event.ActionListener() {
     520                                @Override
     521                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     522                                        if (trainFromUserCheckBox.isSelected()) {
     523                                                userHistoryPanel.setEnabled(true);
     524                                                byAreaRadioButton.setEnabled(true);
     525                                                byTimeRadioButton.setEnabled(true);
     526                                                userNameLabel.setEnabled(true);
     527                                                userNameField.setEnabled(true);
     528                                                daysLabel.setEnabled(true);
     529                                                daysField.setEnabled(true);
     530                                        } else {
     531                                                userHistoryPanel.setEnabled(false);
     532                                                byAreaRadioButton.setEnabled(false);
     533                                                byTimeRadioButton.setEnabled(false);
     534                                                userNameLabel.setEnabled(false);
     535                                                userNameField.setEnabled(false);
     536                                                daysLabel.setEnabled(false);
     537                                                daysField.setEnabled(false);
     538                                        }
     539                                }
     540                        });
     541
     542                        byAreaRadioButton.addActionListener(new java.awt.event.ActionListener() {
     543                                @Override
     544                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     545                                        if (byAreaRadioButton.isSelected()) {
     546                                                daysField.setEditable(false);
     547                                        } else {
     548                                                daysField.setEditable(true);
     549                                        }
     550                                }
     551                        });
     552
     553                        byTimeRadioButton.addActionListener(new java.awt.event.ActionListener() {
     554                                @Override
     555                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     556                                        if (byTimeRadioButton.isSelected()) {
     557                                                daysField.setEditable(true);
     558                                        } else {
     559                                                daysField.setEditable(false);
     560                                        }
     561                                }
     562                        });
     563
     564                        //grouplayout for input panel
     565                        buildInputPanelGroupLayout(inputPanel);
     566
     567                        //grouplayout for param panel
     568                        buildParamPanelGroupLayout(paramPanel);
     569
     570                        inputPanel.add(inputFileLabel);
     571                        inputPanel.add(inputFileField);
     572                        inputPanel.add(fileBrowseButton);
     573                        inputPanel.add(inputFileErrorMessageLabel);
     574
     575                        paramGroup.add(topKButton);
     576                        paramGroup.add(frequencyButton);
     577
     578                        paramPanel.add(cParameterCheckBox);
     579                        paramPanel.add(cParameterField);
     580                        paramPanel.add(cErrorMessageLabel);
     581                        paramPanel.add(topKButton);
     582                        paramPanel.add(topKField);
     583                        paramPanel.add(topKErrorMessageLabel);
     584                        paramPanel.add(frequencyButton);
     585                        paramPanel.add(frequencyField);
     586                        paramPanel.add(frequencyErrorMessageLabel);
     587
     588                        southPanel.add(acceptConfigButton);
     589                        southPanel.add(resetConfigButton);
     590                        southPanel.add(trainFromUserCheckBox);
     591
     592                        userGroup.add(byAreaRadioButton);
     593                        userGroup.add(byTimeRadioButton);
     594                        userHistoryPanel.add(byAreaRadioButton);
     595                        userHistoryPanel.add(byTimeRadioButton);
     596                        userHistoryPanel.add(daysLabel);
     597                        userHistoryPanel.add(daysField);
     598                        userHistoryPanel.add(userNameLabel);
     599                        userHistoryPanel.add(userNameField);
     600
     601                        //grouplayout for user history panel
     602                        /*
    601603                userNameLabel       userField
    602604                arearadiobutton
    603605                timeradiobutton     daysLabel   daysField
    604             */
    605             buildUserHistoryPanelGroupLayout();
    606 
    607             configPanel.add(inputPanel, BorderLayout.NORTH);
    608             configPanel.add(userHistoryPanel, BorderLayout.EAST);
    609             configPanel.add(paramPanel, BorderLayout.WEST);
    610             configPanel.add(southPanel, BorderLayout.SOUTH);
    611 
    612             userHistoryPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
    613                     .createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE), "Train by user History"));
    614             paramPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
    615                     .createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE), "SVM Configuration"));
    616             inputPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    617             configPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    618 
    619             mainPanel.add(configPanel, BorderLayout.NORTH);
    620             mainPanel.add(startTrainingButton, BorderLayout.CENTER);
    621             mainPanel.add(trainingProgressBar, BorderLayout.SOUTH);
    622 
    623             AutoCompletionManager autocomplete = Main.getLayerManager().getEditLayer().data.getAutoCompletionManager();
    624             List<AutoCompletionListItem> keyList = autocomplete.getKeys();
    625             Collections.sort(keyList, defaultACItemComparator);
    626 
    627             setContent(mainPanel, false);
    628         }
    629 
    630         private void buildInputPanelGroupLayout(JPanel inputPanel) {
    631             GroupLayout inputGroupLayout = new GroupLayout(inputPanel);
    632             inputPanel.setLayout(inputGroupLayout);
    633             inputGroupLayout.setAutoCreateGaps(true);
    634             inputGroupLayout.setAutoCreateContainerGaps(true);
    635 
    636             GroupLayout.SequentialGroup inputHorGroup = inputGroupLayout.createSequentialGroup();
    637             inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(inputFileLabel).
    638                     addComponent(inputFileErrorMessageLabel));
    639             inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(inputFileField));
    640             inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(fileBrowseButton));
    641             inputGroupLayout.setHorizontalGroup(inputHorGroup);
    642 
    643             GroupLayout.SequentialGroup inputVerGroup = inputGroupLayout.createSequentialGroup();
    644             inputVerGroup.addGroup(inputGroupLayout.createParallelGroup(Alignment.LEADING).addComponent(inputFileLabel).
    645                     addComponent(inputFileField).addComponent(fileBrowseButton));
    646             inputVerGroup.addGroup(inputGroupLayout.createParallelGroup(Alignment.LEADING).
    647                     addComponent(inputFileErrorMessageLabel));
    648             inputGroupLayout.setVerticalGroup(inputVerGroup);
    649         }
    650 
    651         private void buildParamPanelGroupLayout(JPanel paramPanel) {
    652             GroupLayout paramGroupLayout = new GroupLayout(paramPanel);
    653             paramPanel.setLayout(paramGroupLayout);
    654             paramGroupLayout.setAutoCreateGaps(true);
    655             paramGroupLayout.setAutoCreateContainerGaps(true);
    656 
    657             GroupLayout.SequentialGroup paramHorGroup = paramGroupLayout.createSequentialGroup();
    658             paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(topKButton).
    659                     addComponent(frequencyButton).addComponent(cParameterCheckBox));
    660             paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(cParameterField).
    661                     addComponent(topKField).addComponent(frequencyField));
    662             paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(cErrorMessageLabel).
    663                     addComponent(topKErrorMessageLabel).addComponent(frequencyErrorMessageLabel));
    664             paramGroupLayout.setHorizontalGroup(paramHorGroup);
    665 
    666             GroupLayout.SequentialGroup paramVerGroup = paramGroupLayout.createSequentialGroup();
    667             paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).
    668                     addComponent(cParameterCheckBox).addComponent(cParameterField).addComponent(cErrorMessageLabel));
    669             paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).addComponent(topKButton).
    670                     addComponent(topKField).addComponent(topKErrorMessageLabel));
    671             paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).
    672                     addComponent(frequencyButton).addComponent(frequencyField).addComponent(frequencyErrorMessageLabel));
    673             paramGroupLayout.setVerticalGroup(paramVerGroup);
    674         }
    675 
    676         private void buildUserHistoryPanelGroupLayout() {
    677             GroupLayout userHistoryGroupLayout = new GroupLayout(userHistoryPanel);
    678             userHistoryPanel.setLayout(userHistoryGroupLayout);
    679             userHistoryGroupLayout.setAutoCreateGaps(true);
    680             userHistoryGroupLayout.setAutoCreateContainerGaps(true);
    681             userHistoryGroupLayout.linkSize(SwingConstants.HORIZONTAL, userNameField, daysLabel, daysField);
    682 
    683             GroupLayout.SequentialGroup userHistoryHorGroup = userHistoryGroupLayout.createSequentialGroup();
    684 
    685             userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(userNameLabel)
    686                     .addComponent(byAreaRadioButton).addComponent(byTimeRadioButton));
    687             userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(userNameField)
    688                     .addComponent(daysLabel));
    689             userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(daysField));
    690             userHistoryGroupLayout.setHorizontalGroup(userHistoryHorGroup);
    691 
    692             GroupLayout.SequentialGroup userHistoryVerGroup = userHistoryGroupLayout.createSequentialGroup();
    693             userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
    694                     addComponent(userNameLabel).addComponent(userNameField));
    695             userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
    696                     addComponent(byAreaRadioButton));
    697             userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
    698                     addComponent(byTimeRadioButton).addComponent(daysLabel).addComponent(daysField));
    699             userHistoryGroupLayout.setVerticalGroup(userHistoryVerGroup);
    700         }
    701 
    702         private void inputFileChooserButtonActionPerformed(ActionEvent evt) {
    703             try {
    704                 final File file = new File(inputFileField.getText());
    705                 final JFileChooser fileChooser = new JFileChooser(file);
    706 
    707                 final int returnVal = fileChooser.showOpenDialog(this);
    708                 if (returnVal == JFileChooser.APPROVE_OPTION) {
    709                     inputFileField.setText(fileChooser.getSelectedFile().getAbsolutePath());
    710                 }
    711             } catch (RuntimeException ex) {
    712                 Main.warn(ex);
    713             }
    714         }
    715 
    716         private void acceptConfigButtonActionPerformed(ActionEvent evt) {
    717             //parse values
    718             inputFileValue = inputFileField.getText();
    719 
    720             if (!new File(inputFileValue).exists()) {
    721                 inputFileErrorMessageLabel.setText("OSM file does not exist");
    722                 resetConfigButtonActionPerformed();
    723                 return;
    724             }
    725 
    726             if (cParameterCheckBox.isSelected()) {
    727                 String c = cParameterField.getText();
    728                 try {
    729                     cParameterValue = Double.parseDouble(c.replace(",", "."));
    730                     cErrorMessageLabel.setText("");
    731                 } catch (NumberFormatException ex) {
    732                     cErrorMessageLabel.setText("Must be a number!");
    733                     System.out.println("c must be a number!" + ex); //make empty textLabel beside c param to notify errors
    734                     resetConfigButtonActionPerformed();
    735                     return;
    736                 }
    737                 crossValidateFlag = false;
    738             } else {
    739                 crossValidateFlag = true;
    740             }
    741 
    742             if (topKButton.isSelected()) {
    743                 String k = topKField.getText();
    744                 try {
    745                     topKvalue = Integer.parseInt(k);
    746                     topKErrorMessageLabel.setText("");
    747                 } catch (NumberFormatException ex) {
    748                     topKErrorMessageLabel.setText("Must be an Integer!");
    749                     resetConfigButtonActionPerformed();
    750                     return;
    751                 }
    752             } else {
    753                 String f = frequencyField.getText();
    754                 try {
    755                     frequencyValue = Integer.parseInt(f);
    756                     frequencyErrorMessageLabel.setText("");
    757                 } catch (NumberFormatException ex) {
    758                     frequencyErrorMessageLabel.setText("Must be an Integer!");
    759                     resetConfigButtonActionPerformed();
    760                     return;
    761                 }
    762             }
    763 
    764             if (trainFromUserCheckBox.isSelected()) {
    765                 usernameValue = userNameField.getText();
    766                 if (byTimeRadioButton.isSelected()) {
    767                     try {
    768                         daysValue = Integer.parseInt(daysField.getText());
    769                     } catch (NumberFormatException ex) {
    770                         daysField.setText("Integer!");
    771                         Main.warn(ex);
    772                     }
    773                 }
    774 
    775                 userHistoryPanel.setEnabled(false);
    776                 byAreaRadioButton.setEnabled(false);
    777                 byTimeRadioButton.setEnabled(false);
    778                 userNameLabel.setEnabled(false);
    779                 userNameField.setEnabled(false);
    780                 daysLabel.setEnabled(false);
    781                 daysField.setEnabled(false);
    782             }
    783 
    784             System.out.println("Running configuration:" + "\nC parameter: " + cParameterValue +" \ntopK: " + topKvalue
    785                     + "\nMax Frequency: " + frequencyValue + "\nCross Validate?: " + crossValidateFlag);
    786 
    787             trainFromUserCheckBox.setEnabled(false);
    788             inputFileField.setEditable(false);
    789             cParameterField.setEditable(false);
    790             topKField.setEditable(false);
    791             frequencyField.setEditable(false);
    792             cParameterCheckBox.setEnabled(false);
    793             topKButton.setEnabled(false);
    794             frequencyButton.setEnabled(false);
    795             acceptConfigButton.setEnabled(false);
    796             fileBrowseButton.setEnabled(false);
    797         }
    798 
    799         private void resetConfigButtonActionPerformed() {
    800             if (trainWorker != null) {
    801                 try {
    802                     trainWorker.cancel(true);
    803                 } catch (CancellationException ex) {
    804                     startTrainingButton.setEnabled(true);
    805                     System.out.println(ex);
    806                 }
    807             }
    808             if (userDataExtractAndTrainWorker != null) {
    809                 try {
    810                     userDataExtractAndTrainWorker.cancel(true);
    811                 } catch (CancellationException ex) {
    812                     startTrainingButton.setEnabled(true);
    813                     System.out.println(ex);
    814                 }
    815             }
    816             inputFileField.setEditable(true);
    817             cParameterField.setEditable(true);
    818             topKField.setEditable(true);
    819             frequencyField.setEditable(true);
    820             cParameterCheckBox.setEnabled(true);
    821             topKButton.setEnabled(true);
    822             frequencyButton.setEnabled(true);
    823             acceptConfigButton.setEnabled(true);
    824             fileBrowseButton.setEnabled(true);
    825             trainFromUserCheckBox.setEnabled(true);
    826 
    827             if (trainFromUserCheckBox.isSelected()) {
    828                 userHistoryPanel.setEnabled(true);
    829                 byAreaRadioButton.setEnabled(true);
    830                 byTimeRadioButton.setEnabled(true);
    831                 userNameLabel.setEnabled(true);
    832                 userNameField.setEnabled(true);
    833                 daysLabel.setEnabled(true);
    834                 daysField.setEnabled(true);
    835             }
    836         }
    837 
    838         private void startTraining() {
    839             startTrainingButton.setEnabled(false);
    840 
    841             if (trainFromUserCheckBox.isSelected()) { //if user training. train by area or days
    842                 EventQueue.invokeLater(new Runnable() {
    843                     @Override
    844                     public void run() {
    845 
    846                         userDataExtractAndTrainWorker = new UserDataExtractAndTrainWorker(inputFileValue, usernameValue, daysValue,
    847                                 byAreaRadioButton.isSelected(), crossValidateFlag, cParameterValue, topKvalue, frequencyValue,
    848                                 topKButton.isSelected(), languageDetector);
    849 
    850                         userDataExtractAndTrainWorker.addPropertyChangeListener(new PropertyChangeListener() {
    851                             @Override
    852                             public void propertyChange(PropertyChangeEvent evt) {
    853                                 if ("progress".equals(evt.getPropertyName())) {
    854                                     int progress = (Integer) evt.getNewValue();
    855                                     trainingProgressBar.setValue(progress);
    856                                     if (progress == 100) {
    857                                         startTrainingButton.setEnabled(true);
    858                                     }
    859                                 }
    860                             }
    861                         });
    862 
    863                         try {
    864                             System.out.println("executing userDataExtractAndTrainWorker Thread..");
    865                             userDataExtractAndTrainWorker.execute();
    866                         } catch (Exception ex) {
    867                             Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    868                         }
    869                     }
    870                 });
    871             } else {
    872                 EventQueue.invokeLater(new Runnable() {
    873                     @Override
    874                     public void run() {
    875                         trainWorker = new TrainWorker(inputFileValue, crossValidateFlag, cParameterValue, topKvalue, frequencyValue,
    876                                 topKButton.isSelected(), languageDetector);
    877 
    878                         trainWorker.addPropertyChangeListener(new PropertyChangeListener() {
    879                             @Override
    880                             public void propertyChange(PropertyChangeEvent evt) {
    881                                 if ("progress".equals(evt.getPropertyName())) {
    882                                     int progress = (Integer) evt.getNewValue();
    883                                     trainingProgressBar.setValue(progress);
    884                                     if (progress == 100) {
    885                                         startTrainingButton.setEnabled(true);
    886                                     }
    887                                 }
    888                             }
    889                         });
    890 
    891                         try {
    892                             trainWorker.execute();
    893                         } catch (Exception ex) {
    894                             Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    895                         }
    896                     }
    897                 });
    898             }
    899         }
    900     }
    901 
    902     public static final BooleanProperty PROPERTY_FIX_TAG_LOCALE =
    903             new BooleanProperty("properties.fix-tag-combobox-locale", false);
    904     public static final BooleanProperty PROPERTY_REMEMBER_TAGS =
    905             new BooleanProperty("properties.remember-recently-added-tags", true);
    906     public static final IntegerProperty PROPERTY_RECENT_TAGS_NUMBER =
    907             new IntegerProperty("properties.recently-added-tags", DEFAULT_LRU_TAGS_NUMBER);
    908 
    909     abstract static class AbstractTagsDialog extends ExtendedDialog {
    910         AutoCompletingComboBox keys;
    911         AutoCompletingComboBox values;
    912 
    913         AbstractTagsDialog(Component parent, String title, String[] buttonTexts) {
    914             super(parent, title, buttonTexts);
    915             addMouseListener(new PopupMenuLauncher(popupMenu));
    916         }
    917 
    918         @Override
    919         public void setupDialog() {
    920             super.setupDialog();
    921             final Dimension size = getSize();
    922             // Set resizable only in width
    923             setMinimumSize(size);
    924             setPreferredSize(size);
    925             // setMaximumSize does not work, and never worked, but still it seems not to bother Oracle to fix this 10-year-old bug
    926             // https://bugs.openjdk.java.net/browse/JDK-6200438
    927             // https://bugs.openjdk.java.net/browse/JDK-6464548
    928 
    929             setRememberWindowGeometry(getClass().getName() + ".geometry",
    930                     WindowGeometry.centerInWindow(Main.parent, size));
    931         }
    932 
    933         @Override
    934         public void setVisible(boolean visible) {
    935             // Do not want dialog to be resizable in height, as its size may increase each time because of the recently added tags
    936             // So need to modify the stored geometry (size part only) in order to use the automatic positioning mechanism
    937             if (visible) {
    938                 WindowGeometry geometry = initWindowGeometry();
    939                 Dimension storedSize = geometry.getSize();
    940                 Dimension size = getSize();
    941                 if (!storedSize.equals(size)) {
    942                     if (storedSize.width < size.width) {
    943                         storedSize.width = size.width;
    944                     }
    945                     if (storedSize.height != size.height) {
    946                         storedSize.height = size.height;
    947                     }
    948                     rememberWindowGeometry(geometry);
    949                 }
    950                 if (keys != null) {
    951                     keys.setFixedLocale(PROPERTY_FIX_TAG_LOCALE.get());
    952                 }
    953             }
    954             super.setVisible(visible);
    955         }
    956 
    957         /**
    958         * Create a focus handling adapter and apply in to the editor component of value
    959         * autocompletion box.
    960         * @param autocomplete Manager handling the autocompletion
    961         * @param comparator Class to decide what values are offered on autocompletion
    962         * @return The created adapter
    963         */
    964         protected FocusAdapter addFocusAdapter(final AutoCompletionManager autocomplete, final Comparator<AutoCompletionListItem> comparator) {
    965             // get the combo box' editor component
    966             JTextComponent editor = (JTextComponent) values.getEditor().getEditorComponent();
    967             // Refresh the values model when focus is gained
    968             FocusAdapter focus = new FocusAdapter() {
    969                 @Override
    970                 public void focusGained(FocusEvent e) {
    971                     String key = keys.getEditor().getItem().toString();
    972 
    973                     List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
    974                     Collections.sort(valueList, comparator);
    975 
    976                     values.setPossibleACItems(valueList);
    977                     values.getEditor().selectAll();
    978                 }
    979             };
    980             editor.addFocusListener(focus);
    981             return focus;
    982         }
    983 
    984         protected JPopupMenu popupMenu = new JPopupMenu() {
    985             JCheckBoxMenuItem fixTagLanguageCb = new JCheckBoxMenuItem(
    986                     new AbstractAction(tr("Use English language for tag by default")) {
    987                         @Override
    988                         public void actionPerformed(ActionEvent e) {
    989                             boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
    990                             PROPERTY_FIX_TAG_LOCALE.put(sel);
    991                         }
    992                     });
    993             {
    994                 add(fixTagLanguageCb);
    995                 fixTagLanguageCb.setState(PROPERTY_FIX_TAG_LOCALE.get());
    996             }
    997         };
    998     }
    999 
    1000     class ModelSettingsDialog extends JPanel {
    1001 
    1002         private final JLabel chooseModelLabel;
    1003         private final JButton chooseModelButton;
    1004         private final JTextField chooseModelTextField;
    1005 
    1006         private final DefaultListModel<String> combinationDefaultListModel = new DefaultListModel<>();
    1007         private final JList<String> modelCombinationList = new JList<>(combinationDefaultListModel);
    1008         private final JPanel modelCombinationPanel;
    1009         private final JPanel weightsPanel;
    1010         private final JCheckBox useModelCombinationCheckbox;
    1011         private final JButton acceptWeightsButton;
    1012         private final JButton resetWeightsButton;
    1013         private final JButton removeSelectedModelButton;
    1014         private Map<JTextField, String> weightFieldsAndPaths = new HashMap<>();
    1015         private final Map<String, Double> normalizedPathsAndWeights = new HashMap<>();
    1016         private final JOptionPane pane;
    1017         private final JDialog dlg;
    1018         private final JPanel mainPanel;
    1019         private final JPanel singleSelectionPanel;
    1020         private final JPanel setResetWeightsPanel;
    1021         private final JScrollPane combinationScrollPane;
    1022         private final JScrollPane singleSelectionScrollPane;
    1023         private final TitledBorder modelTitle;
    1024         private final TitledBorder weightTitle;
    1025         private final TitledBorder combineTitle;
    1026         private final Dimension singleSelectionDimension;
    1027         private final Dimension modelCombinationDimension;
    1028         private final Dimension mainPanelDimension;
    1029 
    1030         ModelSettingsDialog(Collection<OsmPrimitive> sel1, final AddTagsDialog addDialog) {
    1031 
    1032             loadPreviousCombinedSVMModel();
    1033             singleSelectionDimension = new Dimension(470, 70);
    1034             modelCombinationDimension = new Dimension(450, 250);
    1035             mainPanelDimension = new Dimension(600, 350);
    1036 
    1037             //------- <NORTH of main> ---------//
    1038             mainPanel = new JPanel(new BorderLayout(10, 10));
    1039             singleSelectionPanel = new JPanel(new BorderLayout(10, 10));
    1040             setResetWeightsPanel = new JPanel();
    1041 
    1042             chooseModelLabel = new JLabel("Choose a Model:");
    1043             chooseModelTextField = new JTextField();
    1044             chooseModelButton = new JButton("...");
    1045             chooseModelTextField.setText(MODEL_PATH);
    1046 
    1047             singleSelectionPanel.add(chooseModelLabel, BorderLayout.NORTH);
    1048             singleSelectionPanel.add(chooseModelTextField, BorderLayout.WEST);
    1049             singleSelectionPanel.add(chooseModelButton, BorderLayout.EAST);
    1050 
    1051             singleSelectionScrollPane = new JScrollPane(singleSelectionPanel);
    1052             singleSelectionScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    1053             singleSelectionScrollPane.setPreferredSize(singleSelectionDimension);
    1054 
    1055             //------- </NORTH of main> ---------//
    1056 
    1057             //------- <WEST of main> ---------//
    1058             modelCombinationList.setFixedCellHeight(20);
    1059             modelCombinationList.setEnabled(false);
    1060             modelCombinationPanel = new JPanel(new BorderLayout(10, 10));
    1061 
    1062             weightsPanel = new JPanel();
    1063             weightsPanel.setLayout(new BoxLayout(weightsPanel, BoxLayout.Y_AXIS));
    1064             weightsPanel.setEnabled(false);
    1065 
    1066 
    1067             acceptWeightsButton = new JButton("Set Weights/Normalize");
    1068             resetWeightsButton = new JButton("Reset Weights");
    1069             removeSelectedModelButton = new JButton("Remove Selected");
    1070             setResetWeightsPanel.add(acceptWeightsButton);
    1071             setResetWeightsPanel.add(resetWeightsButton);
    1072             setResetWeightsPanel.add(removeSelectedModelButton);
    1073             removeSelectedModelButton.setEnabled(false);
    1074             acceptWeightsButton.setEnabled(false);
    1075             resetWeightsButton.setEnabled(false);
    1076 
    1077             modelCombinationPanel.add(modelCombinationList, BorderLayout.CENTER);
    1078             modelCombinationPanel.add(weightsPanel, BorderLayout.EAST);
    1079             modelCombinationPanel.add(setResetWeightsPanel, BorderLayout.SOUTH);
    1080 
    1081             combinationScrollPane = new JScrollPane(modelCombinationPanel);
    1082 
    1083             combinationScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    1084             combinationScrollPane.setPreferredSize(modelCombinationDimension);   //new Dimension(450, 250) // w/h
    1085 
    1086             //------- </WEST of main> ---------//
    1087 
    1088             //------- <SOUTH of main> ---------//
    1089             useModelCombinationCheckbox = new JCheckBox("Combine different models?");
    1090 
    1091             //------- </SOUTH of main> ---------//
    1092 
    1093             //------- <Borders> ---------//
    1094             modelTitle = BorderFactory.createTitledBorder("Models");
    1095             weightTitle = BorderFactory.createTitledBorder("W");
    1096             combineTitle = BorderFactory.createTitledBorder("Combine Models");
    1097             modelCombinationList.setBorder(modelTitle);
    1098             weightsPanel.setBorder(weightTitle);
    1099 
    1100             for (Entry<JTextField, String> entry : weightFieldsAndPaths.entrySet()) {
    1101                 combinationDefaultListModel.addElement(entry.getValue());
    1102 
    1103                 JTextField weightTextField = new JTextField("0.00");
    1104                 weightTextField.setMaximumSize(new Dimension(80, 20));
    1105                 weightsPanel.add(entry.getKey());
    1106             }
    1107 
    1108             //modelCombinationPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1109             modelCombinationPanel.setBorder(combineTitle);
    1110             singleSelectionPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1111             //------- </Borders> ---------//
    1112 
    1113             chooseModelButton.addActionListener(new java.awt.event.ActionListener() {
    1114                 @Override
    1115                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1116                     modelChooserButtonActionPerformed(evt);
    1117                 }
    1118             });
    1119 
    1120             useModelCombinationCheckbox.addActionListener(new java.awt.event.ActionListener() {
    1121                 @Override
    1122                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1123                     userCombinationCheckboxActionPerformed(evt);
    1124                 }
    1125             });
    1126 
    1127             acceptWeightsButton.addActionListener(new java.awt.event.ActionListener() {
    1128                 @Override
    1129                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1130                     acceptWeightsButtonActionPerformed(evt);
    1131                 }
    1132             });
    1133 
    1134             resetWeightsButton.addActionListener(new java.awt.event.ActionListener() {
    1135                 @Override
    1136                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1137                     resetWeightsButtonActionPerformed(evt);
    1138                 }
    1139             });
    1140 
    1141             removeSelectedModelButton.addActionListener(new java.awt.event.ActionListener() {
    1142                 @Override
    1143                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1144                     removeSelectedModelButtonActionPerformed(evt);
    1145                 }
    1146             });
    1147             mainPanel.add(singleSelectionScrollPane, BorderLayout.NORTH);
    1148             mainPanel.add(combinationScrollPane, BorderLayout.CENTER);
    1149             mainPanel.add(useModelCombinationCheckbox, BorderLayout.SOUTH);
    1150 
    1151             mainPanel.setPreferredSize(mainPanelDimension);
    1152 
    1153             this.add(mainPanel);
    1154 
    1155             pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
    1156                 @Override
    1157                 public void setValue(Object newValue) {
    1158                     super.setValue(newValue);
    1159                     if (newValue instanceof Integer && (int) newValue == 0 && useModelCombinationCheckbox.isSelected()) {
    1160                         System.out.println("model settings button value: " + newValue);
    1161                         System.out.println("\nUSE COMBINED MODEL\n");
    1162                         useCombinedModel = true;
    1163                         useCustomSVMModel = false;
    1164 
    1165                         addDialog.loadSVMmodel();
    1166                         addDialog.createOSMObject(sel);
    1167                         saveCombinedModel();
    1168                         dlg.setVisible(false);
    1169                     } else if (newValue instanceof Integer && (int) newValue == -1 && useModelCombinationCheckbox.isSelected()) {
    1170                         System.out.println("model settings button value: " + newValue);
    1171                         useCombinedModel = false;
    1172                         useCustomSVMModel = false;
    1173                         System.out.println("Use combined model");
    1174 
    1175                         addDialog.loadSVMmodel();
    1176                         addDialog.createOSMObject(sel);
    1177                         dlg.setVisible(false);
    1178                     } else if (newValue instanceof Integer && (int) newValue == 0 && !useModelCombinationCheckbox.isSelected()) {
    1179                         System.out.println("model settings button value: " + newValue);
    1180                         System.out.println("Don t use combined model, use custom model");
    1181                         useCombinedModel = false;
    1182                         useCustomSVMModel = true;
    1183                         addDialog.loadSVMmodel();
    1184                         addDialog.createOSMObject(sel);
    1185                         dlg.setVisible(false);
    1186                     } else if (newValue instanceof Integer && (int) newValue == -1 && !useModelCombinationCheckbox.isSelected()) {
    1187                         System.out.println("model settings button value: " + newValue);
    1188                         System.out.println("Don t use combined model, use custom model");
    1189                         useCombinedModel = false;
    1190                         useCustomSVMModel = false;
    1191                         addDialog.loadSVMmodel();
    1192                         addDialog.createOSMObject(sel);
    1193                         dlg.setVisible(false);
    1194                     } else if (newValue == null || newValue.equals("uninitializedValue")) {
    1195                         System.out.println("uninitializedValue, do nothing");
    1196                     }
    1197                 }
    1198             };
    1199 
    1200             dlg = pane.createDialog(Main.parent, tr("Model Settings"));
    1201             dlg.setVisible(true);
    1202         }
    1203 
    1204         public void makeVisible(boolean visible) {
    1205             dlg.setVisible(true);
    1206         }
    1207 
    1208         private void modelChooserButtonActionPerformed(ActionEvent evt) {
    1209 
    1210             try {
    1211                 final File file = new File(chooseModelTextField.getText());
    1212                 final JFileChooser fileChooser = new JFileChooser(file);
    1213 
    1214                 final int returnVal = fileChooser.showOpenDialog(this);
    1215                 if (returnVal == JFileChooser.APPROVE_OPTION) {
    1216                     chooseModelTextField.setText(fileChooser.getSelectedFile().getAbsolutePath());
    1217                     useCustomSVMModel = true;
    1218                     customSVMModelPath = fileChooser.getSelectedFile().getAbsolutePath();
    1219                 }
    1220 
    1221                 if (useModelCombinationCheckbox.isSelected()) {
    1222                     String svmModelPath = fileChooser.getSelectedFile().getAbsolutePath();
    1223                     String svmModelText;
    1224                     if (System.getProperty("os.name").contains("ux")) {
    1225                         if (svmModelPath.contains("/")) {
    1226                             svmModelText = svmModelPath.substring(svmModelPath.lastIndexOf("/"));
    1227                         } else {
    1228                             svmModelText = svmModelPath;
    1229                         }
    1230                     } else {
    1231                         if (svmModelPath.contains("\\")) {
    1232                             svmModelText = svmModelPath.substring(svmModelPath.lastIndexOf("\\"));
    1233                         } else {
    1234                             svmModelText = svmModelPath;
    1235                         }
    1236                     }
    1237                     combinationDefaultListModel.addElement(svmModelText);
    1238                     JTextField weightTextField = new JTextField("0.00");
    1239                     weightFieldsAndPaths.put(weightTextField, svmModelPath);
    1240                     System.out.println("weights size: " + weightFieldsAndPaths.size());
    1241 
    1242                     weightTextField.setMaximumSize(new Dimension(80, 20));
    1243                     weightsPanel.add(weightTextField);
    1244                     //add additional textbox
    1245                 }
    1246             } catch (RuntimeException ex) {
    1247                 Main.warn(ex);
    1248             }
    1249         }
    1250 
    1251         private void userCombinationCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
    1252 
    1253             if (useModelCombinationCheckbox.isSelected()) {
    1254                 useCombinedModel = true;
    1255                 useCustomSVMModel = false; //reseting the selected custom SVM model only here
    1256                 removeSelectedModelButton.setEnabled(true);
    1257                 acceptWeightsButton.setEnabled(true);
    1258                 resetWeightsButton.setEnabled(true);
    1259 
    1260                 chooseModelTextField.setEnabled(false);
    1261                 modelCombinationList.setEnabled(true);
    1262                 weightsPanel.setEnabled(true);
    1263                 Component[] weightPanelComponents = weightsPanel.getComponents();
    1264                 for (Component weightPanelComponent : weightPanelComponents) {
    1265                     weightPanelComponent.setEnabled(true);
    1266                 }
    1267             } else {
    1268                 useCombinedModel = false;
    1269                 useCustomSVMModel = true;
    1270                 removeSelectedModelButton.setEnabled(false);
    1271                 acceptWeightsButton.setEnabled(false);
    1272                 resetWeightsButton.setEnabled(false);
    1273 
    1274                 chooseModelTextField.setEnabled(true);
    1275                 modelCombinationList.setEnabled(false);
    1276                 weightsPanel.setEnabled(false);
    1277                 Component[] weightPanelComponents = weightsPanel.getComponents();
    1278                 for (Component weightPanelComponent : weightPanelComponents) {
    1279                     weightPanelComponent.setEnabled(false);
    1280                 }
    1281             }
    1282         }
    1283 
    1284         private void acceptWeightsButtonActionPerformed(ActionEvent evt) {
    1285             int weightsCount = 0;
    1286             removeSelectedModelButton.setEnabled(false);
    1287             double weightSum = 0;
    1288             for (JTextField weightField : weightFieldsAndPaths.keySet()) {
    1289                 if (weightField.getText().equals("")) {
    1290                     weightField.setText("0.00");
    1291                 }
    1292 
    1293                 try {
    1294                     //TODO replace "," with "." to parse doubles with commas
    1295                     Double weightValue = Double.parseDouble(weightField.getText());
    1296 
    1297                     weightValue = Math.abs(weightValue);
    1298                     weightSum += weightValue;
    1299                 } catch (NumberFormatException ex) {
    1300                     Main.warn(ex);
    1301                 }
    1302                 weightsCount++;
    1303             }
    1304 
    1305             if (!filesAndWeights.isEmpty()) {
    1306                 filesAndWeights.clear();
    1307             }
    1308 
    1309             for (JTextField weightField : weightFieldsAndPaths.keySet()) {
    1310                 try {
    1311                     Double weightValue = Double.parseDouble(weightField.getText());
    1312 
    1313                     weightValue = Math.abs(weightValue)/weightSum; //normalize
    1314 
    1315                     if (weightSum == 0) {
    1316                         weightValue = 1.0/weightsCount;
    1317                     }
    1318 
    1319                     weightField.setText(new DecimalFormat("#.##").format(weightValue));
    1320                     normalizedPathsAndWeights.put(weightFieldsAndPaths.get(weightField), weightValue);
    1321                     filesAndWeights.put(new File(weightFieldsAndPaths.get(weightField)), weightValue);
    1322                     System.out.println("normalized: " + weightFieldsAndPaths.get(weightField) + "->" + weightValue);
    1323                     weightField.setEnabled(false);
    1324 
    1325                 } catch (NumberFormatException ex) {
    1326                     Main.warn(ex);
    1327                 }
    1328             }
    1329 
    1330             useCombinedModel = true;
    1331             useCustomSVMModel = false;
    1332         }
    1333 
    1334         private void resetWeightsButtonActionPerformed(ActionEvent evt) {
    1335             removeSelectedModelButton.setEnabled(true);
    1336             for (JTextField weightField : weightFieldsAndPaths.keySet()) {
    1337                 weightField.setEnabled(true);
    1338             }
    1339         }
    1340 
    1341         private void removeSelectedModelButtonActionPerformed(ActionEvent evt) {
    1342             int index = modelCombinationList.getSelectedIndex();
    1343             String modelToBeRemoved = combinationDefaultListModel.get(index);
    1344             combinationDefaultListModel.remove(index);
    1345             System.out.println("model to be removed: " + modelToBeRemoved);
    1346 
    1347             Iterator<Entry<JTextField, String>> it = weightFieldsAndPaths.entrySet().iterator();
    1348             while (it.hasNext()) {
    1349                 Entry<JTextField, String> en = it.next();
    1350                 if (en.getValue().equals(modelToBeRemoved)) {
    1351                     it.remove();
    1352                 }
    1353             }
    1354             System.out.println("model to be removed: " + modelToBeRemoved);
    1355 
    1356             weightsPanel.remove(index);
    1357             weightsPanel.revalidate();
    1358             weightsPanel.repaint();
    1359         }
    1360 
    1361         @SuppressWarnings("unchecked")
    1362         private void loadPreviousCombinedSVMModel() {
    1363             File combinedModelClassesFile = new File(combinedModelClasses);
    1364 
    1365             if (combinedModelClassesFile.exists()) {
    1366                 FileInputStream fileIn = null;
    1367                 ObjectInputStream in = null;
    1368                 try {
    1369                     fileIn = new FileInputStream(combinedModelClassesFile);
    1370                     in = new ObjectInputStream(fileIn);
    1371                     weightFieldsAndPaths = (Map<JTextField, String>) in.readObject();
    1372                 } catch (FileNotFoundException ex) {
    1373                     Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    1374                 } catch (IOException | ClassNotFoundException ex) {
    1375                     Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    1376                 } finally {
    1377                     try {
    1378                         if (in != null) {
    1379                             in.close();
    1380                         }
    1381                         if (fileIn != null) {
    1382                             fileIn.close();
    1383                         }
    1384 
    1385                     } catch (IOException ex) {
    1386                         Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    1387                     }
    1388                 }
    1389             } else {
    1390                 try {
    1391                     combinedModelClassesFile.createNewFile();
    1392                 } catch (IOException ex) {
    1393                     Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    1394                 }
    1395             }
    1396         }
    1397 
    1398         private void saveCombinedModel() {
    1399             try (FileOutputStream fileOut = new FileOutputStream(combinedModelClasses);
    1400                     ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
    1401                 out.writeObject(weightFieldsAndPaths);
    1402             } catch (IOException e) {
    1403                 System.out.println("serialize error" + e);
    1404             }
    1405         }
    1406     }
    1407 
    1408     class AddTagsDialog extends AbstractTagsDialog {
    1409         List<JosmAction> recentTagsActions = new ArrayList<>();
    1410 
    1411         // Counter of added commands for possible undo
    1412         private int commandCount;
    1413         private final JLabel recommendedClassesLabel;
    1414         private final JButton modelSettingsButton;
    1415         private final JButton addAndContinueButton;
    1416         private final DefaultListModel<String> model;
    1417         private final JList<String> categoryList;
    1418         private Model modelSVM;
    1419         private int modelSVMLabelSize;
    1420         private int[] modelSVMLabels;
    1421         private Map<String, String> mappings;
    1422         private Map<String, Integer> mapperWithIDs;
    1423         private Map<Integer, String> idsWithMappings;
    1424         private List<String> textualList = new ArrayList<>();
    1425         private final JCheckBox useTagsCheckBox;
    1426         private ModelSettingsDialog modelSettingsDialog;
    1427         private static final int RECOMMENDATIONS_SIZE = 10;
    1428 
    1429         AddTagsDialog() {
    1430             super(Main.parent, tr("Add value?"), new String[] {tr("OK"), tr("Cancel")});
    1431             setButtonIcons(new String[] {"ok", "cancel"});
    1432             setCancelButton(2);
    1433             configureContextsensitiveHelp("/Dialog/AddValue", true /* show help button */);
    1434             final AddTagsDialog addTagsDialog = this;
    1435 
    1436             loadOntology();
    1437             //if the user did not train a model by running the training process
    1438             //the list does not exist in a file and so we load the default list from the jar.
    1439 
    1440             System.out.println("path for textual: " + TEXTUAL_LIST_PATH);
    1441             File textualListFile = new File(TEXTUAL_LIST_PATH);
    1442             if (textualListFile.exists()) {
    1443                 loadTextualList(textualListFile);
    1444             } else {
    1445                 loadDefaultTextualList();
    1446             }
    1447 
    1448             //if training process has not been performed, we use two sample SVM models, extracted from the jar
    1449 
    1450             JPanel splitPanel = new JPanel(new BorderLayout(10, 10));
    1451             JPanel mainPanel = new JPanel(new GridBagLayout()); //original panel, will be wrapped by the splitPanel
    1452             JPanel recommendPanel = new JPanel(new BorderLayout(10, 10));   //will contain listPanel, action panel
    1453             JPanel listPanel = new JPanel(new BorderLayout(10, 10)); //class recommend label, recommendation list
    1454             JPanel actionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); //model selection buttons or configuration
    1455 
    1456             addAndContinueButton = new JButton("Add and continue");
    1457             modelSettingsButton = new JButton("Model Settings");
    1458             useTagsCheckBox = new JCheckBox("Predict using tags");
    1459             recommendedClassesLabel = new JLabel("Recommended Classes:");
    1460 
    1461             addAndContinueButton.addActionListener(new java.awt.event.ActionListener() {
    1462                 @Override
    1463                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1464                     String selectedClass = categoryList.getSelectedValue();
    1465                     addAndContinueButtonActionPerformed(evt, selectedClass);
    1466 
    1467                     //reconstruct vector for instance and use the model that was trained with classes here
    1468 
    1469                     List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
    1470                     OsmPrimitive s;
    1471 
    1472                     //get a simple selection
    1473                     if (!osmPrimitiveSelection.isEmpty()) {
    1474                         s = osmPrimitiveSelection.get(0);
    1475                         if (s.getInterestingTags().isEmpty()) {
    1476                             //load original model
    1477                             modelWithClasses = false;
    1478                             loadSVMmodel();
    1479                             createOSMObject(sel); //create object without class features
    1480                         } else {
    1481                             //recommend using tags: set the checkbox selected to avoid confusing the user
    1482                             useTagsCheckBox.setSelected(true);
    1483 
    1484                             if (useTagsCheckBox.isSelected()) {
    1485                                 //load model with classes
    1486                                 modelWithClasses = true;
    1487                                 loadSVMmodel();
    1488                                 createOSMObject(sel); //create object including class features
    1489                             } else {
    1490                                 modelWithClasses = false;
    1491                                 loadSVMmodel();
    1492                                 createOSMObject(sel); //create object including class features
    1493                             }
    1494                         }
    1495                     }
    1496                 }
    1497             });
    1498 
    1499             modelSettingsButton.addActionListener(new java.awt.event.ActionListener() {
    1500                 @Override
    1501                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1502                     if (modelSettingsDialog == null) {
    1503                         System.out.println("new modelSettingsDialog");
    1504                         modelSettingsDialog = new ModelSettingsDialog(sel, addTagsDialog);
    1505                     } else {
    1506                         System.out.println("set modelSettingsDialog visible");
    1507                         modelSettingsDialog.makeVisible(true);
    1508                     }
    1509                 }
    1510             });
    1511 
    1512             useTagsCheckBox.addActionListener(new java.awt.event.ActionListener() {
    1513                 @Override
    1514                 public void actionPerformed(java.awt.event.ActionEvent evt) {
    1515                     List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
    1516                     OsmPrimitive s;
    1517                     if (!osmPrimitiveSelection.isEmpty()) {
    1518                         s = osmPrimitiveSelection.get(0);
    1519                         if (s.getInterestingTags().isEmpty()) {
    1520                             //load original model
    1521                             modelWithClasses = false;
    1522                             loadSVMmodel();
    1523                             createOSMObject(sel); //create object without class features
    1524                         } else {
    1525                             //useTagsCheckBox
    1526                             if (useTagsCheckBox.isSelected()) {
    1527                                 //load model with classes
    1528                                 modelWithClasses = true;
    1529                                 loadSVMmodel();
    1530                                 createOSMObject(sel); //create object including class features
    1531                             } else {
    1532                                 modelWithClasses = false;
    1533                                 loadSVMmodel();
    1534                                 createOSMObject(sel); //create object including class features
    1535                             }
    1536                         }
    1537                     }
    1538                 }
    1539             });
    1540 
    1541             keys = new AutoCompletingComboBox();
    1542             values = new AutoCompletingComboBox();
    1543 
    1544             mainPanel.add(new JLabel("<html>"+trn("This will change up to {0} object.",
    1545                     "This will change up to {0} objects.", sel.size(), sel.size())
    1546             +"<br><br>"+tr("Please select a key")), GBC.eol().fill(GBC.HORIZONTAL));
    1547 
    1548             AutoCompletionManager autocomplete = Main.getLayerManager().getEditLayer().data.getAutoCompletionManager();
    1549             List<AutoCompletionListItem> keyList = autocomplete.getKeys();
    1550 
    1551             AutoCompletionListItem itemToSelect = null;
    1552             // remove the object's tag keys from the list
    1553             Iterator<AutoCompletionListItem> iter = keyList.iterator();
    1554             while (iter.hasNext()) {
    1555                 AutoCompletionListItem item = iter.next();
    1556                 if (item.getValue().equals(lastAddKey)) {
    1557                     itemToSelect = item;
    1558                 }
    1559                 for (int i = 0; i < tagData.getRowCount(); ++i) {
    1560                     if (item.getValue().equals(tagData.getValueAt(i, 0))) {
    1561                         if (itemToSelect == item) {
    1562                             itemToSelect = null;
    1563                         }
    1564                         iter.remove();
    1565                         break;
    1566                     }
    1567                 }
    1568             }
    1569 
    1570             Collections.sort(keyList, defaultACItemComparator);
    1571             keys.setPossibleACItems(keyList);
    1572             keys.setEditable(true);
    1573 
    1574             mainPanel.add(keys, GBC.eop().fill());
    1575             mainPanel.add(new JLabel(tr("Please select a value")), GBC.eol());
    1576 
    1577             model = new DefaultListModel<>();
    1578 
    1579             parseTagsMappedToClasses();
    1580 
    1581             List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
    1582             OsmPrimitive s;
    1583             //get a simple selection
    1584             if (!osmPrimitiveSelection.isEmpty()) {
    1585                 s = osmPrimitiveSelection.get(0);
    1586                 File modelDirectory = new File(MODEL_PATH);
    1587                 String modelWithClassesPath = modelDirectory.getAbsolutePath() + "/model_with_classes";
    1588                 File modelWithClassesFile = new File(modelWithClassesPath);
    1589                 if (s.getInterestingTags().isEmpty() || !modelWithClassesFile.exists()) {
    1590                     modelWithClasses = false;
    1591                     loadSVMmodel(); //load original model
    1592                     createOSMObject(sel); //create object without class features
    1593                 } else {
    1594                     //recommend using tags: set the checkbox selected to avoid confusing the user
    1595                     useTagsCheckBox.setSelected(true);
    1596                     modelWithClasses = true;
    1597                     loadSVMmodel(); //load model with classes
    1598                     createOSMObject(sel); //create object including class features
    1599                 }
    1600             }
    1601 
    1602             categoryList = new JList<>(model);
    1603 
    1604             ListSelectionListener listSelectionListener = new ListSelectionListener() {
    1605                 @Override
    1606                 public void valueChanged(ListSelectionEvent listSelectionEvent) {
    1607                     if (!listSelectionEvent.getValueIsAdjusting()) { //This prevents double events
    1608 
    1609                         String selectedClass = categoryList.getSelectedValue();
    1610 
    1611                         if (selectedClass != null) { //null check, because the model is cleared after a new recommendation
    1612                             //tags become unselected
    1613                             if ((selectedClass.indexOf(" ")+1) > 0) {
    1614                                 //add both key + value in tags
    1615                                 String keyTag = selectedClass.substring(0, selectedClass.indexOf(" "));
    1616                                 String valueTag = selectedClass.substring(selectedClass.indexOf(" ")+1, selectedClass.length());
    1617                                 keys.setSelectedItem(keyTag); //adding selected tags to textBoxes
    1618                                 values.setSelectedItem(valueTag);
    1619                             } else {
    1620                                 //value does not have a value, add the key tag only
    1621                                 String keyTag = selectedClass; //test it
    1622                                 keys.setSelectedItem(keyTag);
    1623                                 values.setSelectedItem("");
    1624                             }
    1625                         }
    1626                     }
    1627                 }
    1628             };
    1629 
    1630             categoryList.addListSelectionListener(listSelectionListener);
    1631             categoryList.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1632             categoryList.setModel(model);
    1633 
    1634             values.setEditable(true);
    1635             mainPanel.add(values, GBC.eop().fill());
    1636             if (itemToSelect != null) {
    1637                 keys.setSelectedItem(itemToSelect);
    1638                 if (lastAddValue != null) {
    1639                     values.setSelectedItem(lastAddValue);
    1640                 }
    1641             }
    1642 
    1643             FocusAdapter focus = addFocusAdapter(autocomplete, defaultACItemComparator);
    1644             // fire focus event in advance or otherwise the popup list will be too small at first
    1645             focus.focusGained(null);
    1646 
    1647             int recentTagsToShow = PROPERTY_RECENT_TAGS_NUMBER.get();
    1648             if (recentTagsToShow > MAX_LRU_TAGS_NUMBER) {
    1649                 recentTagsToShow = MAX_LRU_TAGS_NUMBER;
    1650             }
    1651 
    1652             suggestRecentlyAddedTags(mainPanel, recentTagsToShow, focus);
    1653 
    1654             mainPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1655             listPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1656             splitPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
    1657 
    1658             listPanel.add(recommendedClassesLabel, BorderLayout.NORTH);
    1659             listPanel.add(categoryList, BorderLayout.SOUTH);
    1660             actionsPanel.add(addAndContinueButton);
    1661             actionsPanel.add(modelSettingsButton);
    1662             actionsPanel.add(useTagsCheckBox);
    1663 
    1664             recommendPanel.add(actionsPanel, BorderLayout.WEST);
    1665             recommendPanel.add(listPanel, BorderLayout.NORTH);
    1666 
    1667             splitPanel.add(mainPanel, BorderLayout.WEST);
    1668             splitPanel.add(recommendPanel, BorderLayout.EAST);
    1669 
    1670             setContent(splitPanel, false);
    1671 
    1672             popupMenu.add(new AbstractAction(tr("Set number of recently added tags")) {
    1673                 @Override
    1674                 public void actionPerformed(ActionEvent e) {
    1675                     selectNumberOfTags();
    1676                 }
    1677             });
    1678             JCheckBoxMenuItem rememberLastTags = new JCheckBoxMenuItem(
    1679                     new AbstractAction(tr("Remember last used tags after a restart")) {
    1680                         @Override
    1681                         public void actionPerformed(ActionEvent e) {
    1682                             boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
    1683                             PROPERTY_REMEMBER_TAGS.put(sel);
    1684                             if (sel) saveTagsIfNeeded();
    1685                         }
    1686                     });
    1687             rememberLastTags.setState(PROPERTY_REMEMBER_TAGS.get());
    1688             popupMenu.add(rememberLastTags);
    1689         }
    1690 
    1691         private void addAndContinueButtonActionPerformed(ActionEvent evt, String selectedClass) {
    1692             performTagAdding();
    1693         }
    1694 
    1695         private void selectNumberOfTags() {
    1696             String s = JOptionPane.showInputDialog(this, tr("Please enter the number of recently added tags to display"));
    1697             if (s != null) try {
    1698                 int v = Integer.parseInt(s);
    1699                 if (v >= 0 && v <= MAX_LRU_TAGS_NUMBER) {
    1700                     PROPERTY_RECENT_TAGS_NUMBER.put(v);
    1701                     return;
    1702                 }
    1703             } catch (NumberFormatException ex) {
    1704                 Main.warn(ex);
    1705             }
    1706             JOptionPane.showMessageDialog(this, tr("Please enter integer number between 0 and {0}", MAX_LRU_TAGS_NUMBER));
    1707         }
    1708 
    1709         private void suggestRecentlyAddedTags(JPanel mainPanel, int tagsToShow, final FocusAdapter focus) {
    1710             if (!(tagsToShow > 0 && !recentTags.isEmpty()))
    1711                 return;
    1712 
    1713             mainPanel.add(new JLabel(tr("Recently added tags")), GBC.eol());
    1714 
    1715             int count = 1;
    1716             // We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
    1717             // This implies to iterate in descending order,
    1718             // as the oldest elements will only be removed after we reach the maximum numbern and not the number of tags to show.
    1719             // However, as Set does not allow to iterate in descending order,
    1720             // we need to copy its elements into a List we can access in reverse order.
    1721             List<Tag> tags = new LinkedList<>(recentTags.keySet());
    1722             for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
    1723                 final Tag t = tags.get(i);
    1724                 // Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
    1725                 String scKey = "properties:recent:"+count;
    1726                 String scsKey = "properties:recent:shift:"+count;
    1727                 Shortcut sc = Shortcut.registerShortcut(scKey, tr("Choose recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL);
    1728                 final JosmAction action = new JosmAction(scKey, null, tr("Use this tag again"), sc, false) {
    1729                     @Override
    1730                     public void actionPerformed(ActionEvent e) {
    1731                         keys.setSelectedItem(t.getKey());
    1732                         // fix #7951, #8298 - update list of values before setting value (?)
    1733                         focus.focusGained(null);
    1734                         values.setSelectedItem(t.getValue());
    1735                     }
    1736                 };
    1737                 Shortcut scs = Shortcut.registerShortcut(scsKey, tr("Apply recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL_SHIFT);
    1738                 final JosmAction actionShift = new JosmAction(scsKey, null, tr("Use this tag again"), scs, false) {
    1739                     @Override
    1740                     public void actionPerformed(ActionEvent e) {
    1741                         action.actionPerformed(null);
    1742                         performTagAdding();
    1743                     }
    1744                 };
    1745                 recentTagsActions.add(action);
    1746                 recentTagsActions.add(actionShift);
    1747                 disableTagIfNeeded(t, action);
    1748                 // Find and display icon
    1749                 ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
    1750                 if (icon == null) {
    1751                     // If no icon found in map style look at presets
    1752                     Map<String, String> map = new HashMap<>();
    1753                     map.put(t.getKey(), t.getValue());
    1754                     // If still nothing display an empty icon
    1755                     if (icon == null) {
    1756                         icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
    1757                     }
    1758                 }
    1759                 GridBagConstraints gbc = new GridBagConstraints();
    1760                 gbc.ipadx = 5;
    1761                 mainPanel.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
    1762                 // Create tag label
    1763                 final String color = action.isEnabled() ? "" : "; color:gray";
    1764                 final JLabel tagLabel = new JLabel("<html>"
    1765                         + "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
    1766                         + "<table><tr><td>" + XmlWriter.encode(t.toString(), true) + "</td></tr></table></html>");
    1767                 if (action.isEnabled()) {
    1768                     // Register action
    1769                     mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), scKey);
    1770                     mainPanel.getActionMap().put(scKey, action);
    1771                     mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(scs.getKeyStroke(), scsKey);
    1772                     mainPanel.getActionMap().put(scsKey, actionShift);
    1773                     // Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
    1774                     tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
    1775                     tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
    1776                     tagLabel.addMouseListener(new MouseAdapter() {
    1777                         @Override
    1778                         public void mouseClicked(MouseEvent e) {
    1779                             action.actionPerformed(null);
    1780                             // add tags and close window on double-click
    1781 
    1782                             if (e.getClickCount() > 1) {
    1783                                 buttonAction(0, null); // emulate OK click and close the dialog
    1784                             }
    1785                             // add tags on Shift-Click
    1786                             if (e.isShiftDown()) {
    1787                                 performTagAdding();
    1788                             }
    1789                         }
    1790                     });
    1791                 } else {
    1792                     // Disable tag label
    1793                     tagLabel.setEnabled(false);
    1794                     // Explain in the tooltip why
    1795                     tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
    1796                 }
    1797                 // Finally add label to the resulting panel
    1798                 JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
    1799                 tagPanel.add(tagLabel);
    1800                 mainPanel.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));
    1801             }
    1802         }
    1803 
    1804         public void destroyActions() {
    1805             for (JosmAction action : recentTagsActions) {
    1806                 action.destroy();
    1807             }
    1808         }
    1809 
    1810         /**
    1811         * Read tags from comboboxes and add it to all selected objects
    1812         */
    1813         public final void performTagAdding() {
    1814             String key = Tag.removeWhiteSpaces(keys.getEditor().getItem().toString());
    1815             String value = Tag.removeWhiteSpaces(values.getEditor().getItem().toString());
    1816             if (key.isEmpty() || value.isEmpty()) return;
    1817             for (OsmPrimitive osm: sel) {
    1818                 String val = osm.get(key);
    1819                 if (val != null && !val.equals(value)) {
    1820                     if (!warnOverwriteKey(tr("You changed the value of ''{0}'' from ''{1}'' to ''{2}''.", key, val, value),
    1821                             "overwriteAddKey"))
    1822                         return;
    1823                     break;
    1824                 }
    1825             }
    1826             lastAddKey = key;
    1827             lastAddValue = value;
    1828             recentTags.put(new Tag(key, value), null);
    1829             AutoCompletionManager.rememberUserInput(key, value, false);
    1830             commandCount++;
    1831             Main.main.undoRedo.add(new ChangePropertyCommand(sel, key, value));
    1832             changedKey = key;
    1833         }
    1834 
    1835         public void undoAllTagsAdding() {
    1836             Main.main.undoRedo.undo(commandCount);
    1837         }
    1838 
    1839         private void disableTagIfNeeded(final Tag t, final JosmAction action) {
    1840             // Disable action if its key is already set on the object (the key being absent from the keys list for this reason
    1841             // performing this action leads to autocomplete to the next key (see #7671 comments)
    1842             for (int j = 0; j < tagData.getRowCount(); ++j) {
    1843                 if (t.getKey().equals(tagData.getValueAt(j, 0))) {
    1844                     action.setEnabled(false);
    1845                     break;
    1846                 }
    1847             }
    1848         }
    1849 
    1850         private void loadSVMmodel() {
    1851             File modelDirectory = new File(MODEL_PATH);
    1852             File modelFile;
    1853             if (useCombinedModel) {
    1854                 if (filesAndWeights.isEmpty()) {
    1855                     System.out.println("No models selected! Loading defaults..");
    1856                     if (modelWithClasses) {
    1857                         System.out.println("Using default/last model with classes: " + modelDirectory.getAbsolutePath() + "/model_with_classes");
    1858                         modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
    1859                         try {
    1860                             System.out.println("try to load model: " + modelFile.getAbsolutePath());
    1861                             modelSVM = Model.load(modelFile);
    1862                             System.out.println("model loaded!");
    1863 
    1864                         } catch (IOException ex) {
    1865                             Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    1866                         }
    1867                         modelSVMLabelSize = modelSVM.getLabels().length;
    1868                         modelSVMLabels = modelSVM.getLabels();
    1869                     } else {
    1870                         System.out.println("Using default/last model without classes: " + modelDirectory.getAbsolutePath() + "/best_model");
    1871                         modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
    1872                         try {
    1873                             System.out.println("try to load model: " + modelFile.getAbsolutePath());
    1874                             modelSVM = Model.load(modelFile);
    1875                             System.out.println("model loaded!");
    1876 
    1877                         } catch (IOException ex) {
    1878                             Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    1879                         }
    1880                         modelSVMLabelSize = modelSVM.getLabels().length;
    1881                         modelSVMLabels = modelSVM.getLabels();
    1882                     }
    1883                 }
    1884                 if (modelWithClasses) { //check filenames to define if model with classes is selected
    1885                     System.out.println("Using combined model with classes");
    1886                     useCombinedSVMmodels(sel, true);
    1887                 } else {
    1888                     System.out.println("Using combined model without classes");
    1889                     useCombinedSVMmodels(sel, false);
    1890                 }
    1891             } else if (useCustomSVMModel) {
    1892                 System.out.println("custom path: " + customSVMModelPath);
    1893                 File checkExistance = new File(customSVMModelPath);
    1894                 if (checkExistance.exists() && checkExistance.isFile()) {
    1895                     if (modelWithClasses) {
    1896                         System.out.println("Using custom model with classes: ");
    1897                         if (customSVMModelPath.endsWith(".0")) {
    1898                             String customSVMModelPathWithClasses = customSVMModelPath.substring(0, customSVMModelPath.length() - 2) + ".1";
    1899 
    1900                             modelFile = new File(customSVMModelPathWithClasses);
    1901                             System.out.println(customSVMModelPathWithClasses);
    1902                         } else {
    1903                             modelFile = new File(customSVMModelPath);
    1904                         }
    1905                     } else {
    1906                         System.out.println("Using custom model without classes");
    1907                         if (customSVMModelPath.endsWith(".1")) {
    1908                             String customSVMModelPathWithoutClasses = customSVMModelPath.substring(0, customSVMModelPath.length() - 2) + ".0";
    1909                             modelFile = new File(customSVMModelPathWithoutClasses);
    1910                             System.out.println(customSVMModelPathWithoutClasses);
    1911                         } else {
    1912                             modelFile = new File(customSVMModelPath);
    1913                         }
    1914                     }
    1915                     try {
    1916                         System.out.println("try to load model: " + modelFile.getAbsolutePath());
    1917                         modelSVM = Model.load(modelFile);
    1918                         System.out.println("model loaded!");
    1919 
    1920                     } catch (IOException ex) {
    1921                         Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    1922                     }
    1923                     modelSVMLabelSize = modelSVM.getLabels().length;
    1924                     modelSVMLabels = modelSVM.getLabels();
    1925 
    1926                 } else {
    1927                     //user chose to use a custom model, but did not provide a path to a model:
    1928                     if (modelWithClasses) {
    1929                         System.out.println("Using default/last model with classes");
    1930                         modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
    1931                     } else {
    1932                         System.out.println("Using default/last model without classes");
    1933                         modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
    1934                     }
    1935 
    1936                     try {
    1937                         System.out.println("try to load model: " + modelFile.getAbsolutePath());
    1938                         modelSVM = Model.load(modelFile);
    1939                         System.out.println("model loaded!");
    1940 
    1941                     } catch (IOException ex) {
    1942                         Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    1943                     }
    1944                     modelSVMLabelSize = modelSVM.getLabels().length;
    1945                     modelSVMLabels = modelSVM.getLabels();
    1946 
    1947                 }
    1948             } else {
    1949                 if (modelWithClasses) {
    1950                     System.out.println("Using default/last model with classes");
    1951                     modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
    1952                 } else {
    1953                     System.out.println("Using default/last model without classes");
    1954                     modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
    1955                 }
    1956 
    1957                 try {
    1958                     System.out.println("try to load model: " + modelFile.getAbsolutePath());
    1959                     modelSVM = Model.load(modelFile);
    1960                     System.out.println("model loaded!");
    1961 
    1962                 } catch (IOException ex) {
    1963                     Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    1964                 }
    1965                 modelSVMLabelSize = modelSVM.getLabels().length;
    1966                 modelSVMLabels = modelSVM.getLabels();
    1967             }
    1968         }
    1969 
    1970         private void useCombinedSVMmodels(Collection<OsmPrimitive> sel, boolean useClassFeatures) {
    1971             System.out.println("The system will combine " + filesAndWeights.size() + " SVM models.");
    1972 
    1973             MathTransform transform = null;
    1974             GeometryFactory geometryFactory = new GeometryFactory();
    1975             CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
    1976             CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
    1977             try {
    1978                 transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
    1979 
    1980             } catch (FactoryException ex) {
    1981                 Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    1982             }
    1983 
    1984             OSMWay selectedInstance;
    1985             List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
    1986             OsmPrimitive s;
    1987 
    1988             //get a simple selection
    1989             if (!osmPrimitiveSelection.isEmpty()) {
    1990                 s = osmPrimitiveSelection.get(0);
    1991             } else {
    1992                 return;
    1993             }
    1994 
    1995             selectedInstance = new OSMWay();
    1996             for (Way selectedWay : s.getDataSet().getSelectedWays()) {
    1997                 List<Node> selectedWayNodes = selectedWay.getNodes();
    1998                 for (Node node : selectedWayNodes) {
    1999                     node.getCoor();
    2000                     if (node.isLatLonKnown()) {
    2001                         double lat = node.getCoor().lat();
    2002                         double lon = node.getCoor().lon();
    2003 
    2004                         Coordinate sourceCoordinate = new Coordinate(lon, lat);
    2005                         Coordinate targetGeometry = null;
    2006                         try {
    2007                             targetGeometry = JTS.transform(sourceCoordinate, null, transform);
    2008                         } catch (MismatchedDimensionException | TransformException ex) {
    2009                             Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
    2010                         }
    2011 
    2012                         Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
    2013                         selectedInstance.addNodeGeometry(geom);
    2014                     }
    2015                 }
    2016             }
    2017             Geometry fullGeom = geometryFactory.buildGeometry(selectedInstance.getNodeGeometries());
    2018             if ((selectedInstance.getNodeGeometries().size() > 3) &&
    2019                     selectedInstance.getNodeGeometries().get(0).equals(selectedInstance.getNodeGeometries()
    2020                             .get(selectedInstance.getNodeGeometries().size()-1))) {
    2021                 //checks if the beginning and ending node are the same and the number of nodes are more than 3.
    2022                 //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
    2023                 LinearRing linear = geometryFactory.createLinearRing(fullGeom.getCoordinates());
    2024                 Polygon poly = new Polygon(linear, null, geometryFactory);
    2025                 selectedInstance.setGeometry(poly);
    2026 
    2027                 System.out.println("\n\npolygon");
    2028             } else if (selectedInstance.getNodeGeometries().size() > 1) {
    2029                 //it is an open geometry with more than one nodes, make it linestring
    2030                 System.out.println("\n\nlinestring");
    2031                 LineString lineString = geometryFactory.createLineString(fullGeom.getCoordinates());
    2032                 selectedInstance.setGeometry(lineString);
    2033             } else { //we assume all the rest geometries are points
    2034                 System.out.println("\n\npoint");
    2035                 Point point = geometryFactory.createPoint(fullGeom.getCoordinate());
    2036                 selectedInstance.setGeometry(point);
    2037             }
    2038 
    2039             Map<String, String> selectedTags = s.getInterestingTags();
    2040             selectedInstance.setAllTags(selectedTags);
    2041 
    2042             //construct vector
    2043             if (selectedInstance != null) {
    2044                 int id;
    2045 
    2046                 OSMClassification classifier = new OSMClassification();
    2047                 classifier.calculateClasses(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
    2048 
    2049                 if (useClassFeatures) {
    2050                     ClassFeatures classFeatures = new ClassFeatures();
    2051                     classFeatures.createClassFeatures(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
    2052                     id = 1422;
    2053                 } else {
    2054                     id = 1;
    2055                 }
    2056 
    2057                 GeometryFeatures geometryFeatures = new GeometryFeatures(id);
    2058                 geometryFeatures.createGeometryFeatures(selectedInstance);
    2059                 id = geometryFeatures.getLastID();
    2060                 TextualFeatures textualFeatures = new TextualFeatures(id, textualList, languageDetector);
    2061                 textualFeatures.createTextualFeatures(selectedInstance);
    2062 
    2063                 List<FeatureNode> featureNodeList = selectedInstance.getFeatureNodeList();
    2064 
    2065                 FeatureNode[] featureNodeArray = new FeatureNode[featureNodeList.size()];
    2066 
    2067                 int i = 0;
    2068                 for (FeatureNode featureNode : featureNodeList) {
    2069                     featureNodeArray[i] = featureNode;
    2070                     i++;
    2071                 }
    2072                 FeatureNode[] testInstance2 = featureNodeArray;
    2073 
    2074                 //compute prediction list for every model
    2075                 int[] ranks = new int[10];
    2076 
    2077                 for (int l = 0; l < 10; l++) {
    2078                     ranks[l] = 10-l; //init from 10 to 1
    2079                 }
    2080 
    2081                 Map<String, Double> scoreMap = new HashMap<>();
    2082 
    2083                 Map<File, Double> alignedFilesAndWeights = getAlignedModels(filesAndWeights);
    2084 
    2085                 for (File modelFile : alignedFilesAndWeights.keySet()) {
    2086 
    2087                     try {
    2088                         modelSVM = Model.load(modelFile);
    2089                     } catch (IOException ex) {
    2090                         Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
    2091                     }
    2092                     modelSVMLabelSize = modelSVM.getLabels().length;
    2093                     modelSVMLabels = modelSVM.getLabels();
    2094 
    2095                     Map<Integer, Integer> mapLabelsToIDs = new HashMap<>();
    2096                     for (int h = 0; h < modelSVMLabelSize; h++) {
    2097                         mapLabelsToIDs.put(modelSVMLabels[h], h);
    2098                     }
    2099                     double[] scores = new double[modelSVMLabelSize];
    2100                     Linear.predictValues(modelSVM, testInstance2, scores);
    2101 
    2102                     Map<Double, Integer> scoresValues = new HashMap<>();
    2103                     for (int h = 0; h < scores.length; h++) {
    2104                         scoresValues.put(scores[h], h);
    2105                     }
    2106 
    2107                     Arrays.sort(scores);
    2108                     int predicted1 = modelSVMLabels[scoresValues.get(scores[scores.length-1])];
    2109                     int predicted2 = modelSVMLabels[scoresValues.get(scores[scores.length-2])];
    2110                     int predicted3 = modelSVMLabels[scoresValues.get(scores[scores.length-3])];
    2111                     int predicted4 = modelSVMLabels[scoresValues.get(scores[scores.length-4])];
    2112                     int predicted5 = modelSVMLabels[scoresValues.get(scores[scores.length-5])];
    2113                     int predicted6 = modelSVMLabels[scoresValues.get(scores[scores.length-6])];
    2114                     int predicted7 = modelSVMLabels[scoresValues.get(scores[scores.length-7])];
    2115                     int predicted8 = modelSVMLabels[scoresValues.get(scores[scores.length-8])];
    2116                     int predicted9 = modelSVMLabels[scoresValues.get(scores[scores.length-9])];
    2117                     int predicted10 = modelSVMLabels[scoresValues.get(scores[scores.length-10])];
    2118 
    2119                     String[] predictedTags = new String[10];
    2120                     for (Map.Entry<String, Integer> entry : mapperWithIDs.entrySet()) {
    2121 
    2122                         if (entry.getValue().equals(predicted1)) {
    2123                             predictedTags[0] = entry.getKey();
    2124                         } else if (entry.getValue().equals(predicted2)) {
    2125                             predictedTags[1] = entry.getKey();
    2126                         } else if (entry.getValue().equals(predicted3)) {
    2127                             predictedTags[2] = entry.getKey();
    2128                         } else if (entry.getValue().equals(predicted4)) {
    2129                             predictedTags[3] = entry.getKey();
    2130                         } else if (entry.getValue().equals(predicted5)) {
    2131                             predictedTags[4] = entry.getKey();
    2132                         } else if (entry.getValue().equals(predicted6)) {
    2133                             predictedTags[5] = entry.getKey();
    2134                         } else if (entry.getValue().equals(predicted7)) {
    2135                             predictedTags[6] = entry.getKey();
    2136                         } else if (entry.getValue().equals(predicted8)) {
    2137                             predictedTags[7] = entry.getKey();
    2138                         } else if (entry.getValue().equals(predicted9)) {
    2139                             predictedTags[8] = entry.getKey();
    2140                         } else if (entry.getValue().equals(predicted10)) {
    2141                             predictedTags[9] = entry.getKey();
    2142                         }
    2143                     }
    2144                     //clearing model, to add the new computed classes in jlist
    2145                     model.clear();
    2146                     for (Map.Entry<String, String> tag : mappings.entrySet()) {
    2147 
    2148                         for (int k = 0; k < 10; k++) {
    2149                             if (tag.getValue().equals(predictedTags[k])) {
    2150                                 predictedTags[k] = tag.getKey();
    2151                                 model.addElement(tag.getKey());
    2152                             }
    2153                         }
    2154                     }
    2155                     System.out.println("combined, predicted classes: " + Arrays.toString(predictedTags));
    2156 
    2157                     for (int r = 0; r < ranks.length; r++) {
    2158                         String predictedTag = predictedTags[r];
    2159                         Double currentWeight = alignedFilesAndWeights.get(modelFile);
    2160                         double finalRank = ranks[r]*currentWeight;
    2161 
    2162                         if (scoreMap.containsKey(predictedTag)) {
    2163                             Double scoreToAdd = scoreMap.get(predictedTag);
    2164                             scoreMap.put(predictedTag, finalRank+scoreToAdd);
    2165                         } else {
    2166                             scoreMap.put(predictedTag, finalRank);
    2167                         }
    2168                         //add final weight - predicted tag
    2169                     }
    2170                 } //files iter
    2171                 model.clear();
    2172                 List<Double> scoresList = new ArrayList<>(scoreMap.values());
    2173                 Collections.sort(scoresList, Collections.reverseOrder());
    2174 
    2175                 for (Double sco : scoresList) {
    2176                     if (model.size() > 9) {
    2177                         break;
    2178                     }
    2179                     for (Map.Entry<String, Double> scoreEntry : scoreMap.entrySet()) {
    2180                         if (scoreEntry.getValue().equals(sco)) {
    2181                             model.addElement(scoreEntry.getKey());
    2182                         }
    2183                     }
    2184                 }
    2185             }
    2186         }
    2187 
    2188         private void createOSMObject(Collection<OsmPrimitive> sel) {
    2189 
    2190             MathTransform transform = null;
    2191             GeometryFactory geometryFactory = new GeometryFactory();
    2192             CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
    2193             CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
    2194             try {
    2195                 transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
    2196 
    2197             } catch (FactoryException ex) {
    2198                 Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
    2199             }
    2200 
    2201             //fire an error to the user if he has multiple selection from map
    2202 
    2203             //we consider simple (one instance) selection, so we get the first of the sel list
    2204 
    2205             OSMWay selectedInstance;
    2206             List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
    2207             OsmPrimitive s;
    2208 
    2209             //get a simple selection
    2210             if (!osmPrimitiveSelection.isEmpty()) {
    2211                 s = osmPrimitiveSelection.get(0);
    2212             } else {
    2213                 return;
    2214             }
    2215 
    2216             selectedInstance = new OSMWay();
    2217             for (Way selectedWay : s.getDataSet().getSelectedWays()) {
    2218                 List<Node> selectedWayNodes = selectedWay.getNodes();
    2219                 for (Node node : selectedWayNodes) {
    2220                     node.getCoor();
    2221                     if (node.isLatLonKnown()) {
    2222                         double lat = node.getCoor().lat();
    2223                         double lon = node.getCoor().lon();
    2224 
    2225                         Coordinate sourceCoordinate = new Coordinate(lon, lat);
    2226                         Coordinate targetGeometry = null;
    2227                         try {
    2228                             targetGeometry = JTS.transform(sourceCoordinate, null, transform);
    2229                         } catch (MismatchedDimensionException | TransformException ex) {
    2230                             Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
    2231                         }
    2232 
    2233                         Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
    2234                         selectedInstance.addNodeGeometry(geom);
    2235                     }
    2236                 }
    2237             }
    2238             Geometry fullGeom = geometryFactory.buildGeometry(selectedInstance.getNodeGeometries());
    2239 
    2240             System.out.println("number of nodes: " + selectedInstance.getNodeGeometries().size());
    2241 
    2242             if ((selectedInstance.getNodeGeometries().size() > 3) &&
    2243                     selectedInstance.getNodeGeometries().get(0).equals(selectedInstance.getNodeGeometries()
    2244                             .get(selectedInstance.getNodeGeometries().size()-1))) {
    2245                 //checks if the beginning and ending node are the same and the number of nodes are more than 3.
    2246                 //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
    2247                 LinearRing linear = geometryFactory.createLinearRing(fullGeom.getCoordinates());
    2248                 Polygon poly = new Polygon(linear, null, geometryFactory);
    2249                 selectedInstance.setGeometry(poly);
    2250 
    2251                 System.out.println("\n\npolygon");
    2252             } else if (selectedInstance.getNodeGeometries().size() > 1) {
    2253                 //it is an open geometry with more than one nodes, make it linestring
    2254                 System.out.println("\n\nlinestring");
    2255                 LineString lineString = geometryFactory.createLineString(fullGeom.getCoordinates());
    2256                 selectedInstance.setGeometry(lineString);
    2257             } else { //we assume all the rest geometries are points
    2258                 System.out.println("\n\npoint");
    2259                 Point point = geometryFactory.createPoint(fullGeom.getCoordinate());
    2260                 selectedInstance.setGeometry(point);
    2261             }
    2262 
    2263             Map<String, String> selectedTags = s.getInterestingTags();
    2264             selectedInstance.setAllTags(selectedTags);
    2265 
    2266             //construct vector here
    2267             if (selectedInstance != null) {
    2268                 int id;
    2269                 if (mappings == null) {
    2270                     System.out.println("null mappings ERROR");
    2271                 }
    2272 
    2273                 OSMClassification classifier = new OSMClassification();
    2274                 classifier.calculateClasses(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
    2275 
    2276                 if (modelWithClasses) {
    2277                     ClassFeatures classFeatures = new ClassFeatures();
    2278                     classFeatures.createClassFeatures(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
    2279                     id = 1422;
    2280                 } else {
    2281                     id = 1;
    2282                 }
    2283 
    2284                 GeometryFeatures geometryFeatures = new GeometryFeatures(id);
    2285                 geometryFeatures.createGeometryFeatures(selectedInstance);
    2286                 id = geometryFeatures.getLastID();
    2287                 TextualFeatures textualFeatures = new TextualFeatures(id, textualList, languageDetector);
    2288                 textualFeatures.createTextualFeatures(selectedInstance);
    2289 
    2290                 List<FeatureNode> featureNodeList = selectedInstance.getFeatureNodeList();
    2291                 System.out.println(featureNodeList);
    2292 
    2293                 FeatureNode[] featureNodeArray = new FeatureNode[featureNodeList.size()];
    2294 
    2295                 int i = 0;
    2296                 for (FeatureNode featureNode : featureNodeList) {
    2297                     featureNodeArray[i] = featureNode;
    2298                     i++;
    2299                 }
    2300                 FeatureNode[] testInstance2 = featureNodeArray;
    2301 
    2302                 Map<Integer, Integer> mapLabelsToIDs = new HashMap<>();
    2303                 for (int h = 0; h < modelSVMLabelSize; h++) {
    2304                     mapLabelsToIDs.put(modelSVMLabels[h], h);
    2305                 }
    2306 
    2307                 double[] scores = new double[modelSVMLabelSize];
    2308                 Linear.predictValues(modelSVM, testInstance2, scores);
    2309 
    2310                 Map<Double, Integer> scoresValues = new HashMap<>();
    2311                 for (int h = 0; h < scores.length; h++) {
    2312                     scoresValues.put(scores[h], h);
    2313                 }
    2314 
    2315                 Arrays.sort(scores);
    2316 
    2317                 int[] preds = new int[RECOMMENDATIONS_SIZE];
    2318                 for (int p = 0; p < RECOMMENDATIONS_SIZE; p++) {
    2319                     preds[p] = modelSVMLabels[scoresValues.get(scores[scores.length-(p+1)])];
    2320                 }
    2321                 String[] predictedTags2 = new String[RECOMMENDATIONS_SIZE];
    2322 
    2323                 for (int p = 0; p < RECOMMENDATIONS_SIZE; p++) {
    2324                     if (idsWithMappings.containsKey(preds[p])) {
    2325                         predictedTags2[p] = idsWithMappings.get(preds[p]);
    2326                     }
    2327                 }
    2328 
    2329                 //clearing model, to add the new computed classes in jlist
    2330                 model.clear();
    2331                 for (Map.Entry<String, String> tag : mappings.entrySet()) {
    2332                     for (int k = 0; k < 10; k++) {
    2333                         if (tag.getValue().equals(predictedTags2[k])) {
    2334                             predictedTags2[k] = tag.getKey();
    2335                             model.addElement(tag.getKey());
    2336                         }
    2337                     }
    2338                 }
    2339                 System.out.println("Optimized - create OSMObject, predicted classes: " + Arrays.toString(predictedTags2));
    2340             }
    2341         }
    2342 
    2343         private void parseTagsMappedToClasses() {
    2344 
    2345             InputStream tagsToClassesMapping = TrainWorker.class.getResourceAsStream("/resources/files/Map");
    2346             Mapper mapper = new Mapper();
    2347             try {
    2348                 mapper.parseFile(tagsToClassesMapping);
    2349 
    2350             } catch (FileNotFoundException ex) {
    2351                 Logger.getLogger(Mapper.class.getName()).log(Level.SEVERE, null, ex);
    2352             }
    2353             mappings = mapper.getMappings();
    2354             mapperWithIDs = mapper.getMappingsWithIDs();
    2355             idsWithMappings = mapper.getIDsWithMappings();
    2356         }
    2357 
    2358         private void loadTextualList(File textualListFile) {
    2359 
    2360             Scanner input = null;
    2361 
    2362             try {
    2363                 input = new Scanner(textualListFile);
    2364             } catch (FileNotFoundException ex) {
    2365                 Main.warn(ex);
    2366             }
    2367             while (input.hasNext()) {
    2368                 String nextLine = input.nextLine();
    2369                 textualList.add(nextLine);
    2370             }
    2371             System.out.println("Textual List parsed from file successfully." + textualList);
    2372         }
    2373 
    2374         private void loadDefaultTextualList() {
    2375 
    2376             InputStream textualListStream = TrainWorker.class.getResourceAsStream("/resources/files/textualList.txt");
    2377             TextualStatistics textualStatistics = new TextualStatistics();
    2378             textualStatistics.parseTextualList(textualListStream);
    2379             textualList = textualStatistics.getTextualList();
    2380             System.out.println("Default Textual List parsed from file successfully." + textualList);
    2381         }
    2382 
    2383         private void loadOntology() {
    2384             InputStream ontologyStream = TrainWorker.class.getResourceAsStream("/resources/files/owl.xml");
    2385             Ontology ontology = new Ontology(ontologyStream);
    2386             indirectClasses = ontology.getIndirectClasses();
    2387             indirectClassesWithIDs = ontology.getIndirectClassesIDs();
    2388         }
    2389 
    2390         private Map<File, Double> getAlignedModels(Map<File, Double> filesAndWeights) {
    2391             Map<File, Double> alignedFilesAndWeights = new HashMap<>();
    2392             if (modelWithClasses) {
    2393                 for (Entry<File, Double> entry : filesAndWeights.entrySet()) {
    2394                     String absolutePath = entry.getKey().getAbsolutePath();
    2395                     if (absolutePath.endsWith(".0")) {
    2396                         String newPath = absolutePath.substring(0, absolutePath.length()-2) + ".1";
    2397                         File alignedFile = new File(newPath);
    2398                         if (alignedFile.exists()) {
    2399                             alignedFilesAndWeights.put(alignedFile, entry.getValue());
    2400                         }
    2401                     } else {
    2402                         alignedFilesAndWeights.put(entry.getKey(), entry.getValue());
    2403                     }
    2404                 }
    2405             } else {
    2406                 for (Entry<File, Double> entry : filesAndWeights.entrySet()) {
    2407                     String absolutePath = entry.getKey().getAbsolutePath();
    2408                     if (absolutePath.endsWith(".1")) {
    2409                         String newPath = absolutePath.substring(0, absolutePath.length()-2) + ".0";
    2410                         File alignedFile = new File(newPath);
    2411                         if (alignedFile.exists()) {
    2412                             alignedFilesAndWeights.put(alignedFile, entry.getValue());
    2413                         }
    2414                     } else {
    2415                         alignedFilesAndWeights.put(entry.getKey(), entry.getValue());
    2416                     }
    2417                 }
    2418             }
    2419             return alignedFilesAndWeights;
    2420         }
    2421     }
     606                        */
     607                        buildUserHistoryPanelGroupLayout();
     608
     609                        configPanel.add(inputPanel, BorderLayout.NORTH);
     610                        configPanel.add(userHistoryPanel, BorderLayout.EAST);
     611                        configPanel.add(paramPanel, BorderLayout.WEST);
     612                        configPanel.add(southPanel, BorderLayout.SOUTH);
     613
     614                        userHistoryPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
     615                                        .createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE), "Train by user History"));
     616                        paramPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
     617                                        .createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE), "SVM Configuration"));
     618                        inputPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     619                        configPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     620
     621                        mainPanel.add(configPanel, BorderLayout.NORTH);
     622                        mainPanel.add(startTrainingButton, BorderLayout.CENTER);
     623                        mainPanel.add(trainingProgressBar, BorderLayout.SOUTH);
     624
     625                        AutoCompletionManager autocomplete = MainApplication.getLayerManager().getEditLayer().data.getAutoCompletionManager();
     626                        List<AutoCompletionListItem> keyList = autocomplete.getKeys();
     627                        Collections.sort(keyList, defaultACItemComparator);
     628
     629                        setContent(mainPanel, false);
     630                }
     631
     632                private void buildInputPanelGroupLayout(JPanel inputPanel) {
     633                        GroupLayout inputGroupLayout = new GroupLayout(inputPanel);
     634                        inputPanel.setLayout(inputGroupLayout);
     635                        inputGroupLayout.setAutoCreateGaps(true);
     636                        inputGroupLayout.setAutoCreateContainerGaps(true);
     637
     638                        GroupLayout.SequentialGroup inputHorGroup = inputGroupLayout.createSequentialGroup();
     639                        inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(inputFileLabel).
     640                                        addComponent(inputFileErrorMessageLabel));
     641                        inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(inputFileField));
     642                        inputHorGroup.addGroup(inputGroupLayout.createParallelGroup().addComponent(fileBrowseButton));
     643                        inputGroupLayout.setHorizontalGroup(inputHorGroup);
     644
     645                        GroupLayout.SequentialGroup inputVerGroup = inputGroupLayout.createSequentialGroup();
     646                        inputVerGroup.addGroup(inputGroupLayout.createParallelGroup(Alignment.LEADING).addComponent(inputFileLabel).
     647                                        addComponent(inputFileField).addComponent(fileBrowseButton));
     648                        inputVerGroup.addGroup(inputGroupLayout.createParallelGroup(Alignment.LEADING).
     649                                        addComponent(inputFileErrorMessageLabel));
     650                        inputGroupLayout.setVerticalGroup(inputVerGroup);
     651                }
     652
     653                private void buildParamPanelGroupLayout(JPanel paramPanel) {
     654                        GroupLayout paramGroupLayout = new GroupLayout(paramPanel);
     655                        paramPanel.setLayout(paramGroupLayout);
     656                        paramGroupLayout.setAutoCreateGaps(true);
     657                        paramGroupLayout.setAutoCreateContainerGaps(true);
     658
     659                        GroupLayout.SequentialGroup paramHorGroup = paramGroupLayout.createSequentialGroup();
     660                        paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(topKButton).
     661                                        addComponent(frequencyButton).addComponent(cParameterCheckBox));
     662                        paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(cParameterField).
     663                                        addComponent(topKField).addComponent(frequencyField));
     664                        paramHorGroup.addGroup(paramGroupLayout.createParallelGroup().addComponent(cErrorMessageLabel).
     665                                        addComponent(topKErrorMessageLabel).addComponent(frequencyErrorMessageLabel));
     666                        paramGroupLayout.setHorizontalGroup(paramHorGroup);
     667
     668                        GroupLayout.SequentialGroup paramVerGroup = paramGroupLayout.createSequentialGroup();
     669                        paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).
     670                                        addComponent(cParameterCheckBox).addComponent(cParameterField).addComponent(cErrorMessageLabel));
     671                        paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).addComponent(topKButton).
     672                                        addComponent(topKField).addComponent(topKErrorMessageLabel));
     673                        paramVerGroup.addGroup(paramGroupLayout.createParallelGroup(Alignment.BASELINE).
     674                                        addComponent(frequencyButton).addComponent(frequencyField).addComponent(frequencyErrorMessageLabel));
     675                        paramGroupLayout.setVerticalGroup(paramVerGroup);
     676                }
     677
     678                private void buildUserHistoryPanelGroupLayout() {
     679                        GroupLayout userHistoryGroupLayout = new GroupLayout(userHistoryPanel);
     680                        userHistoryPanel.setLayout(userHistoryGroupLayout);
     681                        userHistoryGroupLayout.setAutoCreateGaps(true);
     682                        userHistoryGroupLayout.setAutoCreateContainerGaps(true);
     683                        userHistoryGroupLayout.linkSize(SwingConstants.HORIZONTAL, userNameField, daysLabel, daysField);
     684
     685                        GroupLayout.SequentialGroup userHistoryHorGroup = userHistoryGroupLayout.createSequentialGroup();
     686
     687                        userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(userNameLabel)
     688                                        .addComponent(byAreaRadioButton).addComponent(byTimeRadioButton));
     689                        userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(userNameField)
     690                                        .addComponent(daysLabel));
     691                        userHistoryHorGroup.addGroup(userHistoryGroupLayout.createParallelGroup().addComponent(daysField));
     692                        userHistoryGroupLayout.setHorizontalGroup(userHistoryHorGroup);
     693
     694                        GroupLayout.SequentialGroup userHistoryVerGroup = userHistoryGroupLayout.createSequentialGroup();
     695                        userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
     696                                        addComponent(userNameLabel).addComponent(userNameField));
     697                        userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
     698                                        addComponent(byAreaRadioButton));
     699                        userHistoryVerGroup.addGroup(userHistoryGroupLayout.createParallelGroup(Alignment.BASELINE).
     700                                        addComponent(byTimeRadioButton).addComponent(daysLabel).addComponent(daysField));
     701                        userHistoryGroupLayout.setVerticalGroup(userHistoryVerGroup);
     702                }
     703
     704                private void inputFileChooserButtonActionPerformed(ActionEvent evt) {
     705                        try {
     706                                final File file = new File(inputFileField.getText());
     707                                final JFileChooser fileChooser = new JFileChooser(file);
     708
     709                                final int returnVal = fileChooser.showOpenDialog(this);
     710                                if (returnVal == JFileChooser.APPROVE_OPTION) {
     711                                        inputFileField.setText(fileChooser.getSelectedFile().getAbsolutePath());
     712                                }
     713                        } catch (RuntimeException ex) {
     714                                Logging.warn(ex);
     715                        }
     716                }
     717
     718                private void acceptConfigButtonActionPerformed(ActionEvent evt) {
     719                        //parse values
     720                        inputFileValue = inputFileField.getText();
     721
     722                        if (!new File(inputFileValue).exists()) {
     723                                inputFileErrorMessageLabel.setText("OSM file does not exist");
     724                                resetConfigButtonActionPerformed();
     725                                return;
     726                        }
     727
     728                        if (cParameterCheckBox.isSelected()) {
     729                                String c = cParameterField.getText();
     730                                try {
     731                                        cParameterValue = Double.parseDouble(c.replace(",", "."));
     732                                        cErrorMessageLabel.setText("");
     733                                } catch (NumberFormatException ex) {
     734                                        cErrorMessageLabel.setText("Must be a number!");
     735                                        System.out.println("c must be a number!" + ex); //make empty textLabel beside c param to notify errors
     736                                        resetConfigButtonActionPerformed();
     737                                        return;
     738                                }
     739                                crossValidateFlag = false;
     740                        } else {
     741                                crossValidateFlag = true;
     742                        }
     743
     744                        if (topKButton.isSelected()) {
     745                                String k = topKField.getText();
     746                                try {
     747                                        topKvalue = Integer.parseInt(k);
     748                                        topKErrorMessageLabel.setText("");
     749                                } catch (NumberFormatException ex) {
     750                                        topKErrorMessageLabel.setText("Must be an Integer!");
     751                                        resetConfigButtonActionPerformed();
     752                                        return;
     753                                }
     754                        } else {
     755                                String f = frequencyField.getText();
     756                                try {
     757                                        frequencyValue = Integer.parseInt(f);
     758                                        frequencyErrorMessageLabel.setText("");
     759                                } catch (NumberFormatException ex) {
     760                                        frequencyErrorMessageLabel.setText("Must be an Integer!");
     761                                        resetConfigButtonActionPerformed();
     762                                        return;
     763                                }
     764                        }
     765
     766                        if (trainFromUserCheckBox.isSelected()) {
     767                                usernameValue = userNameField.getText();
     768                                if (byTimeRadioButton.isSelected()) {
     769                                        try {
     770                                                daysValue = Integer.parseInt(daysField.getText());
     771                                        } catch (NumberFormatException ex) {
     772                                                daysField.setText("Integer!");
     773                                                Logging.warn(ex);
     774                                        }
     775                                }
     776
     777                                userHistoryPanel.setEnabled(false);
     778                                byAreaRadioButton.setEnabled(false);
     779                                byTimeRadioButton.setEnabled(false);
     780                                userNameLabel.setEnabled(false);
     781                                userNameField.setEnabled(false);
     782                                daysLabel.setEnabled(false);
     783                                daysField.setEnabled(false);
     784                        }
     785
     786                        System.out.println("Running configuration:" + "\nC parameter: " + cParameterValue +" \ntopK: " + topKvalue
     787                                        + "\nMax Frequency: " + frequencyValue + "\nCross Validate?: " + crossValidateFlag);
     788
     789                        trainFromUserCheckBox.setEnabled(false);
     790                        inputFileField.setEditable(false);
     791                        cParameterField.setEditable(false);
     792                        topKField.setEditable(false);
     793                        frequencyField.setEditable(false);
     794                        cParameterCheckBox.setEnabled(false);
     795                        topKButton.setEnabled(false);
     796                        frequencyButton.setEnabled(false);
     797                        acceptConfigButton.setEnabled(false);
     798                        fileBrowseButton.setEnabled(false);
     799                }
     800
     801                private void resetConfigButtonActionPerformed() {
     802                        if (trainWorker != null) {
     803                                try {
     804                                        trainWorker.cancel(true);
     805                                } catch (CancellationException ex) {
     806                                        startTrainingButton.setEnabled(true);
     807                                        System.out.println(ex);
     808                                }
     809                        }
     810                        if (userDataExtractAndTrainWorker != null) {
     811                                try {
     812                                        userDataExtractAndTrainWorker.cancel(true);
     813                                } catch (CancellationException ex) {
     814                                        startTrainingButton.setEnabled(true);
     815                                        System.out.println(ex);
     816                                }
     817                        }
     818                        inputFileField.setEditable(true);
     819                        cParameterField.setEditable(true);
     820                        topKField.setEditable(true);
     821                        frequencyField.setEditable(true);
     822                        cParameterCheckBox.setEnabled(true);
     823                        topKButton.setEnabled(true);
     824                        frequencyButton.setEnabled(true);
     825                        acceptConfigButton.setEnabled(true);
     826                        fileBrowseButton.setEnabled(true);
     827                        trainFromUserCheckBox.setEnabled(true);
     828
     829                        if (trainFromUserCheckBox.isSelected()) {
     830                                userHistoryPanel.setEnabled(true);
     831                                byAreaRadioButton.setEnabled(true);
     832                                byTimeRadioButton.setEnabled(true);
     833                                userNameLabel.setEnabled(true);
     834                                userNameField.setEnabled(true);
     835                                daysLabel.setEnabled(true);
     836                                daysField.setEnabled(true);
     837                        }
     838                }
     839
     840                private void startTraining() {
     841                        startTrainingButton.setEnabled(false);
     842
     843                        if (trainFromUserCheckBox.isSelected()) { //if user training. train by area or days
     844                                EventQueue.invokeLater(new Runnable() {
     845                                        @Override
     846                                        public void run() {
     847
     848                                                userDataExtractAndTrainWorker = new UserDataExtractAndTrainWorker(inputFileValue, usernameValue, daysValue,
     849                                                                byAreaRadioButton.isSelected(), crossValidateFlag, cParameterValue, topKvalue, frequencyValue,
     850                                                                topKButton.isSelected(), languageDetector);
     851
     852                                                userDataExtractAndTrainWorker.addPropertyChangeListener(new PropertyChangeListener() {
     853                                                        @Override
     854                                                        public void propertyChange(PropertyChangeEvent evt) {
     855                                                                if ("progress".equals(evt.getPropertyName())) {
     856                                                                        int progress = (Integer) evt.getNewValue();
     857                                                                        trainingProgressBar.setValue(progress);
     858                                                                        if (progress == 100) {
     859                                                                                startTrainingButton.setEnabled(true);
     860                                                                        }
     861                                                                }
     862                                                        }
     863                                                });
     864
     865                                                try {
     866                                                        System.out.println("executing userDataExtractAndTrainWorker Thread..");
     867                                                        userDataExtractAndTrainWorker.execute();
     868                                                } catch (Exception ex) {
     869                                                        Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     870                                                }
     871                                        }
     872                                });
     873                        } else {
     874                                EventQueue.invokeLater(new Runnable() {
     875                                        @Override
     876                                        public void run() {
     877                                                trainWorker = new TrainWorker(inputFileValue, crossValidateFlag, cParameterValue, topKvalue, frequencyValue,
     878                                                                topKButton.isSelected(), languageDetector);
     879
     880                                                trainWorker.addPropertyChangeListener(new PropertyChangeListener() {
     881                                                        @Override
     882                                                        public void propertyChange(PropertyChangeEvent evt) {
     883                                                                if ("progress".equals(evt.getPropertyName())) {
     884                                                                        int progress = (Integer) evt.getNewValue();
     885                                                                        trainingProgressBar.setValue(progress);
     886                                                                        if (progress == 100) {
     887                                                                                startTrainingButton.setEnabled(true);
     888                                                                        }
     889                                                                }
     890                                                        }
     891                                                });
     892
     893                                                try {
     894                                                        trainWorker.execute();
     895                                                } catch (Exception ex) {
     896                                                        Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     897                                                }
     898                                        }
     899                                });
     900                        }
     901                }
     902        }
     903
     904        public static final BooleanProperty PROPERTY_FIX_TAG_LOCALE =
     905                        new BooleanProperty("properties.fix-tag-combobox-locale", false);
     906        public static final BooleanProperty PROPERTY_REMEMBER_TAGS =
     907                        new BooleanProperty("properties.remember-recently-added-tags", true);
     908        public static final IntegerProperty PROPERTY_RECENT_TAGS_NUMBER =
     909                        new IntegerProperty("properties.recently-added-tags", DEFAULT_LRU_TAGS_NUMBER);
     910
     911        abstract static class AbstractTagsDialog extends ExtendedDialog {
     912                AutoCompletingComboBox keys;
     913                AutoCompletingComboBox values;
     914
     915                AbstractTagsDialog(Component parent, String title, String[] buttonTexts) {
     916                        super(parent, title, buttonTexts);
     917                        addMouseListener(new PopupMenuLauncher(popupMenu));
     918                }
     919
     920                @Override
     921                public void setupDialog() {
     922                        super.setupDialog();
     923                        final Dimension size = getSize();
     924                        // Set resizable only in width
     925                        setMinimumSize(size);
     926                        setPreferredSize(size);
     927                        // setMaximumSize does not work, and never worked, but still it seems not to bother Oracle to fix this 10-year-old bug
     928                        // https://bugs.openjdk.java.net/browse/JDK-6200438
     929                        // https://bugs.openjdk.java.net/browse/JDK-6464548
     930
     931                        setRememberWindowGeometry(getClass().getName() + ".geometry",
     932                                        WindowGeometry.centerInWindow(Main.parent, size));
     933                }
     934
     935                @Override
     936                public void setVisible(boolean visible) {
     937                        // Do not want dialog to be resizable in height, as its size may increase each time because of the recently added tags
     938                        // So need to modify the stored geometry (size part only) in order to use the automatic positioning mechanism
     939                        if (visible) {
     940                                WindowGeometry geometry = initWindowGeometry();
     941                                Dimension storedSize = geometry.getSize();
     942                                Dimension size = getSize();
     943                                if (!storedSize.equals(size)) {
     944                                        if (storedSize.width < size.width) {
     945                                                storedSize.width = size.width;
     946                                        }
     947                                        if (storedSize.height != size.height) {
     948                                                storedSize.height = size.height;
     949                                        }
     950                                        rememberWindowGeometry(geometry);
     951                                }
     952                                if (keys != null) {
     953                                        keys.setFixedLocale(PROPERTY_FIX_TAG_LOCALE.get());
     954                                }
     955                        }
     956                        super.setVisible(visible);
     957                }
     958
     959                /**
     960                * Create a focus handling adapter and apply in to the editor component of value
     961                * autocompletion box.
     962                * @param autocomplete Manager handling the autocompletion
     963                * @param comparator Class to decide what values are offered on autocompletion
     964                * @return The created adapter
     965                */
     966                protected FocusAdapter addFocusAdapter(final AutoCompletionManager autocomplete, final Comparator<AutoCompletionListItem> comparator) {
     967                        // get the combo box' editor component
     968                        JTextComponent editor = (JTextComponent) values.getEditor().getEditorComponent();
     969                        // Refresh the values model when focus is gained
     970                        FocusAdapter focus = new FocusAdapter() {
     971                                @Override
     972                                public void focusGained(FocusEvent e) {
     973                                        String key = keys.getEditor().getItem().toString();
     974
     975                                        List<AutoCompletionListItem> valueList = autocomplete.getValues(getAutocompletionKeys(key));
     976                                        Collections.sort(valueList, comparator);
     977
     978                                        values.setPossibleACItems(valueList);
     979                                        values.getEditor().selectAll();
     980                                }
     981                        };
     982                        editor.addFocusListener(focus);
     983                        return focus;
     984                }
     985
     986                protected JPopupMenu popupMenu = new JPopupMenu() {
     987                        JCheckBoxMenuItem fixTagLanguageCb = new JCheckBoxMenuItem(
     988                                        new AbstractAction(tr("Use English language for tag by default")) {
     989                                                @Override
     990                                                public void actionPerformed(ActionEvent e) {
     991                                                        boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
     992                                                        PROPERTY_FIX_TAG_LOCALE.put(sel);
     993                                                }
     994                                        });
     995                        {
     996                                add(fixTagLanguageCb);
     997                                fixTagLanguageCb.setState(PROPERTY_FIX_TAG_LOCALE.get());
     998                        }
     999                };
     1000        }
     1001
     1002        class ModelSettingsDialog extends JPanel {
     1003
     1004                private final JLabel chooseModelLabel;
     1005                private final JButton chooseModelButton;
     1006                private final JTextField chooseModelTextField;
     1007
     1008                private final DefaultListModel<String> combinationDefaultListModel = new DefaultListModel<>();
     1009                private final JList<String> modelCombinationList = new JList<>(combinationDefaultListModel);
     1010                private final JPanel modelCombinationPanel;
     1011                private final JPanel weightsPanel;
     1012                private final JCheckBox useModelCombinationCheckbox;
     1013                private final JButton acceptWeightsButton;
     1014                private final JButton resetWeightsButton;
     1015                private final JButton removeSelectedModelButton;
     1016                private Map<JTextField, String> weightFieldsAndPaths = new HashMap<>();
     1017                private final Map<String, Double> normalizedPathsAndWeights = new HashMap<>();
     1018                private final JOptionPane pane;
     1019                private final JDialog dlg;
     1020                private final JPanel mainPanel;
     1021                private final JPanel singleSelectionPanel;
     1022                private final JPanel setResetWeightsPanel;
     1023                private final JScrollPane combinationScrollPane;
     1024                private final JScrollPane singleSelectionScrollPane;
     1025                private final TitledBorder modelTitle;
     1026                private final TitledBorder weightTitle;
     1027                private final TitledBorder combineTitle;
     1028                private final Dimension singleSelectionDimension;
     1029                private final Dimension modelCombinationDimension;
     1030                private final Dimension mainPanelDimension;
     1031
     1032                ModelSettingsDialog(Collection<OsmPrimitive> sel1, final AddTagsDialog addDialog) {
     1033
     1034                        loadPreviousCombinedSVMModel();
     1035                        singleSelectionDimension = new Dimension(470, 70);
     1036                        modelCombinationDimension = new Dimension(450, 250);
     1037                        mainPanelDimension = new Dimension(600, 350);
     1038
     1039                        //------- <NORTH of main> ---------//
     1040                        mainPanel = new JPanel(new BorderLayout(10, 10));
     1041                        singleSelectionPanel = new JPanel(new BorderLayout(10, 10));
     1042                        setResetWeightsPanel = new JPanel();
     1043
     1044                        chooseModelLabel = new JLabel("Choose a Model:");
     1045                        chooseModelTextField = new JTextField();
     1046                        chooseModelButton = new JButton("...");
     1047                        chooseModelTextField.setText(MODEL_PATH);
     1048
     1049                        singleSelectionPanel.add(chooseModelLabel, BorderLayout.NORTH);
     1050                        singleSelectionPanel.add(chooseModelTextField, BorderLayout.WEST);
     1051                        singleSelectionPanel.add(chooseModelButton, BorderLayout.EAST);
     1052
     1053                        singleSelectionScrollPane = new JScrollPane(singleSelectionPanel);
     1054                        singleSelectionScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
     1055                        singleSelectionScrollPane.setPreferredSize(singleSelectionDimension);
     1056
     1057                        //------- </NORTH of main> ---------//
     1058
     1059                        //------- <WEST of main> ---------//
     1060                        modelCombinationList.setFixedCellHeight(20);
     1061                        modelCombinationList.setEnabled(false);
     1062                        modelCombinationPanel = new JPanel(new BorderLayout(10, 10));
     1063
     1064                        weightsPanel = new JPanel();
     1065                        weightsPanel.setLayout(new BoxLayout(weightsPanel, BoxLayout.Y_AXIS));
     1066                        weightsPanel.setEnabled(false);
     1067
     1068
     1069                        acceptWeightsButton = new JButton("Set Weights/Normalize");
     1070                        resetWeightsButton = new JButton("Reset Weights");
     1071                        removeSelectedModelButton = new JButton("Remove Selected");
     1072                        setResetWeightsPanel.add(acceptWeightsButton);
     1073                        setResetWeightsPanel.add(resetWeightsButton);
     1074                        setResetWeightsPanel.add(removeSelectedModelButton);
     1075                        removeSelectedModelButton.setEnabled(false);
     1076                        acceptWeightsButton.setEnabled(false);
     1077                        resetWeightsButton.setEnabled(false);
     1078
     1079                        modelCombinationPanel.add(modelCombinationList, BorderLayout.CENTER);
     1080                        modelCombinationPanel.add(weightsPanel, BorderLayout.EAST);
     1081                        modelCombinationPanel.add(setResetWeightsPanel, BorderLayout.SOUTH);
     1082
     1083                        combinationScrollPane = new JScrollPane(modelCombinationPanel);
     1084
     1085                        combinationScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
     1086                        combinationScrollPane.setPreferredSize(modelCombinationDimension);   //new Dimension(450, 250) // w/h
     1087
     1088                        //------- </WEST of main> ---------//
     1089
     1090                        //------- <SOUTH of main> ---------//
     1091                        useModelCombinationCheckbox = new JCheckBox("Combine different models?");
     1092
     1093                        //------- </SOUTH of main> ---------//
     1094
     1095                        //------- <Borders> ---------//
     1096                        modelTitle = BorderFactory.createTitledBorder("Models");
     1097                        weightTitle = BorderFactory.createTitledBorder("W");
     1098                        combineTitle = BorderFactory.createTitledBorder("Combine Models");
     1099                        modelCombinationList.setBorder(modelTitle);
     1100                        weightsPanel.setBorder(weightTitle);
     1101
     1102                        for (Entry<JTextField, String> entry : weightFieldsAndPaths.entrySet()) {
     1103                                combinationDefaultListModel.addElement(entry.getValue());
     1104
     1105                                JTextField weightTextField = new JTextField("0.00");
     1106                                weightTextField.setMaximumSize(new Dimension(80, 20));
     1107                                weightsPanel.add(entry.getKey());
     1108                        }
     1109
     1110                        //modelCombinationPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1111                        modelCombinationPanel.setBorder(combineTitle);
     1112                        singleSelectionPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1113                        //------- </Borders> ---------//
     1114
     1115                        chooseModelButton.addActionListener(new java.awt.event.ActionListener() {
     1116                                @Override
     1117                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1118                                        modelChooserButtonActionPerformed(evt);
     1119                                }
     1120                        });
     1121
     1122                        useModelCombinationCheckbox.addActionListener(new java.awt.event.ActionListener() {
     1123                                @Override
     1124                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1125                                        userCombinationCheckboxActionPerformed(evt);
     1126                                }
     1127                        });
     1128
     1129                        acceptWeightsButton.addActionListener(new java.awt.event.ActionListener() {
     1130                                @Override
     1131                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1132                                        acceptWeightsButtonActionPerformed(evt);
     1133                                }
     1134                        });
     1135
     1136                        resetWeightsButton.addActionListener(new java.awt.event.ActionListener() {
     1137                                @Override
     1138                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1139                                        resetWeightsButtonActionPerformed(evt);
     1140                                }
     1141                        });
     1142
     1143                        removeSelectedModelButton.addActionListener(new java.awt.event.ActionListener() {
     1144                                @Override
     1145                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1146                                        removeSelectedModelButtonActionPerformed(evt);
     1147                                }
     1148                        });
     1149                        mainPanel.add(singleSelectionScrollPane, BorderLayout.NORTH);
     1150                        mainPanel.add(combinationScrollPane, BorderLayout.CENTER);
     1151                        mainPanel.add(useModelCombinationCheckbox, BorderLayout.SOUTH);
     1152
     1153                        mainPanel.setPreferredSize(mainPanelDimension);
     1154
     1155                        this.add(mainPanel);
     1156
     1157                        pane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION) {
     1158                                @Override
     1159                                public void setValue(Object newValue) {
     1160                                        super.setValue(newValue);
     1161                                        if (newValue instanceof Integer && (int) newValue == 0 && useModelCombinationCheckbox.isSelected()) {
     1162                                                System.out.println("model settings button value: " + newValue);
     1163                                                System.out.println("\nUSE COMBINED MODEL\n");
     1164                                                useCombinedModel = true;
     1165                                                useCustomSVMModel = false;
     1166
     1167                                                addDialog.loadSVMmodel();
     1168                                                addDialog.createOSMObject(sel);
     1169                                                saveCombinedModel();
     1170                                                dlg.setVisible(false);
     1171                                        } else if (newValue instanceof Integer && (int) newValue == -1 && useModelCombinationCheckbox.isSelected()) {
     1172                                                System.out.println("model settings button value: " + newValue);
     1173                                                useCombinedModel = false;
     1174                                                useCustomSVMModel = false;
     1175                                                System.out.println("Use combined model");
     1176
     1177                                                addDialog.loadSVMmodel();
     1178                                                addDialog.createOSMObject(sel);
     1179                                                dlg.setVisible(false);
     1180                                        } else if (newValue instanceof Integer && (int) newValue == 0 && !useModelCombinationCheckbox.isSelected()) {
     1181                                                System.out.println("model settings button value: " + newValue);
     1182                                                System.out.println("Don t use combined model, use custom model");
     1183                                                useCombinedModel = false;
     1184                                                useCustomSVMModel = true;
     1185                                                addDialog.loadSVMmodel();
     1186                                                addDialog.createOSMObject(sel);
     1187                                                dlg.setVisible(false);
     1188                                        } else if (newValue instanceof Integer && (int) newValue == -1 && !useModelCombinationCheckbox.isSelected()) {
     1189                                                System.out.println("model settings button value: " + newValue);
     1190                                                System.out.println("Don t use combined model, use custom model");
     1191                                                useCombinedModel = false;
     1192                                                useCustomSVMModel = false;
     1193                                                addDialog.loadSVMmodel();
     1194                                                addDialog.createOSMObject(sel);
     1195                                                dlg.setVisible(false);
     1196                                        } else if (newValue == null || newValue.equals("uninitializedValue")) {
     1197                                                System.out.println("uninitializedValue, do nothing");
     1198                                        }
     1199                                }
     1200                        };
     1201
     1202                        dlg = pane.createDialog(Main.parent, tr("Model Settings"));
     1203                        dlg.setVisible(true);
     1204                }
     1205
     1206                public void makeVisible(boolean visible) {
     1207                        dlg.setVisible(true);
     1208                }
     1209
     1210                private void modelChooserButtonActionPerformed(ActionEvent evt) {
     1211
     1212                        try {
     1213                                final File file = new File(chooseModelTextField.getText());
     1214                                final JFileChooser fileChooser = new JFileChooser(file);
     1215
     1216                                final int returnVal = fileChooser.showOpenDialog(this);
     1217                                if (returnVal == JFileChooser.APPROVE_OPTION) {
     1218                                        chooseModelTextField.setText(fileChooser.getSelectedFile().getAbsolutePath());
     1219                                        useCustomSVMModel = true;
     1220                                        customSVMModelPath = fileChooser.getSelectedFile().getAbsolutePath();
     1221                                }
     1222
     1223                                if (useModelCombinationCheckbox.isSelected()) {
     1224                                        String svmModelPath = fileChooser.getSelectedFile().getAbsolutePath();
     1225                                        String svmModelText;
     1226                                        if (System.getProperty("os.name").contains("ux")) {
     1227                                                if (svmModelPath.contains("/")) {
     1228                                                        svmModelText = svmModelPath.substring(svmModelPath.lastIndexOf("/"));
     1229                                                } else {
     1230                                                        svmModelText = svmModelPath;
     1231                                                }
     1232                                        } else {
     1233                                                if (svmModelPath.contains("\\")) {
     1234                                                        svmModelText = svmModelPath.substring(svmModelPath.lastIndexOf("\\"));
     1235                                                } else {
     1236                                                        svmModelText = svmModelPath;
     1237                                                }
     1238                                        }
     1239                                        combinationDefaultListModel.addElement(svmModelText);
     1240                                        JTextField weightTextField = new JTextField("0.00");
     1241                                        weightFieldsAndPaths.put(weightTextField, svmModelPath);
     1242                                        System.out.println("weights size: " + weightFieldsAndPaths.size());
     1243
     1244                                        weightTextField.setMaximumSize(new Dimension(80, 20));
     1245                                        weightsPanel.add(weightTextField);
     1246                                        //add additional textbox
     1247                                }
     1248                        } catch (RuntimeException ex) {
     1249                                Logging.warn(ex);
     1250                        }
     1251                }
     1252
     1253                private void userCombinationCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
     1254
     1255                        if (useModelCombinationCheckbox.isSelected()) {
     1256                                useCombinedModel = true;
     1257                                useCustomSVMModel = false; //reseting the selected custom SVM model only here
     1258                                removeSelectedModelButton.setEnabled(true);
     1259                                acceptWeightsButton.setEnabled(true);
     1260                                resetWeightsButton.setEnabled(true);
     1261
     1262                                chooseModelTextField.setEnabled(false);
     1263                                modelCombinationList.setEnabled(true);
     1264                                weightsPanel.setEnabled(true);
     1265                                Component[] weightPanelComponents = weightsPanel.getComponents();
     1266                                for (Component weightPanelComponent : weightPanelComponents) {
     1267                                        weightPanelComponent.setEnabled(true);
     1268                                }
     1269                        } else {
     1270                                useCombinedModel = false;
     1271                                useCustomSVMModel = true;
     1272                                removeSelectedModelButton.setEnabled(false);
     1273                                acceptWeightsButton.setEnabled(false);
     1274                                resetWeightsButton.setEnabled(false);
     1275
     1276                                chooseModelTextField.setEnabled(true);
     1277                                modelCombinationList.setEnabled(false);
     1278                                weightsPanel.setEnabled(false);
     1279                                Component[] weightPanelComponents = weightsPanel.getComponents();
     1280                                for (Component weightPanelComponent : weightPanelComponents) {
     1281                                        weightPanelComponent.setEnabled(false);
     1282                                }
     1283                        }
     1284                }
     1285
     1286                private void acceptWeightsButtonActionPerformed(ActionEvent evt) {
     1287                        int weightsCount = 0;
     1288                        removeSelectedModelButton.setEnabled(false);
     1289                        double weightSum = 0;
     1290                        for (JTextField weightField : weightFieldsAndPaths.keySet()) {
     1291                                if (weightField.getText().equals("")) {
     1292                                        weightField.setText("0.00");
     1293                                }
     1294
     1295                                try {
     1296                                        //TODO replace "," with "." to parse doubles with commas
     1297                                        Double weightValue = Double.parseDouble(weightField.getText());
     1298
     1299                                        weightValue = Math.abs(weightValue);
     1300                                        weightSum += weightValue;
     1301                                } catch (NumberFormatException ex) {
     1302                                        Logging.warn(ex);
     1303                                }
     1304                                weightsCount++;
     1305                        }
     1306
     1307                        if (!filesAndWeights.isEmpty()) {
     1308                                filesAndWeights.clear();
     1309                        }
     1310
     1311                        for (JTextField weightField : weightFieldsAndPaths.keySet()) {
     1312                                try {
     1313                                        Double weightValue = Double.parseDouble(weightField.getText());
     1314
     1315                                        weightValue = Math.abs(weightValue)/weightSum; //normalize
     1316
     1317                                        if (weightSum == 0) {
     1318                                                weightValue = 1.0/weightsCount;
     1319                                        }
     1320
     1321                                        weightField.setText(new DecimalFormat("#.##").format(weightValue));
     1322                                        normalizedPathsAndWeights.put(weightFieldsAndPaths.get(weightField), weightValue);
     1323                                        filesAndWeights.put(new File(weightFieldsAndPaths.get(weightField)), weightValue);
     1324                                        System.out.println("normalized: " + weightFieldsAndPaths.get(weightField) + "->" + weightValue);
     1325                                        weightField.setEnabled(false);
     1326
     1327                                } catch (NumberFormatException ex) {
     1328                                        Logging.warn(ex);
     1329                                }
     1330                        }
     1331
     1332                        useCombinedModel = true;
     1333                        useCustomSVMModel = false;
     1334                }
     1335
     1336                private void resetWeightsButtonActionPerformed(ActionEvent evt) {
     1337                        removeSelectedModelButton.setEnabled(true);
     1338                        for (JTextField weightField : weightFieldsAndPaths.keySet()) {
     1339                                weightField.setEnabled(true);
     1340                        }
     1341                }
     1342
     1343                private void removeSelectedModelButtonActionPerformed(ActionEvent evt) {
     1344                        int index = modelCombinationList.getSelectedIndex();
     1345                        String modelToBeRemoved = combinationDefaultListModel.get(index);
     1346                        combinationDefaultListModel.remove(index);
     1347                        System.out.println("model to be removed: " + modelToBeRemoved);
     1348
     1349                        Iterator<Entry<JTextField, String>> it = weightFieldsAndPaths.entrySet().iterator();
     1350                        while (it.hasNext()) {
     1351                                Entry<JTextField, String> en = it.next();
     1352                                if (en.getValue().equals(modelToBeRemoved)) {
     1353                                        it.remove();
     1354                                }
     1355                        }
     1356                        System.out.println("model to be removed: " + modelToBeRemoved);
     1357
     1358                        weightsPanel.remove(index);
     1359                        weightsPanel.revalidate();
     1360                        weightsPanel.repaint();
     1361                }
     1362
     1363                @SuppressWarnings("unchecked")
     1364                private void loadPreviousCombinedSVMModel() {
     1365                        File combinedModelClassesFile = new File(combinedModelClasses);
     1366
     1367                        if (combinedModelClassesFile.exists()) {
     1368                                FileInputStream fileIn = null;
     1369                                ObjectInputStream in = null;
     1370                                try {
     1371                                        fileIn = new FileInputStream(combinedModelClassesFile);
     1372                                        in = new ObjectInputStream(fileIn);
     1373                                        weightFieldsAndPaths = (Map<JTextField, String>) in.readObject();
     1374                                } catch (FileNotFoundException ex) {
     1375                                        Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     1376                                } catch (IOException | ClassNotFoundException ex) {
     1377                                        Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     1378                                } finally {
     1379                                        try {
     1380                                                if (in != null) {
     1381                                                        in.close();
     1382                                                }
     1383                                                if (fileIn != null) {
     1384                                                        fileIn.close();
     1385                                                }
     1386
     1387                                        } catch (IOException ex) {
     1388                                                Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     1389                                        }
     1390                                }
     1391                        } else {
     1392                                try {
     1393                                        combinedModelClassesFile.createNewFile();
     1394                                } catch (IOException ex) {
     1395                                        Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     1396                                }
     1397                        }
     1398                }
     1399
     1400                private void saveCombinedModel() {
     1401                        try (FileOutputStream fileOut = new FileOutputStream(combinedModelClasses);
     1402                                        ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
     1403                                out.writeObject(weightFieldsAndPaths);
     1404                        } catch (IOException e) {
     1405                                System.out.println("serialize error" + e);
     1406                        }
     1407                }
     1408        }
     1409
     1410        class AddTagsDialog extends AbstractTagsDialog {
     1411                List<JosmAction> recentTagsActions = new ArrayList<>();
     1412
     1413                // Counter of added commands for possible undo
     1414                private int commandCount;
     1415                private final JLabel recommendedClassesLabel;
     1416                private final JButton modelSettingsButton;
     1417                private final JButton addAndContinueButton;
     1418                private final DefaultListModel<String> model;
     1419                private final JList<String> categoryList;
     1420                private Model modelSVM;
     1421                private int modelSVMLabelSize;
     1422                private int[] modelSVMLabels;
     1423                private Map<String, String> mappings;
     1424                private Map<String, Integer> mapperWithIDs;
     1425                private Map<Integer, String> idsWithMappings;
     1426                private List<String> textualList = new ArrayList<>();
     1427                private final JCheckBox useTagsCheckBox;
     1428                private ModelSettingsDialog modelSettingsDialog;
     1429                private static final int RECOMMENDATIONS_SIZE = 10;
     1430
     1431                AddTagsDialog() {
     1432                        super(Main.parent, tr("Add value?"), new String[] {tr("OK"), tr("Cancel")});
     1433                        setButtonIcons(new String[] {"ok", "cancel"});
     1434                        setCancelButton(2);
     1435                        configureContextsensitiveHelp("/Dialog/AddValue", true /* show help button */);
     1436                        final AddTagsDialog addTagsDialog = this;
     1437
     1438                        loadOntology();
     1439                        //if the user did not train a model by running the training process
     1440                        //the list does not exist in a file and so we load the default list from the jar.
     1441
     1442                        System.out.println("path for textual: " + TEXTUAL_LIST_PATH);
     1443                        File textualListFile = new File(TEXTUAL_LIST_PATH);
     1444                        if (textualListFile.exists()) {
     1445                                loadTextualList(textualListFile);
     1446                        } else {
     1447                                loadDefaultTextualList();
     1448                        }
     1449
     1450                        //if training process has not been performed, we use two sample SVM models, extracted from the jar
     1451
     1452                        JPanel splitPanel = new JPanel(new BorderLayout(10, 10));
     1453                        JPanel mainPanel = new JPanel(new GridBagLayout()); //original panel, will be wrapped by the splitPanel
     1454                        JPanel recommendPanel = new JPanel(new BorderLayout(10, 10));   //will contain listPanel, action panel
     1455                        JPanel listPanel = new JPanel(new BorderLayout(10, 10)); //class recommend label, recommendation list
     1456                        JPanel actionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); //model selection buttons or configuration
     1457
     1458                        addAndContinueButton = new JButton("Add and continue");
     1459                        modelSettingsButton = new JButton("Model Settings");
     1460                        useTagsCheckBox = new JCheckBox("Predict using tags");
     1461                        recommendedClassesLabel = new JLabel("Recommended Classes:");
     1462
     1463                        addAndContinueButton.addActionListener(new java.awt.event.ActionListener() {
     1464                                @Override
     1465                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1466                                        String selectedClass = categoryList.getSelectedValue();
     1467                                        addAndContinueButtonActionPerformed(evt, selectedClass);
     1468
     1469                                        //reconstruct vector for instance and use the model that was trained with classes here
     1470
     1471                                        List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
     1472                                        OsmPrimitive s;
     1473
     1474                                        //get a simple selection
     1475                                        if (!osmPrimitiveSelection.isEmpty()) {
     1476                                                s = osmPrimitiveSelection.get(0);
     1477                                                if (s.getInterestingTags().isEmpty()) {
     1478                                                        //load original model
     1479                                                        modelWithClasses = false;
     1480                                                        loadSVMmodel();
     1481                                                        createOSMObject(sel); //create object without class features
     1482                                                } else {
     1483                                                        //recommend using tags: set the checkbox selected to avoid confusing the user
     1484                                                        useTagsCheckBox.setSelected(true);
     1485
     1486                                                        if (useTagsCheckBox.isSelected()) {
     1487                                                                //load model with classes
     1488                                                                modelWithClasses = true;
     1489                                                                loadSVMmodel();
     1490                                                                createOSMObject(sel); //create object including class features
     1491                                                        } else {
     1492                                                                modelWithClasses = false;
     1493                                                                loadSVMmodel();
     1494                                                                createOSMObject(sel); //create object including class features
     1495                                                        }
     1496                                                }
     1497                                        }
     1498                                }
     1499                        });
     1500
     1501                        modelSettingsButton.addActionListener(new java.awt.event.ActionListener() {
     1502                                @Override
     1503                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1504                                        if (modelSettingsDialog == null) {
     1505                                                System.out.println("new modelSettingsDialog");
     1506                                                modelSettingsDialog = new ModelSettingsDialog(sel, addTagsDialog);
     1507                                        } else {
     1508                                                System.out.println("set modelSettingsDialog visible");
     1509                                                modelSettingsDialog.makeVisible(true);
     1510                                        }
     1511                                }
     1512                        });
     1513
     1514                        useTagsCheckBox.addActionListener(new java.awt.event.ActionListener() {
     1515                                @Override
     1516                                public void actionPerformed(java.awt.event.ActionEvent evt) {
     1517                                        List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
     1518                                        OsmPrimitive s;
     1519                                        if (!osmPrimitiveSelection.isEmpty()) {
     1520                                                s = osmPrimitiveSelection.get(0);
     1521                                                if (s.getInterestingTags().isEmpty()) {
     1522                                                        //load original model
     1523                                                        modelWithClasses = false;
     1524                                                        loadSVMmodel();
     1525                                                        createOSMObject(sel); //create object without class features
     1526                                                } else {
     1527                                                        //useTagsCheckBox
     1528                                                        if (useTagsCheckBox.isSelected()) {
     1529                                                                //load model with classes
     1530                                                                modelWithClasses = true;
     1531                                                                loadSVMmodel();
     1532                                                                createOSMObject(sel); //create object including class features
     1533                                                        } else {
     1534                                                                modelWithClasses = false;
     1535                                                                loadSVMmodel();
     1536                                                                createOSMObject(sel); //create object including class features
     1537                                                        }
     1538                                                }
     1539                                        }
     1540                                }
     1541                        });
     1542
     1543                        keys = new AutoCompletingComboBox();
     1544                        values = new AutoCompletingComboBox();
     1545
     1546                        mainPanel.add(new JLabel("<html>"+trn("This will change up to {0} object.",
     1547                                        "This will change up to {0} objects.", sel.size(), sel.size())
     1548                        +"<br><br>"+tr("Please select a key")), GBC.eol().fill(GBC.HORIZONTAL));
     1549
     1550                        AutoCompletionManager autocomplete = MainApplication.getLayerManager().getEditLayer().data.getAutoCompletionManager();
     1551                        List<AutoCompletionListItem> keyList = autocomplete.getKeys();
     1552
     1553                        AutoCompletionListItem itemToSelect = null;
     1554                        // remove the object's tag keys from the list
     1555                        Iterator<AutoCompletionListItem> iter = keyList.iterator();
     1556                        while (iter.hasNext()) {
     1557                                AutoCompletionListItem item = iter.next();
     1558                                if (item.getValue().equals(lastAddKey)) {
     1559                                        itemToSelect = item;
     1560                                }
     1561                                for (int i = 0; i < tagData.getRowCount(); ++i) {
     1562                                        if (item.getValue().equals(tagData.getValueAt(i, 0))) {
     1563                                                if (itemToSelect == item) {
     1564                                                        itemToSelect = null;
     1565                                                }
     1566                                                iter.remove();
     1567                                                break;
     1568                                        }
     1569                                }
     1570                        }
     1571
     1572                        Collections.sort(keyList, defaultACItemComparator);
     1573                        keys.setPossibleACItems(keyList);
     1574                        keys.setEditable(true);
     1575
     1576                        mainPanel.add(keys, GBC.eop().fill());
     1577                        mainPanel.add(new JLabel(tr("Please select a value")), GBC.eol());
     1578
     1579                        model = new DefaultListModel<>();
     1580
     1581                        parseTagsMappedToClasses();
     1582
     1583                        List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
     1584                        OsmPrimitive s;
     1585                        //get a simple selection
     1586                        if (!osmPrimitiveSelection.isEmpty()) {
     1587                                s = osmPrimitiveSelection.get(0);
     1588                                File modelDirectory = new File(MODEL_PATH);
     1589                                String modelWithClassesPath = modelDirectory.getAbsolutePath() + "/model_with_classes";
     1590                                File modelWithClassesFile = new File(modelWithClassesPath);
     1591                                if (s.getInterestingTags().isEmpty() || !modelWithClassesFile.exists()) {
     1592                                        modelWithClasses = false;
     1593                                        loadSVMmodel(); //load original model
     1594                                        createOSMObject(sel); //create object without class features
     1595                                } else {
     1596                                        //recommend using tags: set the checkbox selected to avoid confusing the user
     1597                                        useTagsCheckBox.setSelected(true);
     1598                                        modelWithClasses = true;
     1599                                        loadSVMmodel(); //load model with classes
     1600                                        createOSMObject(sel); //create object including class features
     1601                                }
     1602                        }
     1603
     1604                        categoryList = new JList<>(model);
     1605
     1606                        ListSelectionListener listSelectionListener = new ListSelectionListener() {
     1607                                @Override
     1608                                public void valueChanged(ListSelectionEvent listSelectionEvent) {
     1609                                        if (!listSelectionEvent.getValueIsAdjusting()) { //This prevents double events
     1610
     1611                                                String selectedClass = categoryList.getSelectedValue();
     1612
     1613                                                if (selectedClass != null) { //null check, because the model is cleared after a new recommendation
     1614                                                        //tags become unselected
     1615                                                        if ((selectedClass.indexOf(" ")+1) > 0) {
     1616                                                                //add both key + value in tags
     1617                                                                String keyTag = selectedClass.substring(0, selectedClass.indexOf(" "));
     1618                                                                String valueTag = selectedClass.substring(selectedClass.indexOf(" ")+1, selectedClass.length());
     1619                                                                keys.setSelectedItem(keyTag); //adding selected tags to textBoxes
     1620                                                                values.setSelectedItem(valueTag);
     1621                                                        } else {
     1622                                                                //value does not have a value, add the key tag only
     1623                                                                String keyTag = selectedClass; //test it
     1624                                                                keys.setSelectedItem(keyTag);
     1625                                                                values.setSelectedItem("");
     1626                                                        }
     1627                                                }
     1628                                        }
     1629                                }
     1630                        };
     1631
     1632                        categoryList.addListSelectionListener(listSelectionListener);
     1633                        categoryList.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1634                        categoryList.setModel(model);
     1635
     1636                        values.setEditable(true);
     1637                        mainPanel.add(values, GBC.eop().fill());
     1638                        if (itemToSelect != null) {
     1639                                keys.setSelectedItem(itemToSelect);
     1640                                if (lastAddValue != null) {
     1641                                        values.setSelectedItem(lastAddValue);
     1642                                }
     1643                        }
     1644
     1645                        FocusAdapter focus = addFocusAdapter(autocomplete, defaultACItemComparator);
     1646                        // fire focus event in advance or otherwise the popup list will be too small at first
     1647                        focus.focusGained(null);
     1648
     1649                        int recentTagsToShow = PROPERTY_RECENT_TAGS_NUMBER.get();
     1650                        if (recentTagsToShow > MAX_LRU_TAGS_NUMBER) {
     1651                                recentTagsToShow = MAX_LRU_TAGS_NUMBER;
     1652                        }
     1653
     1654                        suggestRecentlyAddedTags(mainPanel, recentTagsToShow, focus);
     1655
     1656                        mainPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1657                        listPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1658                        splitPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.GRAY, Color.WHITE));
     1659
     1660                        listPanel.add(recommendedClassesLabel, BorderLayout.NORTH);
     1661                        listPanel.add(categoryList, BorderLayout.SOUTH);
     1662                        actionsPanel.add(addAndContinueButton);
     1663                        actionsPanel.add(modelSettingsButton);
     1664                        actionsPanel.add(useTagsCheckBox);
     1665
     1666                        recommendPanel.add(actionsPanel, BorderLayout.WEST);
     1667                        recommendPanel.add(listPanel, BorderLayout.NORTH);
     1668
     1669                        splitPanel.add(mainPanel, BorderLayout.WEST);
     1670                        splitPanel.add(recommendPanel, BorderLayout.EAST);
     1671
     1672                        setContent(splitPanel, false);
     1673
     1674                        popupMenu.add(new AbstractAction(tr("Set number of recently added tags")) {
     1675                                @Override
     1676                                public void actionPerformed(ActionEvent e) {
     1677                                        selectNumberOfTags();
     1678                                }
     1679                        });
     1680                        JCheckBoxMenuItem rememberLastTags = new JCheckBoxMenuItem(
     1681                                        new AbstractAction(tr("Remember last used tags after a restart")) {
     1682                                                @Override
     1683                                                public void actionPerformed(ActionEvent e) {
     1684                                                        boolean sel = ((JCheckBoxMenuItem) e.getSource()).getState();
     1685                                                        PROPERTY_REMEMBER_TAGS.put(sel);
     1686                                                        if (sel) saveTagsIfNeeded();
     1687                                                }
     1688                                        });
     1689                        rememberLastTags.setState(PROPERTY_REMEMBER_TAGS.get());
     1690                        popupMenu.add(rememberLastTags);
     1691                }
     1692
     1693                private void addAndContinueButtonActionPerformed(ActionEvent evt, String selectedClass) {
     1694                        performTagAdding();
     1695                }
     1696
     1697                private void selectNumberOfTags() {
     1698                        String s = JOptionPane.showInputDialog(this, tr("Please enter the number of recently added tags to display"));
     1699                        if (s != null) try {
     1700                                int v = Integer.parseInt(s);
     1701                                if (v >= 0 && v <= MAX_LRU_TAGS_NUMBER) {
     1702                                        PROPERTY_RECENT_TAGS_NUMBER.put(v);
     1703                                        return;
     1704                                }
     1705                        } catch (NumberFormatException ex) {
     1706                                Logging.warn(ex);
     1707                        }
     1708                        JOptionPane.showMessageDialog(this, tr("Please enter integer number between 0 and {0}", MAX_LRU_TAGS_NUMBER));
     1709                }
     1710
     1711                private void suggestRecentlyAddedTags(JPanel mainPanel, int tagsToShow, final FocusAdapter focus) {
     1712                        if (!(tagsToShow > 0 && !recentTags.isEmpty()))
     1713                                return;
     1714
     1715                        mainPanel.add(new JLabel(tr("Recently added tags")), GBC.eol());
     1716
     1717                        int count = 1;
     1718                        // We store the maximum number (9) of recent tags to allow dynamic change of number of tags shown in the preferences.
     1719                        // This implies to iterate in descending order,
     1720                        // as the oldest elements will only be removed after we reach the maximum numbern and not the number of tags to show.
     1721                        // However, as Set does not allow to iterate in descending order,
     1722                        // we need to copy its elements into a List we can access in reverse order.
     1723                        List<Tag> tags = new LinkedList<>(recentTags.keySet());
     1724                        for (int i = tags.size()-1; i >= 0 && count <= tagsToShow; i--, count++) {
     1725                                final Tag t = tags.get(i);
     1726                                // Create action for reusing the tag, with keyboard shortcut Ctrl+(1-5)
     1727                                String scKey = "properties:recent:"+count;
     1728                                String scsKey = "properties:recent:shift:"+count;
     1729                                Shortcut sc = Shortcut.registerShortcut(scKey, tr("Choose recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL);
     1730                                final JosmAction action = new JosmAction(scKey, null, tr("Use this tag again"), sc, false) {
     1731                                        @Override
     1732                                        public void actionPerformed(ActionEvent e) {
     1733                                                keys.setSelectedItem(t.getKey());
     1734                                                // fix #7951, #8298 - update list of values before setting value (?)
     1735                                                focus.focusGained(null);
     1736                                                values.setSelectedItem(t.getValue());
     1737                                        }
     1738                                };
     1739                                Shortcut scs = Shortcut.registerShortcut(scsKey, tr("Apply recent tag {0}", count), KeyEvent.VK_0+count, Shortcut.CTRL_SHIFT);
     1740                                final JosmAction actionShift = new JosmAction(scsKey, null, tr("Use this tag again"), scs, false) {
     1741                                        @Override
     1742                                        public void actionPerformed(ActionEvent e) {
     1743                                                action.actionPerformed(null);
     1744                                                performTagAdding();
     1745                                        }
     1746                                };
     1747                                recentTagsActions.add(action);
     1748                                recentTagsActions.add(actionShift);
     1749                                disableTagIfNeeded(t, action);
     1750                                // Find and display icon
     1751                                ImageIcon icon = MapPaintStyles.getNodeIcon(t, false); // Filters deprecated icon
     1752                                if (icon == null) {
     1753                                        // If no icon found in map style look at presets
     1754                                        Map<String, String> map = new HashMap<>();
     1755                                        map.put(t.getKey(), t.getValue());
     1756                                        // If still nothing display an empty icon
     1757                                        if (icon == null) {
     1758                                                icon = new ImageIcon(new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB));
     1759                                        }
     1760                                }
     1761                                GridBagConstraints gbc = new GridBagConstraints();
     1762                                gbc.ipadx = 5;
     1763                                mainPanel.add(new JLabel(action.isEnabled() ? icon : GuiHelper.getDisabledIcon(icon)), gbc);
     1764                                // Create tag label
     1765                                final String color = action.isEnabled() ? "" : "; color:gray";
     1766                                final JLabel tagLabel = new JLabel("<html>"
     1767                                                + "<style>td{border:1px solid gray; font-weight:normal"+color+"}</style>"
     1768                                                + "<table><tr><td>" + XmlWriter.encode(t.toString(), true) + "</td></tr></table></html>");
     1769                                if (action.isEnabled()) {
     1770                                        // Register action
     1771                                        mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(sc.getKeyStroke(), scKey);
     1772                                        mainPanel.getActionMap().put(scKey, action);
     1773                                        mainPanel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(scs.getKeyStroke(), scsKey);
     1774                                        mainPanel.getActionMap().put(scsKey, actionShift);
     1775                                        // Make the tag label clickable and set tooltip to the action description (this displays also the keyboard shortcut)
     1776                                        tagLabel.setToolTipText((String) action.getValue(Action.SHORT_DESCRIPTION));
     1777                                        tagLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
     1778                                        tagLabel.addMouseListener(new MouseAdapter() {
     1779                                                @Override
     1780                                                public void mouseClicked(MouseEvent e) {
     1781                                                        action.actionPerformed(null);
     1782                                                        // add tags and close window on double-click
     1783
     1784                                                        if (e.getClickCount() > 1) {
     1785                                                                buttonAction(0, null); // emulate OK click and close the dialog
     1786                                                        }
     1787                                                        // add tags on Shift-Click
     1788                                                        if (e.isShiftDown()) {
     1789                                                                performTagAdding();
     1790                                                        }
     1791                                                }
     1792                                        });
     1793                                } else {
     1794                                        // Disable tag label
     1795                                        tagLabel.setEnabled(false);
     1796                                        // Explain in the tooltip why
     1797                                        tagLabel.setToolTipText(tr("The key ''{0}'' is already used", t.getKey()));
     1798                                }
     1799                                // Finally add label to the resulting panel
     1800                                JPanel tagPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
     1801                                tagPanel.add(tagLabel);
     1802                                mainPanel.add(tagPanel, GBC.eol().fill(GBC.HORIZONTAL));
     1803                        }
     1804                }
     1805
     1806                public void destroyActions() {
     1807                        for (JosmAction action : recentTagsActions) {
     1808                                action.destroy();
     1809                        }
     1810                }
     1811
     1812                /**
     1813                * Read tags from comboboxes and add it to all selected objects
     1814                */
     1815                public final void performTagAdding() {
     1816                        String key = Tag.removeWhiteSpaces(keys.getEditor().getItem().toString());
     1817                        String value = Tag.removeWhiteSpaces(values.getEditor().getItem().toString());
     1818                        if (key.isEmpty() || value.isEmpty()) return;
     1819                        for (OsmPrimitive osm: sel) {
     1820                                String val = osm.get(key);
     1821                                if (val != null && !val.equals(value)) {
     1822                                        if (!warnOverwriteKey(tr("You changed the value of ''{0}'' from ''{1}'' to ''{2}''.", key, val, value),
     1823                                                        "overwriteAddKey"))
     1824                                                return;
     1825                                        break;
     1826                                }
     1827                        }
     1828                        lastAddKey = key;
     1829                        lastAddValue = value;
     1830                        recentTags.put(new Tag(key, value), null);
     1831                        AutoCompletionManager.rememberUserInput(key, value, false);
     1832                        commandCount++;
     1833                        MainApplication.undoRedo.add(new ChangePropertyCommand(sel, key, value));
     1834                        changedKey = key;
     1835                }
     1836
     1837                public void undoAllTagsAdding() {
     1838                        MainApplication.undoRedo.undo(commandCount);
     1839                }
     1840
     1841                private void disableTagIfNeeded(final Tag t, final JosmAction action) {
     1842                        // Disable action if its key is already set on the object (the key being absent from the keys list for this reason
     1843                        // performing this action leads to autocomplete to the next key (see #7671 comments)
     1844                        for (int j = 0; j < tagData.getRowCount(); ++j) {
     1845                                if (t.getKey().equals(tagData.getValueAt(j, 0))) {
     1846                                        action.setEnabled(false);
     1847                                        break;
     1848                                }
     1849                        }
     1850                }
     1851
     1852                private void loadSVMmodel() {
     1853                        File modelDirectory = new File(MODEL_PATH);
     1854                        File modelFile;
     1855                        if (useCombinedModel) {
     1856                                if (filesAndWeights.isEmpty()) {
     1857                                        System.out.println("No models selected! Loading defaults..");
     1858                                        if (modelWithClasses) {
     1859                                                System.out.println("Using default/last model with classes: " + modelDirectory.getAbsolutePath() + "/model_with_classes");
     1860                                                modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
     1861                                                try {
     1862                                                        System.out.println("try to load model: " + modelFile.getAbsolutePath());
     1863                                                        modelSVM = Model.load(modelFile);
     1864                                                        System.out.println("model loaded!");
     1865
     1866                                                } catch (IOException ex) {
     1867                                                        Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     1868                                                }
     1869                                                modelSVMLabelSize = modelSVM.getLabels().length;
     1870                                                modelSVMLabels = modelSVM.getLabels();
     1871                                        } else {
     1872                                                System.out.println("Using default/last model without classes: " + modelDirectory.getAbsolutePath() + "/best_model");
     1873                                                modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
     1874                                                try {
     1875                                                        System.out.println("try to load model: " + modelFile.getAbsolutePath());
     1876                                                        modelSVM = Model.load(modelFile);
     1877                                                        System.out.println("model loaded!");
     1878
     1879                                                } catch (IOException ex) {
     1880                                                        Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     1881                                                }
     1882                                                modelSVMLabelSize = modelSVM.getLabels().length;
     1883                                                modelSVMLabels = modelSVM.getLabels();
     1884                                        }
     1885                                }
     1886                                if (modelWithClasses) { //check filenames to define if model with classes is selected
     1887                                        System.out.println("Using combined model with classes");
     1888                                        useCombinedSVMmodels(sel, true);
     1889                                } else {
     1890                                        System.out.println("Using combined model without classes");
     1891                                        useCombinedSVMmodels(sel, false);
     1892                                }
     1893                        } else if (useCustomSVMModel) {
     1894                                System.out.println("custom path: " + customSVMModelPath);
     1895                                File checkExistance = new File(customSVMModelPath);
     1896                                if (checkExistance.exists() && checkExistance.isFile()) {
     1897                                        if (modelWithClasses) {
     1898                                                System.out.println("Using custom model with classes: ");
     1899                                                if (customSVMModelPath.endsWith(".0")) {
     1900                                                        String customSVMModelPathWithClasses = customSVMModelPath.substring(0, customSVMModelPath.length() - 2) + ".1";
     1901
     1902                                                        modelFile = new File(customSVMModelPathWithClasses);
     1903                                                        System.out.println(customSVMModelPathWithClasses);
     1904                                                } else {
     1905                                                        modelFile = new File(customSVMModelPath);
     1906                                                }
     1907                                        } else {
     1908                                                System.out.println("Using custom model without classes");
     1909                                                if (customSVMModelPath.endsWith(".1")) {
     1910                                                        String customSVMModelPathWithoutClasses = customSVMModelPath.substring(0, customSVMModelPath.length() - 2) + ".0";
     1911                                                        modelFile = new File(customSVMModelPathWithoutClasses);
     1912                                                        System.out.println(customSVMModelPathWithoutClasses);
     1913                                                } else {
     1914                                                        modelFile = new File(customSVMModelPath);
     1915                                                }
     1916                                        }
     1917                                        try {
     1918                                                System.out.println("try to load model: " + modelFile.getAbsolutePath());
     1919                                                modelSVM = Model.load(modelFile);
     1920                                                System.out.println("model loaded!");
     1921
     1922                                        } catch (IOException ex) {
     1923                                                Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     1924                                        }
     1925                                        modelSVMLabelSize = modelSVM.getLabels().length;
     1926                                        modelSVMLabels = modelSVM.getLabels();
     1927
     1928                                } else {
     1929                                        //user chose to use a custom model, but did not provide a path to a model:
     1930                                        if (modelWithClasses) {
     1931                                                System.out.println("Using default/last model with classes");
     1932                                                modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
     1933                                        } else {
     1934                                                System.out.println("Using default/last model without classes");
     1935                                                modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
     1936                                        }
     1937
     1938                                        try {
     1939                                                System.out.println("try to load model: " + modelFile.getAbsolutePath());
     1940                                                modelSVM = Model.load(modelFile);
     1941                                                System.out.println("model loaded!");
     1942
     1943                                        } catch (IOException ex) {
     1944                                                Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     1945                                        }
     1946                                        modelSVMLabelSize = modelSVM.getLabels().length;
     1947                                        modelSVMLabels = modelSVM.getLabels();
     1948
     1949                                }
     1950                        } else {
     1951                                if (modelWithClasses) {
     1952                                        System.out.println("Using default/last model with classes");
     1953                                        modelFile = new File(modelDirectory.getAbsolutePath() + "/model_with_classes");
     1954                                } else {
     1955                                        System.out.println("Using default/last model without classes");
     1956                                        modelFile = new File(modelDirectory.getAbsolutePath() + "/best_model");
     1957                                }
     1958
     1959                                try {
     1960                                        System.out.println("try to load model: " + modelFile.getAbsolutePath());
     1961                                        modelSVM = Model.load(modelFile);
     1962                                        System.out.println("model loaded!");
     1963
     1964                                } catch (IOException ex) {
     1965                                        Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     1966                                }
     1967                                modelSVMLabelSize = modelSVM.getLabels().length;
     1968                                modelSVMLabels = modelSVM.getLabels();
     1969                        }
     1970                }
     1971
     1972                private void useCombinedSVMmodels(Collection<OsmPrimitive> sel, boolean useClassFeatures) {
     1973                        System.out.println("The system will combine " + filesAndWeights.size() + " SVM models.");
     1974
     1975                        MathTransform transform = null;
     1976                        GeometryFactory geometryFactory = new GeometryFactory();
     1977                        CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
     1978                        CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
     1979                        try {
     1980                                transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
     1981
     1982                        } catch (FactoryException ex) {
     1983                                Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     1984                        }
     1985
     1986                        OSMWay selectedInstance;
     1987                        List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
     1988                        OsmPrimitive s;
     1989
     1990                        //get a simple selection
     1991                        if (!osmPrimitiveSelection.isEmpty()) {
     1992                                s = osmPrimitiveSelection.get(0);
     1993                        } else {
     1994                                return;
     1995                        }
     1996
     1997                        selectedInstance = new OSMWay();
     1998                        for (Way selectedWay : s.getDataSet().getSelectedWays()) {
     1999                                List<Node> selectedWayNodes = selectedWay.getNodes();
     2000                                for (Node node : selectedWayNodes) {
     2001                                        node.getCoor();
     2002                                        if (node.isLatLonKnown()) {
     2003                                                double lat = node.getCoor().lat();
     2004                                                double lon = node.getCoor().lon();
     2005
     2006                                                Coordinate sourceCoordinate = new Coordinate(lon, lat);
     2007                                                Coordinate targetGeometry = null;
     2008                                                try {
     2009                                                        targetGeometry = JTS.transform(sourceCoordinate, null, transform);
     2010                                                } catch (MismatchedDimensionException | TransformException ex) {
     2011                                                        Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
     2012                                                }
     2013
     2014                                                Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
     2015                                                selectedInstance.addNodeGeometry(geom);
     2016                                        }
     2017                                }
     2018                        }
     2019                        Geometry fullGeom = geometryFactory.buildGeometry(selectedInstance.getNodeGeometries());
     2020                        if ((selectedInstance.getNodeGeometries().size() > 3) &&
     2021                                        selectedInstance.getNodeGeometries().get(0).equals(selectedInstance.getNodeGeometries()
     2022                                                        .get(selectedInstance.getNodeGeometries().size()-1))) {
     2023                                //checks if the beginning and ending node are the same and the number of nodes are more than 3.
     2024                                //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
     2025                                LinearRing linear = geometryFactory.createLinearRing(fullGeom.getCoordinates());
     2026                                Polygon poly = new Polygon(linear, null, geometryFactory);
     2027                                selectedInstance.setGeometry(poly);
     2028
     2029                                System.out.println("\n\npolygon");
     2030                        } else if (selectedInstance.getNodeGeometries().size() > 1) {
     2031                                //it is an open geometry with more than one nodes, make it linestring
     2032                                System.out.println("\n\nlinestring");
     2033                                LineString lineString = geometryFactory.createLineString(fullGeom.getCoordinates());
     2034                                selectedInstance.setGeometry(lineString);
     2035                        } else { //we assume all the rest geometries are points
     2036                                System.out.println("\n\npoint");
     2037                                Point point = geometryFactory.createPoint(fullGeom.getCoordinate());
     2038                                selectedInstance.setGeometry(point);
     2039                        }
     2040
     2041                        Map<String, String> selectedTags = s.getInterestingTags();
     2042                        selectedInstance.setAllTags(selectedTags);
     2043
     2044                        //construct vector
     2045                        if (selectedInstance != null) {
     2046                                int id;
     2047
     2048                                OSMClassification classifier = new OSMClassification();
     2049                                classifier.calculateClasses(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
     2050
     2051                                if (useClassFeatures) {
     2052                                        ClassFeatures classFeatures = new ClassFeatures();
     2053                                        classFeatures.createClassFeatures(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
     2054                                        id = 1422;
     2055                                } else {
     2056                                        id = 1;
     2057                                }
     2058
     2059                                GeometryFeatures geometryFeatures = new GeometryFeatures(id);
     2060                                geometryFeatures.createGeometryFeatures(selectedInstance);
     2061                                id = geometryFeatures.getLastID();
     2062                                TextualFeatures textualFeatures = new TextualFeatures(id, textualList, languageDetector);
     2063                                textualFeatures.createTextualFeatures(selectedInstance);
     2064
     2065                                List<FeatureNode> featureNodeList = selectedInstance.getFeatureNodeList();
     2066
     2067                                FeatureNode[] featureNodeArray = new FeatureNode[featureNodeList.size()];
     2068
     2069                                int i = 0;
     2070                                for (FeatureNode featureNode : featureNodeList) {
     2071                                        featureNodeArray[i] = featureNode;
     2072                                        i++;
     2073                                }
     2074                                FeatureNode[] testInstance2 = featureNodeArray;
     2075
     2076                                //compute prediction list for every model
     2077                                int[] ranks = new int[10];
     2078
     2079                                for (int l = 0; l < 10; l++) {
     2080                                        ranks[l] = 10-l; //init from 10 to 1
     2081                                }
     2082
     2083                                Map<String, Double> scoreMap = new HashMap<>();
     2084
     2085                                Map<File, Double> alignedFilesAndWeights = getAlignedModels(filesAndWeights);
     2086
     2087                                for (File modelFile : alignedFilesAndWeights.keySet()) {
     2088
     2089                                        try {
     2090                                                modelSVM = Model.load(modelFile);
     2091                                        } catch (IOException ex) {
     2092                                                Logger.getLogger(TrainWorker.class.getName()).log(Level.SEVERE, null, ex);
     2093                                        }
     2094                                        modelSVMLabelSize = modelSVM.getLabels().length;
     2095                                        modelSVMLabels = modelSVM.getLabels();
     2096
     2097                                        Map<Integer, Integer> mapLabelsToIDs = new HashMap<>();
     2098                                        for (int h = 0; h < modelSVMLabelSize; h++) {
     2099                                                mapLabelsToIDs.put(modelSVMLabels[h], h);
     2100                                        }
     2101                                        double[] scores = new double[modelSVMLabelSize];
     2102                                        Linear.predictValues(modelSVM, testInstance2, scores);
     2103
     2104                                        Map<Double, Integer> scoresValues = new HashMap<>();
     2105                                        for (int h = 0; h < scores.length; h++) {
     2106                                                scoresValues.put(scores[h], h);
     2107                                        }
     2108
     2109                                        Arrays.sort(scores);
     2110                                        int predicted1 = modelSVMLabels[scoresValues.get(scores[scores.length-1])];
     2111                                        int predicted2 = modelSVMLabels[scoresValues.get(scores[scores.length-2])];
     2112                                        int predicted3 = modelSVMLabels[scoresValues.get(scores[scores.length-3])];
     2113                                        int predicted4 = modelSVMLabels[scoresValues.get(scores[scores.length-4])];
     2114                                        int predicted5 = modelSVMLabels[scoresValues.get(scores[scores.length-5])];
     2115                                        int predicted6 = modelSVMLabels[scoresValues.get(scores[scores.length-6])];
     2116                                        int predicted7 = modelSVMLabels[scoresValues.get(scores[scores.length-7])];
     2117                                        int predicted8 = modelSVMLabels[scoresValues.get(scores[scores.length-8])];
     2118                                        int predicted9 = modelSVMLabels[scoresValues.get(scores[scores.length-9])];
     2119                                        int predicted10 = modelSVMLabels[scoresValues.get(scores[scores.length-10])];
     2120
     2121                                        String[] predictedTags = new String[10];
     2122                                        for (Map.Entry<String, Integer> entry : mapperWithIDs.entrySet()) {
     2123
     2124                                                if (entry.getValue().equals(predicted1)) {
     2125                                                        predictedTags[0] = entry.getKey();
     2126                                                } else if (entry.getValue().equals(predicted2)) {
     2127                                                        predictedTags[1] = entry.getKey();
     2128                                                } else if (entry.getValue().equals(predicted3)) {
     2129                                                        predictedTags[2] = entry.getKey();
     2130                                                } else if (entry.getValue().equals(predicted4)) {
     2131                                                        predictedTags[3] = entry.getKey();
     2132                                                } else if (entry.getValue().equals(predicted5)) {
     2133                                                        predictedTags[4] = entry.getKey();
     2134                                                } else if (entry.getValue().equals(predicted6)) {
     2135                                                        predictedTags[5] = entry.getKey();
     2136                                                } else if (entry.getValue().equals(predicted7)) {
     2137                                                        predictedTags[6] = entry.getKey();
     2138                                                } else if (entry.getValue().equals(predicted8)) {
     2139                                                        predictedTags[7] = entry.getKey();
     2140                                                } else if (entry.getValue().equals(predicted9)) {
     2141                                                        predictedTags[8] = entry.getKey();
     2142                                                } else if (entry.getValue().equals(predicted10)) {
     2143                                                        predictedTags[9] = entry.getKey();
     2144                                                }
     2145                                        }
     2146                                        //clearing model, to add the new computed classes in jlist
     2147                                        model.clear();
     2148                                        for (Map.Entry<String, String> tag : mappings.entrySet()) {
     2149
     2150                                                for (int k = 0; k < 10; k++) {
     2151                                                        if (tag.getValue().equals(predictedTags[k])) {
     2152                                                                predictedTags[k] = tag.getKey();
     2153                                                                model.addElement(tag.getKey());
     2154                                                        }
     2155                                                }
     2156                                        }
     2157                                        System.out.println("combined, predicted classes: " + Arrays.toString(predictedTags));
     2158
     2159                                        for (int r = 0; r < ranks.length; r++) {
     2160                                                String predictedTag = predictedTags[r];
     2161                                                Double currentWeight = alignedFilesAndWeights.get(modelFile);
     2162                                                double finalRank = ranks[r]*currentWeight;
     2163
     2164                                                if (scoreMap.containsKey(predictedTag)) {
     2165                                                        Double scoreToAdd = scoreMap.get(predictedTag);
     2166                                                        scoreMap.put(predictedTag, finalRank+scoreToAdd);
     2167                                                } else {
     2168                                                        scoreMap.put(predictedTag, finalRank);
     2169                                                }
     2170                                                //add final weight - predicted tag
     2171                                        }
     2172                                } //files iter
     2173                                model.clear();
     2174                                List<Double> scoresList = new ArrayList<>(scoreMap.values());
     2175                                Collections.sort(scoresList, Collections.reverseOrder());
     2176
     2177                                for (Double sco : scoresList) {
     2178                                        if (model.size() > 9) {
     2179                                                break;
     2180                                        }
     2181                                        for (Map.Entry<String, Double> scoreEntry : scoreMap.entrySet()) {
     2182                                                if (scoreEntry.getValue().equals(sco)) {
     2183                                                        model.addElement(scoreEntry.getKey());
     2184                                                }
     2185                                        }
     2186                                }
     2187                        }
     2188                }
     2189
     2190                private void createOSMObject(Collection<OsmPrimitive> sel) {
     2191
     2192                        MathTransform transform = null;
     2193                        GeometryFactory geometryFactory = new GeometryFactory();
     2194                        CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
     2195                        CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
     2196                        try {
     2197                                transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
     2198
     2199                        } catch (FactoryException ex) {
     2200                                Logger.getLogger(OSMRecPluginHelper.class.getName()).log(Level.SEVERE, null, ex);
     2201                        }
     2202
     2203                        //fire an error to the user if he has multiple selection from map
     2204
     2205                        //we consider simple (one instance) selection, so we get the first of the sel list
     2206
     2207                        OSMWay selectedInstance;
     2208                        List<OsmPrimitive> osmPrimitiveSelection = new ArrayList<>(sel);
     2209                        OsmPrimitive s;
     2210
     2211                        //get a simple selection
     2212                        if (!osmPrimitiveSelection.isEmpty()) {
     2213                                s = osmPrimitiveSelection.get(0);
     2214                        } else {
     2215                                return;
     2216                        }
     2217
     2218                        selectedInstance = new OSMWay();
     2219                        for (Way selectedWay : s.getDataSet().getSelectedWays()) {
     2220                                List<Node> selectedWayNodes = selectedWay.getNodes();
     2221                                for (Node node : selectedWayNodes) {
     2222                                        node.getCoor();
     2223                                        if (node.isLatLonKnown()) {
     2224                                                double lat = node.getCoor().lat();
     2225                                                double lon = node.getCoor().lon();
     2226
     2227                                                Coordinate sourceCoordinate = new Coordinate(lon, lat);
     2228                                                Coordinate targetGeometry = null;
     2229                                                try {
     2230                                                        targetGeometry = JTS.transform(sourceCoordinate, null, transform);
     2231                                                } catch (MismatchedDimensionException | TransformException ex) {
     2232                                                        Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
     2233                                                }
     2234
     2235                                                Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
     2236                                                selectedInstance.addNodeGeometry(geom);
     2237                                        }
     2238                                }
     2239                        }
     2240                        Geometry fullGeom = geometryFactory.buildGeometry(selectedInstance.getNodeGeometries());
     2241
     2242                        System.out.println("number of nodes: " + selectedInstance.getNodeGeometries().size());
     2243
     2244                        if ((selectedInstance.getNodeGeometries().size() > 3) &&
     2245                                        selectedInstance.getNodeGeometries().get(0).equals(selectedInstance.getNodeGeometries()
     2246                                                        .get(selectedInstance.getNodeGeometries().size()-1))) {
     2247                                //checks if the beginning and ending node are the same and the number of nodes are more than 3.
     2248                                //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
     2249                                LinearRing linear = geometryFactory.createLinearRing(fullGeom.getCoordinates());
     2250                                Polygon poly = new Polygon(linear, null, geometryFactory);
     2251                                selectedInstance.setGeometry(poly);
     2252
     2253                                System.out.println("\n\npolygon");
     2254                        } else if (selectedInstance.getNodeGeometries().size() > 1) {
     2255                                //it is an open geometry with more than one nodes, make it linestring
     2256                                System.out.println("\n\nlinestring");
     2257                                LineString lineString = geometryFactory.createLineString(fullGeom.getCoordinates());
     2258                                selectedInstance.setGeometry(lineString);
     2259                        } else { //we assume all the rest geometries are points
     2260                                System.out.println("\n\npoint");
     2261                                Point point = geometryFactory.createPoint(fullGeom.getCoordinate());
     2262                                selectedInstance.setGeometry(point);
     2263                        }
     2264
     2265                        Map<String, String> selectedTags = s.getInterestingTags();
     2266                        selectedInstance.setAllTags(selectedTags);
     2267
     2268                        //construct vector here
     2269                        if (selectedInstance != null) {
     2270                                int id;
     2271                                if (mappings == null) {
     2272                                        System.out.println("null mappings ERROR");
     2273                                }
     2274
     2275                                OSMClassification classifier = new OSMClassification();
     2276                                classifier.calculateClasses(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
     2277
     2278                                if (modelWithClasses) {
     2279                                        ClassFeatures classFeatures = new ClassFeatures();
     2280                                        classFeatures.createClassFeatures(selectedInstance, mappings, mapperWithIDs, indirectClasses, indirectClassesWithIDs);
     2281                                        id = 1422;
     2282                                } else {
     2283                                        id = 1;
     2284                                }
     2285
     2286                                GeometryFeatures geometryFeatures = new GeometryFeatures(id);
     2287                                geometryFeatures.createGeometryFeatures(selectedInstance);
     2288                                id = geometryFeatures.getLastID();
     2289                                TextualFeatures textualFeatures = new TextualFeatures(id, textualList, languageDetector);
     2290                                textualFeatures.createTextualFeatures(selectedInstance);
     2291
     2292                                List<FeatureNode> featureNodeList = selectedInstance.getFeatureNodeList();
     2293                                System.out.println(featureNodeList);
     2294
     2295                                FeatureNode[] featureNodeArray = new FeatureNode[featureNodeList.size()];
     2296
     2297                                int i = 0;
     2298                                for (FeatureNode featureNode : featureNodeList) {
     2299                                        featureNodeArray[i] = featureNode;
     2300                                        i++;
     2301                                }
     2302                                FeatureNode[] testInstance2 = featureNodeArray;
     2303
     2304                                Map<Integer, Integer> mapLabelsToIDs = new HashMap<>();
     2305                                for (int h = 0; h < modelSVMLabelSize; h++) {
     2306                                        mapLabelsToIDs.put(modelSVMLabels[h], h);
     2307                                }
     2308
     2309                                double[] scores = new double[modelSVMLabelSize];
     2310                                Linear.predictValues(modelSVM, testInstance2, scores);
     2311
     2312                                Map<Double, Integer> scoresValues = new HashMap<>();
     2313                                for (int h = 0; h < scores.length; h++) {
     2314                                        scoresValues.put(scores[h], h);
     2315                                }
     2316
     2317                                Arrays.sort(scores);
     2318
     2319                                int[] preds = new int[RECOMMENDATIONS_SIZE];
     2320                                for (int p = 0; p < RECOMMENDATIONS_SIZE; p++) {
     2321                                        preds[p] = modelSVMLabels[scoresValues.get(scores[scores.length-(p+1)])];
     2322                                }
     2323                                String[] predictedTags2 = new String[RECOMMENDATIONS_SIZE];
     2324
     2325                                for (int p = 0; p < RECOMMENDATIONS_SIZE; p++) {
     2326                                        if (idsWithMappings.containsKey(preds[p])) {
     2327                                                predictedTags2[p] = idsWithMappings.get(preds[p]);
     2328                                        }
     2329                                }
     2330
     2331                                //clearing model, to add the new computed classes in jlist
     2332                                model.clear();
     2333                                for (Map.Entry<String, String> tag : mappings.entrySet()) {
     2334                                        for (int k = 0; k < 10; k++) {
     2335                                                if (tag.getValue().equals(predictedTags2[k])) {
     2336                                                        predictedTags2[k] = tag.getKey();
     2337                                                        model.addElement(tag.getKey());
     2338                                                }
     2339                                        }
     2340                                }
     2341                                System.out.println("Optimized - create OSMObject, predicted classes: " + Arrays.toString(predictedTags2));
     2342                        }
     2343                }
     2344
     2345                private void parseTagsMappedToClasses() {
     2346
     2347                        InputStream tagsToClassesMapping = TrainWorker.class.getResourceAsStream("/resources/files/Map");
     2348                        Mapper mapper = new Mapper();
     2349                        try {
     2350                                mapper.parseFile(tagsToClassesMapping);
     2351
     2352                        } catch (FileNotFoundException ex) {
     2353                                Logger.getLogger(Mapper.class.getName()).log(Level.SEVERE, null, ex);
     2354                        }
     2355                        mappings = mapper.getMappings();
     2356                        mapperWithIDs = mapper.getMappingsWithIDs();
     2357                        idsWithMappings = mapper.getIDsWithMappings();
     2358                }
     2359
     2360                private void loadTextualList(File textualListFile) {
     2361
     2362                        Scanner input = null;
     2363
     2364                        try {
     2365                                input = new Scanner(textualListFile);
     2366                        } catch (FileNotFoundException ex) {
     2367                                Logging.warn(ex);
     2368                        }
     2369                        while (input.hasNext()) {
     2370                                String nextLine = input.nextLine();
     2371                                textualList.add(nextLine);
     2372                        }
     2373                        System.out.println("Textual List parsed from file successfully." + textualList);
     2374                }
     2375
     2376                private void loadDefaultTextualList() {
     2377
     2378                        InputStream textualListStream = TrainWorker.class.getResourceAsStream("/resources/files/textualList.txt");
     2379                        TextualStatistics textualStatistics = new TextualStatistics();
     2380                        textualStatistics.parseTextualList(textualListStream);
     2381                        textualList = textualStatistics.getTextualList();
     2382                        System.out.println("Default Textual List parsed from file successfully." + textualList);
     2383                }
     2384
     2385                private void loadOntology() {
     2386                        InputStream ontologyStream = TrainWorker.class.getResourceAsStream("/resources/files/owl.xml");
     2387                        Ontology ontology = new Ontology(ontologyStream);
     2388                        indirectClasses = ontology.getIndirectClasses();
     2389                        indirectClassesWithIDs = ontology.getIndirectClassesIDs();
     2390                }
     2391
     2392                private Map<File, Double> getAlignedModels(Map<File, Double> filesAndWeights) {
     2393                        Map<File, Double> alignedFilesAndWeights = new HashMap<>();
     2394                        if (modelWithClasses) {
     2395                                for (Entry<File, Double> entry : filesAndWeights.entrySet()) {
     2396                                        String absolutePath = entry.getKey().getAbsolutePath();
     2397                                        if (absolutePath.endsWith(".0")) {
     2398                                                String newPath = absolutePath.substring(0, absolutePath.length()-2) + ".1";
     2399                                                File alignedFile = new File(newPath);
     2400                                                if (alignedFile.exists()) {
     2401                                                        alignedFilesAndWeights.put(alignedFile, entry.getValue());
     2402                                                }
     2403                                        } else {
     2404                                                alignedFilesAndWeights.put(entry.getKey(), entry.getValue());
     2405                                        }
     2406                                }
     2407                        } else {
     2408                                for (Entry<File, Double> entry : filesAndWeights.entrySet()) {
     2409                                        String absolutePath = entry.getKey().getAbsolutePath();
     2410                                        if (absolutePath.endsWith(".1")) {
     2411                                                String newPath = absolutePath.substring(0, absolutePath.length()-2) + ".0";
     2412                                                File alignedFile = new File(newPath);
     2413                                                if (alignedFile.exists()) {
     2414                                                        alignedFilesAndWeights.put(alignedFile, entry.getValue());
     2415                                                }
     2416                                        } else {
     2417                                                alignedFilesAndWeights.put(entry.getKey(), entry.getValue());
     2418                                        }
     2419                                }
     2420                        }
     2421                        return alignedFilesAndWeights;
     2422                }
     2423        }
    24222424}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/OSMRecToggleDialog.java

    r33524 r33525  
    4242import org.openstreetmap.josm.data.osm.event.AbstractDatasetChangedEvent;
    4343import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
     44import org.openstreetmap.josm.gui.MainApplication;
    4445import org.openstreetmap.josm.gui.SideButton;
    4546import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
     
    7172implements SelectionChangedListener, DataSetListenerAdapter.Listener {
    7273
    73     /**
    74     * The tag data of selected objects.
    75     */
    76     private final DefaultTableModel tagData = new ReadOnlyTableModel();
    77 
    78     /**
    79     * The membership data of selected objects.
    80     */
    81     private final DefaultTableModel membershipData = new ReadOnlyTableModel();
    82 
    83     /**
    84     * The tags table.
    85     */
    86     private final JTable tagTable = new JTable(tagData);
    87 
    88     /**
    89     * The membership table.
    90     */
    91     private final JTable membershipTable = new JTable(membershipData);
    92 
    93     /** JPanel containing both previous tables */
    94     private final JPanel bothTables = new JPanel();
    95 
    96     private final transient Map<String, Map<String, Integer>> valueCount = new TreeMap<>();
    97     /**
    98     * This sub-object is responsible for all adding and editing of tags
    99     */
    100     private final transient OSMRecPluginHelper editHelper = new OSMRecPluginHelper(tagData, valueCount);
    101 
    102     private final AddAction addAction = new AddAction();
    103     private final EditActionTrain editAction = new EditActionTrain();
    104     //    private final DeleteAction deleteAction = new DeleteAction();
    105     //    private final JosmAction[] josmActions = new JosmAction[]{addAction, editAction, deleteAction};
    106 
    107     /**
    108     * The Add button (needed to be able to disable it)
    109     */
    110     private final SideButton btnAdd = new SideButton(addAction);
    111     /**
    112     * The Edit button (needed to be able to disable it)
    113     */
    114     private final SideButton btnEdit = new SideButton(editAction);
    115 
    116     /**
    117     * Text to display when nothing selected.
    118     */
    119     private final JLabel selectSth = new JLabel("<html><p>"
    120             + tr("Select objects or create new objects and get recommendation.") + "</p></html>");
    121 
    122     // <editor-fold defaultstate="collapsed" desc="Dialog construction and helper methods">
    123 
    124     /**
    125     * Create a new OSMRecToggleDialog
    126     */
    127     public OSMRecToggleDialog() {
    128         super(tr("Tags/Memberships"), "propertiesdialog", tr("Tags for selected objects."),
    129                 Shortcut.registerShortcut("subwindow:properties", tr("Toggle: {0}", tr("Tags/Memberships")), KeyEvent.VK_P,
    130                         Shortcut.ALT_SHIFT), 150, true);
    131 
    132         System.out.println("cleaning test..");
    133         bothTables.setLayout(new GridBagLayout());
    134         bothTables.setVisible(false); //my
    135         // Let the actions know when selection in the tables change
    136         tagTable.getSelectionModel().addListSelectionListener(editAction);
    137         membershipTable.getSelectionModel().addListSelectionListener(editAction);
    138 
    139         JScrollPane scrollPane = (JScrollPane) createLayout(bothTables, true,
    140                 Arrays.asList(this.btnAdd, this.btnEdit));
    141 
    142         MouseClickWatch mouseClickWatch = new MouseClickWatch();
    143         tagTable.addMouseListener(mouseClickWatch);
    144         membershipTable.addMouseListener(mouseClickWatch);
    145         scrollPane.addMouseListener(mouseClickWatch);
    146         editHelper.loadTagsIfNeeded();
    147 
    148     }
    149 
    150     /**
    151     * This simply fires up an {@link RelationEditor} for the relation shown; everything else
    152     * is the editor's business.
    153     *
    154     * @param row position
    155     */
    156     private void editMembership(int row) {
    157         Relation relation = (Relation) membershipData.getValueAt(row, 0);
    158         Main.map.relationListDialog.selectRelation(relation);
    159     }
    160 
    161     private int findRow(TableModel model, Object value) {
    162         for (int i = 0; i < model.getRowCount(); i++) {
    163             if (model.getValueAt(i, 0).equals(value))
    164                 return i;
    165         }
    166         return -1;
    167     }
    168 
    169     /**
    170     * Update selection status, call @{link #selectionChanged} function.
    171     */
    172     private void updateSelection() {
    173         // Parameter is ignored in this class
    174         selectionChanged(null);
    175     }
    176 
    177     // </editor-fold>
    178 
    179     // <editor-fold defaultstate="collapsed" desc="Event listeners methods">
    180 
    181     @Override
    182     public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
    183         if (tagTable == null)
    184             return; // selection changed may be received in base class constructor before init
    185         if (tagTable.getCellEditor() != null) {
    186             tagTable.getCellEditor().cancelCellEditing();
    187         }
    188 
    189         // Ignore parameter as we do not want to operate always on real selection here, especially in draw mode
    190         Collection<OsmPrimitive> newSel = Main.main.getInProgressSelection();
    191         if (newSel == null) {
    192             newSel = Collections.<OsmPrimitive>emptyList();
    193         }
    194 
    195         String selectedTag;
    196         Relation selectedRelation = null;
    197         selectedTag = editHelper.getChangedKey(); // select last added or last edited key by default
    198         if (selectedTag == null && tagTable.getSelectedRowCount() == 1) {
    199             selectedTag = (String) tagData.getValueAt(tagTable.getSelectedRow(), 0);
    200         }
    201         if (membershipTable.getSelectedRowCount() == 1) {
    202             selectedRelation = (Relation) membershipData.getValueAt(membershipTable.getSelectedRow(), 0);
    203         }
    204 
    205         // re-load tag data
    206         tagData.setRowCount(0);
    207 
    208         final Map<String, String> tags = new HashMap<>();
    209         valueCount.clear();
    210         for (Entry<String, Map<String, Integer>> e : valueCount.entrySet()) {
    211             int count = 0;
    212             for (Entry<String, Integer> e1 : e.getValue().entrySet()) {
    213                 count += e1.getValue();
    214             }
    215             if (count < newSel.size()) {
    216                 e.getValue().put("", newSel.size() - count);
    217             }
    218             tagData.addRow(new Object[]{e.getKey(), e.getValue()});
    219             tags.put(e.getKey(), e.getValue().size() == 1
    220                     ? e.getValue().keySet().iterator().next() : tr("<different>"));
    221         }
    222 
    223         membershipData.setRowCount(0);
    224 
    225         Map<Relation, MemberInfo> roles = new HashMap<>();
    226         for (OsmPrimitive primitive: newSel) {
    227             for (OsmPrimitive ref: primitive.getReferrers(true)) {
    228                 if (ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted()) {
    229                     Relation r = (Relation) ref;
    230                     MemberInfo mi = roles.get(r);
    231                     if (mi == null) {
    232                         mi = new MemberInfo(newSel);
    233                     }
    234                     roles.put(r, mi);
    235                     int i = 1;
    236                     for (RelationMember m : r.getMembers()) {
    237                         if (m.getMember() == primitive) {
    238                             mi.add(m, i);
    239                         }
    240                         ++i;
    241                     }
    242                 }
    243             }
    244         }
    245 
    246         List<Relation> sortedRelations = new ArrayList<>(roles.keySet());
    247         Collections.sort(sortedRelations, new Comparator<Relation>() {
    248             @Override public int compare(Relation o1, Relation o2) {
    249                 int comp = Boolean.valueOf(o1.isDisabledAndHidden()).compareTo(o2.isDisabledAndHidden());
    250                 return comp != 0 ? comp : DefaultNameFormatter.getInstance().getRelationComparator().compare(o1, o2);
    251             } });
    252 
    253         for (Relation r: sortedRelations) {
    254             membershipData.addRow(new Object[]{r, roles.get(r)});
    255         }
    256 
    257         membershipTable.getTableHeader().setVisible(membershipData.getRowCount() > 0);
    258         membershipTable.setVisible(membershipData.getRowCount() > 0);
    259 
    260         boolean hasSelection = !newSel.isEmpty();
    261         boolean hasTags = hasSelection && tagData.getRowCount() > 0;
    262         boolean hasMemberships = hasSelection && membershipData.getRowCount() > 0;
    263 
    264         addAction.setEnabled(hasSelection);
    265         //editAction.setEnabled(hasTags || hasMemberships);
    266         editAction.setEnabled(true);
    267         tagTable.setVisible(hasTags);
    268         tagTable.getTableHeader().setVisible(hasTags);
    269         selectSth.setVisible(!hasSelection);
    270 
    271         int selectedIndex;
    272         if (selectedTag != null && (selectedIndex = findRow(tagData, selectedTag)) != -1) {
    273             tagTable.changeSelection(selectedIndex, 0, false, false);
    274         } else if (selectedRelation != null && (selectedIndex = findRow(membershipData, selectedRelation)) != -1) {
    275             membershipTable.changeSelection(selectedIndex, 0, false, false);
    276         } else if (hasTags) {
    277             tagTable.changeSelection(0, 0, false, false);
    278         } else if (hasMemberships) {
    279             membershipTable.changeSelection(0, 0, false, false);
    280         }
    281     }
    282 
    283     @Override
    284     public void processDatasetEvent(AbstractDatasetChangedEvent event) {
    285         updateSelection();
    286     }
    287 
    288     // </editor-fold>
    289 
    290     // <editor-fold defaultstate="collapsed" desc="Methods that are called by plugins to extend fuctionality ">
    291 
    292 
    293     /**
    294     * Returns the selected tag.
    295     * @return The current selected tag
    296     */
    297     @SuppressWarnings("unchecked")
    298     public Tag getSelectedProperty() {
    299         int row = tagTable.getSelectedRow();
    300         if (row == -1) return null;
    301         Map<String, Integer> map = (TreeMap<String, Integer>) tagData.getValueAt(row, 1);
    302         return new Tag(
    303                 tagData.getValueAt(row, 0).toString(),
    304                 map.size() > 1 ? "" : map.keySet().iterator().next());
    305     }
    306 
    307     /**
    308     * Returns the selected relation membership.
    309     * @return The current selected relation membership
    310     */
    311     public IRelation getSelectedMembershipRelation() {
    312         int row = membershipTable.getSelectedRow();
    313         return row > -1 ? (IRelation) membershipData.getValueAt(row, 0) : null;
    314     }
    315 
    316     // </editor-fold>
    317 
    318     /**
    319     * Class that watches for mouse clicks
    320     * @author imi
    321     */
    322     public class MouseClickWatch extends MouseAdapter {
    323         @Override
    324         public void mouseClicked(MouseEvent e) {
    325             if (e.getClickCount() < 2) {
    326                 // single click, clear selection in other table not clicked in
    327                 if (e.getSource() == tagTable) {
    328                     membershipTable.clearSelection();
    329                 } else if (e.getSource() == membershipTable) {
    330                     tagTable.clearSelection();
    331                 }
    332             } else if (e.getSource() == tagTable) {
    333                 // double click, edit or add tag
    334                 int row = tagTable.rowAtPoint(e.getPoint());
    335                 if (row > -1) {
    336                     boolean focusOnKey = tagTable.columnAtPoint(e.getPoint()) == 0;
    337                     editHelper.editTag(row, focusOnKey);
    338                 } else {
    339                     editHelper.addTag();
    340                 }
    341             } else if (e.getSource() == membershipTable) {
    342                 int row = membershipTable.rowAtPoint(e.getPoint());
    343                 if (row > -1) {
    344                     editMembership(row);
    345                 }
    346             } else {
    347                 editHelper.addTag();
    348             }
    349         }
    350 
    351         @Override
    352         public void mousePressed(MouseEvent e) {
    353             if (e.getSource() == tagTable) {
    354                 membershipTable.clearSelection();
    355             } else if (e.getSource() == membershipTable) {
    356                 tagTable.clearSelection();
    357             }
    358         }
    359     }
    360 
    361     static class MemberInfo {
    362         private List<RelationMember> role = new ArrayList<>();
    363         private Set<OsmPrimitive> members = new HashSet<>();
    364         private List<Integer> position = new ArrayList<>();
    365         private Iterable<OsmPrimitive> selection;
    366         private String positionString;
    367         private String roleString;
    368 
    369         MemberInfo(Iterable<OsmPrimitive> selection) {
    370             this.selection = selection;
    371         }
    372 
    373         void add(RelationMember r, Integer p) {
    374             role.add(r);
    375             members.add(r.getMember());
    376             position.add(p);
    377         }
    378 
    379         @Override
    380         public String toString() {
    381             return "MemberInfo{" +
    382                     "roles='" + roleString + '\'' +
    383                     ", positions='" + positionString + '\'' +
    384                     '}';
    385         }
    386     }
    387 
    388     /**
    389     * Class that allows fast creation of read-only table model with String columns
    390     */
    391     public static class ReadOnlyTableModel extends DefaultTableModel {
    392         @Override
    393         public boolean isCellEditable(int row, int column) {
    394             return false;
    395         }
    396 
    397         @Override
    398         public Class<?> getColumnClass(int columnIndex) {
    399             return String.class;
    400         }
    401     }
    402 
    403     /**
    404     * Action handling add button press in properties dialog.
    405     */
    406     class AddAction extends JosmAction {
    407         AddAction() {
    408             super(tr("Add Recommendation"), /* ICON() */ "dialogs/add", tr("Add a recommended key/value pair to your object"),
    409                     Shortcut.registerShortcut("properties:add", tr("Add Tag"), KeyEvent.VK_A,
    410                             Shortcut.ALT), false);
    411         }
    412 
    413         @Override
    414         public void actionPerformed(ActionEvent e) {
    415             editHelper.addTag();
    416             btnAdd.requestFocusInWindow();
    417         }
    418     }
    419 
    420     /**
    421     * Action handling edit button press in properties dialog.
    422     * training process dialog/configuration
    423     */
    424     class EditActionTrain extends JosmAction implements ListSelectionListener {
    425         EditActionTrain() {
    426             super(tr("Train a Model"), /* ICON() */ "dialogs/fix", tr("Start the training engine!"),
    427                     Shortcut.registerShortcut("properties:edit", tr("Edit Tags"), KeyEvent.VK_S,
    428                             Shortcut.ALT), false);
    429             setEnabled(true);
    430             updateEnabledState();
    431         }
    432 
    433         @Override
    434         public void actionPerformed(ActionEvent e) {
    435             if (!isEnabled())
    436                 return;
    437             if (tagTable.getSelectedRowCount() == 1) {
    438                 int row = tagTable.getSelectedRow();
    439                 editHelper.editTag(row, false);
    440             } else if (membershipTable.getSelectedRowCount() == 1) {
    441                 int row = membershipTable.getSelectedRow();
    442                 editHelper.editTag(row, false);
    443             } else {
    444                 editHelper.editTag(1, false);
    445             }
    446         }
    447 
    448         @Override
    449         protected void updateEnabledState() {
    450             setEnabled(true);
    451         }
    452 
    453         @Override
    454         public void valueChanged(ListSelectionEvent e) {
    455             updateEnabledState();
    456         }
    457     }
     74        /**
     75        * The tag data of selected objects.
     76        */
     77        private final DefaultTableModel tagData = new ReadOnlyTableModel();
     78
     79        /**
     80        * The membership data of selected objects.
     81        */
     82        private final DefaultTableModel membershipData = new ReadOnlyTableModel();
     83
     84        /**
     85        * The tags table.
     86        */
     87        private final JTable tagTable = new JTable(tagData);
     88
     89        /**
     90        * The membership table.
     91        */
     92        private final JTable membershipTable = new JTable(membershipData);
     93
     94        /** JPanel containing both previous tables */
     95        private final JPanel bothTables = new JPanel();
     96
     97        private final transient Map<String, Map<String, Integer>> valueCount = new TreeMap<>();
     98        /**
     99        * This sub-object is responsible for all adding and editing of tags
     100        */
     101        private final transient OSMRecPluginHelper editHelper = new OSMRecPluginHelper(tagData, valueCount);
     102
     103        private final AddAction addAction = new AddAction();
     104        private final EditActionTrain editAction = new EditActionTrain();
     105        //    private final DeleteAction deleteAction = new DeleteAction();
     106        //    private final JosmAction[] josmActions = new JosmAction[]{addAction, editAction, deleteAction};
     107
     108        /**
     109        * The Add button (needed to be able to disable it)
     110        */
     111        private final SideButton btnAdd = new SideButton(addAction);
     112        /**
     113        * The Edit button (needed to be able to disable it)
     114        */
     115        private final SideButton btnEdit = new SideButton(editAction);
     116
     117        /**
     118        * Text to display when nothing selected.
     119        */
     120        private final JLabel selectSth = new JLabel("<html><p>"
     121                        + tr("Select objects or create new objects and get recommendation.") + "</p></html>");
     122
     123        // <editor-fold defaultstate="collapsed" desc="Dialog construction and helper methods">
     124
     125        /**
     126        * Create a new OSMRecToggleDialog
     127        */
     128        public OSMRecToggleDialog() {
     129                super(tr("Tags/Memberships"), "propertiesdialog", tr("Tags for selected objects."),
     130                                Shortcut.registerShortcut("subwindow:properties", tr("Toggle: {0}", tr("Tags/Memberships")), KeyEvent.VK_P,
     131                                                Shortcut.ALT_SHIFT), 150, true);
     132
     133                System.out.println("cleaning test..");
     134                bothTables.setLayout(new GridBagLayout());
     135                bothTables.setVisible(false); //my
     136                // Let the actions know when selection in the tables change
     137                tagTable.getSelectionModel().addListSelectionListener(editAction);
     138                membershipTable.getSelectionModel().addListSelectionListener(editAction);
     139
     140                JScrollPane scrollPane = (JScrollPane) createLayout(bothTables, true,
     141                                Arrays.asList(this.btnAdd, this.btnEdit));
     142
     143                MouseClickWatch mouseClickWatch = new MouseClickWatch();
     144                tagTable.addMouseListener(mouseClickWatch);
     145                membershipTable.addMouseListener(mouseClickWatch);
     146                scrollPane.addMouseListener(mouseClickWatch);
     147                editHelper.loadTagsIfNeeded();
     148
     149        }
     150
     151        /**
     152        * This simply fires up an {@link RelationEditor} for the relation shown; everything else
     153        * is the editor's business.
     154        *
     155        * @param row position
     156        */
     157        private void editMembership(int row) {
     158                Relation relation = (Relation) membershipData.getValueAt(row, 0);
     159                MainApplication.getMap().relationListDialog.selectRelation(relation);
     160        }
     161
     162        private int findRow(TableModel model, Object value) {
     163                for (int i = 0; i < model.getRowCount(); i++) {
     164                        if (model.getValueAt(i, 0).equals(value))
     165                                return i;
     166                }
     167                return -1;
     168        }
     169
     170        /**
     171        * Update selection status, call @{link #selectionChanged} function.
     172        */
     173        private void updateSelection() {
     174                // Parameter is ignored in this class
     175                selectionChanged(null);
     176        }
     177
     178        // </editor-fold>
     179
     180        // <editor-fold defaultstate="collapsed" desc="Event listeners methods">
     181
     182        @Override
     183        public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     184                if (tagTable == null)
     185                        return; // selection changed may be received in base class constructor before init
     186                if (tagTable.getCellEditor() != null) {
     187                        tagTable.getCellEditor().cancelCellEditing();
     188                }
     189
     190                // Ignore parameter as we do not want to operate always on real selection here, especially in draw mode
     191                Collection<OsmPrimitive> newSel = Main.main.getInProgressSelection();
     192                if (newSel == null) {
     193                        newSel = Collections.<OsmPrimitive>emptyList();
     194                }
     195
     196                String selectedTag;
     197                Relation selectedRelation = null;
     198                selectedTag = editHelper.getChangedKey(); // select last added or last edited key by default
     199                if (selectedTag == null && tagTable.getSelectedRowCount() == 1) {
     200                        selectedTag = (String) tagData.getValueAt(tagTable.getSelectedRow(), 0);
     201                }
     202                if (membershipTable.getSelectedRowCount() == 1) {
     203                        selectedRelation = (Relation) membershipData.getValueAt(membershipTable.getSelectedRow(), 0);
     204                }
     205
     206                // re-load tag data
     207                tagData.setRowCount(0);
     208
     209                final Map<String, String> tags = new HashMap<>();
     210                valueCount.clear();
     211                for (Entry<String, Map<String, Integer>> e : valueCount.entrySet()) {
     212                        int count = 0;
     213                        for (Entry<String, Integer> e1 : e.getValue().entrySet()) {
     214                                count += e1.getValue();
     215                        }
     216                        if (count < newSel.size()) {
     217                                e.getValue().put("", newSel.size() - count);
     218                        }
     219                        tagData.addRow(new Object[]{e.getKey(), e.getValue()});
     220                        tags.put(e.getKey(), e.getValue().size() == 1
     221                                        ? e.getValue().keySet().iterator().next() : tr("<different>"));
     222                }
     223
     224                membershipData.setRowCount(0);
     225
     226                Map<Relation, MemberInfo> roles = new HashMap<>();
     227                for (OsmPrimitive primitive: newSel) {
     228                        for (OsmPrimitive ref: primitive.getReferrers(true)) {
     229                                if (ref instanceof Relation && !ref.isIncomplete() && !ref.isDeleted()) {
     230                                        Relation r = (Relation) ref;
     231                                        MemberInfo mi = roles.get(r);
     232                                        if (mi == null) {
     233                                                mi = new MemberInfo(newSel);
     234                                        }
     235                                        roles.put(r, mi);
     236                                        int i = 1;
     237                                        for (RelationMember m : r.getMembers()) {
     238                                                if (m.getMember() == primitive) {
     239                                                        mi.add(m, i);
     240                                                }
     241                                                ++i;
     242                                        }
     243                                }
     244                        }
     245                }
     246
     247                List<Relation> sortedRelations = new ArrayList<>(roles.keySet());
     248                Collections.sort(sortedRelations, new Comparator<Relation>() {
     249                        @Override public int compare(Relation o1, Relation o2) {
     250                                int comp = Boolean.valueOf(o1.isDisabledAndHidden()).compareTo(o2.isDisabledAndHidden());
     251                                return comp != 0 ? comp : DefaultNameFormatter.getInstance().getRelationComparator().compare(o1, o2);
     252                        } });
     253
     254                for (Relation r: sortedRelations) {
     255                        membershipData.addRow(new Object[]{r, roles.get(r)});
     256                }
     257
     258                membershipTable.getTableHeader().setVisible(membershipData.getRowCount() > 0);
     259                membershipTable.setVisible(membershipData.getRowCount() > 0);
     260
     261                boolean hasSelection = !newSel.isEmpty();
     262                boolean hasTags = hasSelection && tagData.getRowCount() > 0;
     263                boolean hasMemberships = hasSelection && membershipData.getRowCount() > 0;
     264
     265                addAction.setEnabled(hasSelection);
     266                //editAction.setEnabled(hasTags || hasMemberships);
     267                editAction.setEnabled(true);
     268                tagTable.setVisible(hasTags);
     269                tagTable.getTableHeader().setVisible(hasTags);
     270                selectSth.setVisible(!hasSelection);
     271
     272                int selectedIndex;
     273                if (selectedTag != null && (selectedIndex = findRow(tagData, selectedTag)) != -1) {
     274                        tagTable.changeSelection(selectedIndex, 0, false, false);
     275                } else if (selectedRelation != null && (selectedIndex = findRow(membershipData, selectedRelation)) != -1) {
     276                        membershipTable.changeSelection(selectedIndex, 0, false, false);
     277                } else if (hasTags) {
     278                        tagTable.changeSelection(0, 0, false, false);
     279                } else if (hasMemberships) {
     280                        membershipTable.changeSelection(0, 0, false, false);
     281                }
     282        }
     283
     284        @Override
     285        public void processDatasetEvent(AbstractDatasetChangedEvent event) {
     286                updateSelection();
     287        }
     288
     289        // </editor-fold>
     290
     291        // <editor-fold defaultstate="collapsed" desc="Methods that are called by plugins to extend fuctionality ">
     292
     293
     294        /**
     295        * Returns the selected tag.
     296        * @return The current selected tag
     297        */
     298        @SuppressWarnings("unchecked")
     299        public Tag getSelectedProperty() {
     300                int row = tagTable.getSelectedRow();
     301                if (row == -1) return null;
     302                Map<String, Integer> map = (TreeMap<String, Integer>) tagData.getValueAt(row, 1);
     303                return new Tag(
     304                                tagData.getValueAt(row, 0).toString(),
     305                                map.size() > 1 ? "" : map.keySet().iterator().next());
     306        }
     307
     308        /**
     309        * Returns the selected relation membership.
     310        * @return The current selected relation membership
     311        */
     312        public IRelation getSelectedMembershipRelation() {
     313                int row = membershipTable.getSelectedRow();
     314                return row > -1 ? (IRelation) membershipData.getValueAt(row, 0) : null;
     315        }
     316
     317        // </editor-fold>
     318
     319        /**
     320        * Class that watches for mouse clicks
     321        * @author imi
     322        */
     323        public class MouseClickWatch extends MouseAdapter {
     324                @Override
     325                public void mouseClicked(MouseEvent e) {
     326                        if (e.getClickCount() < 2) {
     327                                // single click, clear selection in other table not clicked in
     328                                if (e.getSource() == tagTable) {
     329                                        membershipTable.clearSelection();
     330                                } else if (e.getSource() == membershipTable) {
     331                                        tagTable.clearSelection();
     332                                }
     333                        } else if (e.getSource() == tagTable) {
     334                                // double click, edit or add tag
     335                                int row = tagTable.rowAtPoint(e.getPoint());
     336                                if (row > -1) {
     337                                        boolean focusOnKey = tagTable.columnAtPoint(e.getPoint()) == 0;
     338                                        editHelper.editTag(row, focusOnKey);
     339                                } else {
     340                                        editHelper.addTag();
     341                                }
     342                        } else if (e.getSource() == membershipTable) {
     343                                int row = membershipTable.rowAtPoint(e.getPoint());
     344                                if (row > -1) {
     345                                        editMembership(row);
     346                                }
     347                        } else {
     348                                editHelper.addTag();
     349                        }
     350                }
     351
     352                @Override
     353                public void mousePressed(MouseEvent e) {
     354                        if (e.getSource() == tagTable) {
     355                                membershipTable.clearSelection();
     356                        } else if (e.getSource() == membershipTable) {
     357                                tagTable.clearSelection();
     358                        }
     359                }
     360        }
     361
     362        static class MemberInfo {
     363                private List<RelationMember> role = new ArrayList<>();
     364                private Set<OsmPrimitive> members = new HashSet<>();
     365                private List<Integer> position = new ArrayList<>();
     366                private Iterable<OsmPrimitive> selection;
     367                private String positionString;
     368                private String roleString;
     369
     370                MemberInfo(Iterable<OsmPrimitive> selection) {
     371                        this.selection = selection;
     372                }
     373
     374                void add(RelationMember r, Integer p) {
     375                        role.add(r);
     376                        members.add(r.getMember());
     377                        position.add(p);
     378                }
     379
     380                @Override
     381                public String toString() {
     382                        return "MemberInfo{" +
     383                                        "roles='" + roleString + '\'' +
     384                                        ", positions='" + positionString + '\'' +
     385                                        '}';
     386                }
     387        }
     388
     389        /**
     390        * Class that allows fast creation of read-only table model with String columns
     391        */
     392        public static class ReadOnlyTableModel extends DefaultTableModel {
     393                @Override
     394                public boolean isCellEditable(int row, int column) {
     395                        return false;
     396                }
     397
     398                @Override
     399                public Class<?> getColumnClass(int columnIndex) {
     400                        return String.class;
     401                }
     402        }
     403
     404        /**
     405        * Action handling add button press in properties dialog.
     406        */
     407        class AddAction extends JosmAction {
     408                AddAction() {
     409                        super(tr("Add Recommendation"), /* ICON() */ "dialogs/add", tr("Add a recommended key/value pair to your object"),
     410                                        Shortcut.registerShortcut("properties:add", tr("Add Tag"), KeyEvent.VK_A,
     411                                                        Shortcut.ALT), false);
     412                }
     413
     414                @Override
     415                public void actionPerformed(ActionEvent e) {
     416                        editHelper.addTag();
     417                        btnAdd.requestFocusInWindow();
     418                }
     419        }
     420
     421        /**
     422        * Action handling edit button press in properties dialog.
     423        * training process dialog/configuration
     424        */
     425        class EditActionTrain extends JosmAction implements ListSelectionListener {
     426                EditActionTrain() {
     427                        super(tr("Train a Model"), /* ICON() */ "dialogs/fix", tr("Start the training engine!"),
     428                                        Shortcut.registerShortcut("properties:edit", tr("Edit Tags"), KeyEvent.VK_S,
     429                                                        Shortcut.ALT), false);
     430                        setEnabled(true);
     431                        updateEnabledState();
     432                }
     433
     434                @Override
     435                public void actionPerformed(ActionEvent e) {
     436                        if (!isEnabled())
     437                                return;
     438                        if (tagTable.getSelectedRowCount() == 1) {
     439                                int row = tagTable.getSelectedRow();
     440                                editHelper.editTag(row, false);
     441                        } else if (membershipTable.getSelectedRowCount() == 1) {
     442                                int row = membershipTable.getSelectedRow();
     443                                editHelper.editTag(row, false);
     444                        } else {
     445                                editHelper.editTag(1, false);
     446                        }
     447                }
     448
     449                @Override
     450                protected void updateEnabledState() {
     451                        setEnabled(true);
     452                }
     453
     454                @Override
     455                public void valueChanged(ListSelectionEvent e) {
     456                        updateEnabledState();
     457                }
     458        }
    458459}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/extractor/FrequenceExtractor.java

    r32404 r33525  
    1010import javax.xml.parsers.ParserConfigurationException;
    1111
    12 import org.openstreetmap.josm.Main;
    1312import org.openstreetmap.josm.plugins.osmrec.container.OSMNode;
    1413import org.openstreetmap.josm.plugins.osmrec.container.OSMRelation;
    1514import org.openstreetmap.josm.plugins.osmrec.container.OSMWay;
     15import org.openstreetmap.josm.tools.Logging;
    1616import org.openstreetmap.josm.tools.Utils;
    1717import org.xml.sax.Attributes;
     
    2727public class FrequenceExtractor extends DefaultHandler {
    2828
    29     private final List<OSMNode> nodeList; //will be populated with nodes
    30     private final List<OSMRelation> relationList;
    31     private final Map<String, OSMNode> nodesWithIDs; //map containing IDs as Strings and the corresponding OSMNode objects
    32     private final List<OSMWay> wayList;  //populated with ways of the OSM file
    33     private final String osmXmlFileName;
    34     private OSMNode nodeTmp;
    35     private OSMWay wayTmp;
    36     private OSMRelation relationTmp;
    37     private boolean inWay = false; //when parser is in a way node becomes true in order to track the parser position
    38     private boolean inNode = false; //becomes true when the parser is in a simple node
    39     private boolean inRelation = false; //becomes true when the parser is in a relarion node
    40     private Map<String, Integer> frequency;
    41 
    42     public FrequenceExtractor(String osmXmlFileName) {
    43         this.osmXmlFileName = osmXmlFileName;
    44         nodeList = new ArrayList<>();
    45         wayList = new ArrayList<>();
    46         relationList = new ArrayList<>();
    47         nodesWithIDs = new HashMap<>();
    48         frequency = new HashMap<>();
    49         for (int i = 0; i < 100; i++) {
    50             frequency.put("", 0);
    51         }
    52     }
    53 
    54     public void parseDocument() {
    55         Main.info("extracting frequencies...");
    56         try {
    57             Utils.newSafeSAXParser().parse(osmXmlFileName, this);
    58         } catch (ParserConfigurationException | IOException | SAXException e) {
    59             Main.error(e);
    60         }
    61     }
    62 
    63     @Override
    64     public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
    65 
    66         // if current element is an OSMNode , create new node and populate with the appropriate values
    67         if (elementName.equalsIgnoreCase("node")) {
    68             nodeTmp = new OSMNode();
    69             inNode = true;
    70             inWay = false;
    71             inRelation = false;
    72 
    73         } else if (elementName.equalsIgnoreCase("way")) {
    74             wayTmp = new OSMWay();
    75             //wayTmp.setID(attributes.getValue("id"));
    76             inWay = true;
    77             inNode = false;
    78             inRelation = false;
    79         } else if (elementName.equalsIgnoreCase("relation")) {
    80             relationTmp = new OSMRelation();
    81             //relationTmp.setID(attributes.getValue("id"));
    82             inRelation = true;
    83             inWay = false;
    84             inNode = false;
    85         } else if (elementName.equalsIgnoreCase("nd")) {
    86             //wayTmp.addNodeReference(attributes.getValue("ref"));
    87 
    88         } else if (elementName.equalsIgnoreCase("tag")) {
    89 
    90             if (inNode) {
    91                 //if the path is in an OSMNode set tagKey and value to the corresponding node
    92                 nodeTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    93             } else if (inWay) {
    94                 //else if the path is in an OSM way set tagKey and value to the corresponding way
    95                 wayTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    96             } else if (inRelation) {
    97                 //set the key-value pairs of relation tags
    98                 relationTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    99             }
    100 
    101         } else if (elementName.equalsIgnoreCase("member")) {
    102             //relationTmp.addMemberReference(attributes.getValue("ref"));
    103         }
    104     }
    105 
    106     @Override
    107     public void endElement(String s, String s1, String element) throws SAXException {
    108         // if end of node element, add to appropriate list
    109         if (element.equalsIgnoreCase("node")) {
    110             Map<String, String> tags = nodeTmp.getTagKeyValue();
    111             if (tags.keySet().contains("name")) {
    112                 for (Map.Entry<String, String> tag : tags.entrySet()) {
    113                     if (tag.getKey().equals("name")) {
    114                         //split name value in each white space and store the values separetely. Count each occurance
    115                         String name = tag.getValue();
    116                         String[] SplitName = name.split("\\s+");
    117 
    118                         for (String split : SplitName) {
    119                             //put all splits with zero, at the constructor. put here the incremented values. for tomoro
    120                             if (frequency.get(split) != null) {
    121                                 int k = frequency.get(split) +1;
    122                                 frequency.put(split, k);
    123                             } else {
    124                                 frequency.put(split, 1);
    125                             }
    126                         }
    127                     }
    128                 }
    129             }
    130         }
    131 
    132         if (element.equalsIgnoreCase("way")) {
    133             //name frequency
    134             Map<String, String> tags = wayTmp.getTagKeyValue();
    135 
    136             if (tags.keySet().contains("name")) {
    137                 for (Map.Entry<String, String> tag : tags.entrySet()) {
    138                     if (tag.getKey().equals("name")) {
    139                         //split name value in each white space and store the values separetely. Count each occurance
    140                         String name = tag.getValue();
    141                         String[] SplitName = name.split("\\s+");
    142                         for (String split : SplitName) {
    143                             //put all splits with zero, at the constructor. put here the incremented values. for tomoro
    144                             if (frequency.get(split) != null) {
    145                                 int k = frequency.get(split) +1;
    146                                 frequency.put(split, k);
    147                             } else {
    148                                 frequency.put(split, 1);
    149                             }
    150                         }
    151                     }
    152                 }
    153             }
    154         }
    155 
    156         if (element.equalsIgnoreCase("relation")) {
    157             //name frequency
    158             Map<String, String> tags = relationTmp.getTagKeyValue();
    159 
    160             if (tags.keySet().contains("name")) {
    161                 for (Map.Entry<String, String> tag : tags.entrySet()) {
    162                     if (tag.getKey().equals("name")) {
    163                         //split name value in each white space and store the values separetely. Count each occurance
    164                         String name = tag.getValue();
    165                         String[] SplitName = name.split("\\s+");
    166 
    167                         for (String split : SplitName) {
    168                             //put all splits with zero, at the constructor. put here the incremented values. for tomoro
    169                             if (frequency.get(split) != null) {
    170                                 int k = frequency.get(split) +1;
    171                                 frequency.put(split, k);
    172                             } else {
    173                                 frequency.put(split, 1);
    174                             }
    175                         }
    176                     }
    177                 }
    178             }
    179         }
    180     }
    181 
    182     public List<OSMNode> getNodeList() {
    183         return nodeList;
    184     }
    185 
    186     public List<OSMWay> getWayList() {
    187         return wayList;
    188     }
    189 
    190     public List<OSMRelation> getRelationList() {
    191         return relationList;
    192     }
    193 
    194     public Map<String, OSMNode> getNodesWithIDs() {
    195         return nodesWithIDs;
    196     }
    197 
    198     //frequency temp
    199     public Map<String, Integer> getFrequency() {
    200         return frequency;
    201     }
     29        private final List<OSMNode> nodeList; //will be populated with nodes
     30        private final List<OSMRelation> relationList;
     31        private final Map<String, OSMNode> nodesWithIDs; //map containing IDs as Strings and the corresponding OSMNode objects
     32        private final List<OSMWay> wayList;  //populated with ways of the OSM file
     33        private final String osmXmlFileName;
     34        private OSMNode nodeTmp;
     35        private OSMWay wayTmp;
     36        private OSMRelation relationTmp;
     37        private boolean inWay = false; //when parser is in a way node becomes true in order to track the parser position
     38        private boolean inNode = false; //becomes true when the parser is in a simple node
     39        private boolean inRelation = false; //becomes true when the parser is in a relarion node
     40        private Map<String, Integer> frequency;
     41
     42        public FrequenceExtractor(String osmXmlFileName) {
     43                this.osmXmlFileName = osmXmlFileName;
     44                nodeList = new ArrayList<>();
     45                wayList = new ArrayList<>();
     46                relationList = new ArrayList<>();
     47                nodesWithIDs = new HashMap<>();
     48                frequency = new HashMap<>();
     49                for (int i = 0; i < 100; i++) {
     50                        frequency.put("", 0);
     51                }
     52        }
     53
     54        public void parseDocument() {
     55                Logging.info("extracting frequencies...");
     56                try {
     57                        Utils.newSafeSAXParser().parse(osmXmlFileName, this);
     58                } catch (ParserConfigurationException | IOException | SAXException e) {
     59                        Logging.error(e);
     60                }
     61        }
     62
     63        @Override
     64        public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
     65
     66                // if current element is an OSMNode , create new node and populate with the appropriate values
     67                if (elementName.equalsIgnoreCase("node")) {
     68                        nodeTmp = new OSMNode();
     69                        inNode = true;
     70                        inWay = false;
     71                        inRelation = false;
     72
     73                } else if (elementName.equalsIgnoreCase("way")) {
     74                        wayTmp = new OSMWay();
     75                        //wayTmp.setID(attributes.getValue("id"));
     76                        inWay = true;
     77                        inNode = false;
     78                        inRelation = false;
     79                } else if (elementName.equalsIgnoreCase("relation")) {
     80                        relationTmp = new OSMRelation();
     81                        //relationTmp.setID(attributes.getValue("id"));
     82                        inRelation = true;
     83                        inWay = false;
     84                        inNode = false;
     85                } else if (elementName.equalsIgnoreCase("nd")) {
     86                        //wayTmp.addNodeReference(attributes.getValue("ref"));
     87
     88                } else if (elementName.equalsIgnoreCase("tag")) {
     89
     90                        if (inNode) {
     91                                //if the path is in an OSMNode set tagKey and value to the corresponding node
     92                                nodeTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     93                        } else if (inWay) {
     94                                //else if the path is in an OSM way set tagKey and value to the corresponding way
     95                                wayTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     96                        } else if (inRelation) {
     97                                //set the key-value pairs of relation tags
     98                                relationTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     99                        }
     100
     101                } else if (elementName.equalsIgnoreCase("member")) {
     102                        //relationTmp.addMemberReference(attributes.getValue("ref"));
     103                }
     104        }
     105
     106        @Override
     107        public void endElement(String s, String s1, String element) throws SAXException {
     108                // if end of node element, add to appropriate list
     109                if (element.equalsIgnoreCase("node")) {
     110                        Map<String, String> tags = nodeTmp.getTagKeyValue();
     111                        if (tags.keySet().contains("name")) {
     112                                for (Map.Entry<String, String> tag : tags.entrySet()) {
     113                                        if (tag.getKey().equals("name")) {
     114                                                //split name value in each white space and store the values separetely. Count each occurance
     115                                                String name = tag.getValue();
     116                                                String[] SplitName = name.split("\\s+");
     117
     118                                                for (String split : SplitName) {
     119                                                        //put all splits with zero, at the constructor. put here the incremented values. for tomoro
     120                                                        if (frequency.get(split) != null) {
     121                                                                int k = frequency.get(split) +1;
     122                                                                frequency.put(split, k);
     123                                                        } else {
     124                                                                frequency.put(split, 1);
     125                                                        }
     126                                                }
     127                                        }
     128                                }
     129                        }
     130                }
     131
     132                if (element.equalsIgnoreCase("way")) {
     133                        //name frequency
     134                        Map<String, String> tags = wayTmp.getTagKeyValue();
     135
     136                        if (tags.keySet().contains("name")) {
     137                                for (Map.Entry<String, String> tag : tags.entrySet()) {
     138                                        if (tag.getKey().equals("name")) {
     139                                                //split name value in each white space and store the values separetely. Count each occurance
     140                                                String name = tag.getValue();
     141                                                String[] SplitName = name.split("\\s+");
     142                                                for (String split : SplitName) {
     143                                                        //put all splits with zero, at the constructor. put here the incremented values. for tomoro
     144                                                        if (frequency.get(split) != null) {
     145                                                                int k = frequency.get(split) +1;
     146                                                                frequency.put(split, k);
     147                                                        } else {
     148                                                                frequency.put(split, 1);
     149                                                        }
     150                                                }
     151                                        }
     152                                }
     153                        }
     154                }
     155
     156                if (element.equalsIgnoreCase("relation")) {
     157                        //name frequency
     158                        Map<String, String> tags = relationTmp.getTagKeyValue();
     159
     160                        if (tags.keySet().contains("name")) {
     161                                for (Map.Entry<String, String> tag : tags.entrySet()) {
     162                                        if (tag.getKey().equals("name")) {
     163                                                //split name value in each white space and store the values separetely. Count each occurance
     164                                                String name = tag.getValue();
     165                                                String[] SplitName = name.split("\\s+");
     166
     167                                                for (String split : SplitName) {
     168                                                        //put all splits with zero, at the constructor. put here the incremented values. for tomoro
     169                                                        if (frequency.get(split) != null) {
     170                                                                int k = frequency.get(split) +1;
     171                                                                frequency.put(split, k);
     172                                                        } else {
     173                                                                frequency.put(split, 1);
     174                                                        }
     175                                                }
     176                                        }
     177                                }
     178                        }
     179                }
     180        }
     181
     182        public List<OSMNode> getNodeList() {
     183                return nodeList;
     184        }
     185
     186        public List<OSMWay> getWayList() {
     187                return wayList;
     188        }
     189
     190        public List<OSMRelation> getRelationList() {
     191                return relationList;
     192        }
     193
     194        public Map<String, OSMNode> getNodesWithIDs() {
     195                return nodesWithIDs;
     196        }
     197
     198        //frequency temp
     199        public Map<String, Integer> getFrequency() {
     200                return frequency;
     201        }
    202202}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/extractor/LanguageDetector.java

    r32404 r33525  
    99import java.util.logging.Logger;
    1010
    11 import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.tools.Logging;
    1212import org.openstreetmap.josm.tools.Utils;
    1313
     
    2323public final class LanguageDetector {
    2424
    25     private static LanguageDetector languageDetector = null;
     25        private static LanguageDetector languageDetector = null;
    2626
    27     private LanguageDetector() {
    28         //prevent instatiation
    29     }
     27        private LanguageDetector() {
     28                //prevent instatiation
     29        }
    3030
    31     public static LanguageDetector getInstance(String languageProfilesPath) {
    32         if (languageDetector == null) {
    33             languageDetector = new LanguageDetector();
    34             loadProfilesFromStream(languageProfilesPath);
    35             //profilesLoaded = true;
    36         }
    37         return languageDetector;
    38     }
     31        public static LanguageDetector getInstance(String languageProfilesPath) {
     32                if (languageDetector == null) {
     33                        languageDetector = new LanguageDetector();
     34                        loadProfilesFromStream(languageProfilesPath);
     35                        //profilesLoaded = true;
     36                }
     37                return languageDetector;
     38        }
    3939
    40     public static void loadProfilesFromStream(String languageProfilesPath) { //create profiles directory in system from stream and load them
     40        public static void loadProfilesFromStream(String languageProfilesPath) { //create profiles directory in system from stream and load them
    4141
    42         /*  supported languages
     42                /*  supported languages
    4343            el:greek, en:english, de:german, fr:french, es:spanish, ru:russian, tr:turkish, zh-cn:chinese, hi:hindi
    44         */
    45         InputStream languageProfilesInputStreamEl = LanguageDetector.class.getResourceAsStream("/profiles/el");
    46         InputStream languageProfilesInputStreamEn = LanguageDetector.class.getResourceAsStream("/profiles/en");
    47         InputStream languageProfilesInputStreamDe = LanguageDetector.class.getResourceAsStream("/profiles/de");
    48         InputStream languageProfilesInputStreamFr = LanguageDetector.class.getResourceAsStream("/profiles/fr");
    49         InputStream languageProfilesInputStreamEs = LanguageDetector.class.getResourceAsStream("/profiles/es");
    50         InputStream languageProfilesInputStreamRu = LanguageDetector.class.getResourceAsStream("/profiles/ru");
    51         InputStream languageProfilesInputStreamTr = LanguageDetector.class.getResourceAsStream("/profiles/tr");
    52         InputStream languageProfilesInputStreamZh = LanguageDetector.class.getResourceAsStream("/profiles/zh-cn");
    53         InputStream languageProfilesInputStreamHi = LanguageDetector.class.getResourceAsStream("/profiles/hi");
    54         //InputStream languageProfilesInputStream2 = LanguageDetector.class.getResourceAsStream("/resources/profiles/en");
     44                */
     45                InputStream languageProfilesInputStreamEl = LanguageDetector.class.getResourceAsStream("/profiles/el");
     46                InputStream languageProfilesInputStreamEn = LanguageDetector.class.getResourceAsStream("/profiles/en");
     47                InputStream languageProfilesInputStreamDe = LanguageDetector.class.getResourceAsStream("/profiles/de");
     48                InputStream languageProfilesInputStreamFr = LanguageDetector.class.getResourceAsStream("/profiles/fr");
     49                InputStream languageProfilesInputStreamEs = LanguageDetector.class.getResourceAsStream("/profiles/es");
     50                InputStream languageProfilesInputStreamRu = LanguageDetector.class.getResourceAsStream("/profiles/ru");
     51                InputStream languageProfilesInputStreamTr = LanguageDetector.class.getResourceAsStream("/profiles/tr");
     52                InputStream languageProfilesInputStreamZh = LanguageDetector.class.getResourceAsStream("/profiles/zh-cn");
     53                InputStream languageProfilesInputStreamHi = LanguageDetector.class.getResourceAsStream("/profiles/hi");
     54                //InputStream languageProfilesInputStream2 = LanguageDetector.class.getResourceAsStream("/resources/profiles/en");
    5555
    56         if (!new File(languageProfilesPath).exists()) {
    57             Utils.mkDirs(new File(languageProfilesPath));
    58         }
     56                if (!new File(languageProfilesPath).exists()) {
     57                        Utils.mkDirs(new File(languageProfilesPath));
     58                }
    5959
    60         File languageProfilesOutputFileEl = new File(languageProfilesPath + "/el");
    61         File languageProfilesOutputFileEn = new File(languageProfilesPath + "/en");
    62         File languageProfilesOutputFileDe = new File(languageProfilesPath + "/de");
    63         File languageProfilesOutputFileFr = new File(languageProfilesPath + "/fr");
    64         File languageProfilesOutputFileEs = new File(languageProfilesPath + "/es");
    65         File languageProfilesOutputFileRu = new File(languageProfilesPath + "/ru");
    66         File languageProfilesOutputFileTr = new File(languageProfilesPath + "/tr");
    67         File languageProfilesOutputFileZh = new File(languageProfilesPath + "/zh-cn");
    68         File languageProfilesOutputFileHi = new File(languageProfilesPath + "/hi");
     60                File languageProfilesOutputFileEl = new File(languageProfilesPath + "/el");
     61                File languageProfilesOutputFileEn = new File(languageProfilesPath + "/en");
     62                File languageProfilesOutputFileDe = new File(languageProfilesPath + "/de");
     63                File languageProfilesOutputFileFr = new File(languageProfilesPath + "/fr");
     64                File languageProfilesOutputFileEs = new File(languageProfilesPath + "/es");
     65                File languageProfilesOutputFileRu = new File(languageProfilesPath + "/ru");
     66                File languageProfilesOutputFileTr = new File(languageProfilesPath + "/tr");
     67                File languageProfilesOutputFileZh = new File(languageProfilesPath + "/zh-cn");
     68                File languageProfilesOutputFileHi = new File(languageProfilesPath + "/hi");
    6969
    70         try {
    71             languageProfilesOutputFileEl.createNewFile();
    72             languageProfilesOutputFileEn.createNewFile();
    73             languageProfilesOutputFileDe.createNewFile();
    74             languageProfilesOutputFileFr.createNewFile();
    75             languageProfilesOutputFileEs.createNewFile();
    76             languageProfilesOutputFileRu.createNewFile();
    77             languageProfilesOutputFileTr.createNewFile();
    78             languageProfilesOutputFileZh.createNewFile();
    79             languageProfilesOutputFileHi.createNewFile();
    80         } catch (IOException ex) {
    81             Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
    82             Main.error(ex);
    83         }
     70                try {
     71                        languageProfilesOutputFileEl.createNewFile();
     72                        languageProfilesOutputFileEn.createNewFile();
     73                        languageProfilesOutputFileDe.createNewFile();
     74                        languageProfilesOutputFileFr.createNewFile();
     75                        languageProfilesOutputFileEs.createNewFile();
     76                        languageProfilesOutputFileRu.createNewFile();
     77                        languageProfilesOutputFileTr.createNewFile();
     78                        languageProfilesOutputFileZh.createNewFile();
     79                        languageProfilesOutputFileHi.createNewFile();
     80                } catch (IOException ex) {
     81                        Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
     82                        Logging.error(ex);
     83                }
    8484
    85         try {
    86             Files.copy(languageProfilesInputStreamEl, languageProfilesOutputFileEl.toPath());
    87             Files.copy(languageProfilesInputStreamEn, languageProfilesOutputFileEn.toPath());
    88             Files.copy(languageProfilesInputStreamDe, languageProfilesOutputFileDe.toPath());
    89             Files.copy(languageProfilesInputStreamFr, languageProfilesOutputFileFr.toPath());
    90             Files.copy(languageProfilesInputStreamEs, languageProfilesOutputFileEs.toPath());
    91             Files.copy(languageProfilesInputStreamRu, languageProfilesOutputFileRu.toPath());
    92             Files.copy(languageProfilesInputStreamTr, languageProfilesOutputFileTr.toPath());
    93             Files.copy(languageProfilesInputStreamZh, languageProfilesOutputFileZh.toPath());
    94             Files.copy(languageProfilesInputStreamHi, languageProfilesOutputFileHi.toPath());
    95         } catch (IOException ex) {
    96             Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
    97             Main.error(ex);
    98         }
     85                try {
     86                        Files.copy(languageProfilesInputStreamEl, languageProfilesOutputFileEl.toPath());
     87                        Files.copy(languageProfilesInputStreamEn, languageProfilesOutputFileEn.toPath());
     88                        Files.copy(languageProfilesInputStreamDe, languageProfilesOutputFileDe.toPath());
     89                        Files.copy(languageProfilesInputStreamFr, languageProfilesOutputFileFr.toPath());
     90                        Files.copy(languageProfilesInputStreamEs, languageProfilesOutputFileEs.toPath());
     91                        Files.copy(languageProfilesInputStreamRu, languageProfilesOutputFileRu.toPath());
     92                        Files.copy(languageProfilesInputStreamTr, languageProfilesOutputFileTr.toPath());
     93                        Files.copy(languageProfilesInputStreamZh, languageProfilesOutputFileZh.toPath());
     94                        Files.copy(languageProfilesInputStreamHi, languageProfilesOutputFileHi.toPath());
     95                } catch (IOException ex) {
     96                        Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
     97                        Logging.error(ex);
     98                }
    9999
    100         try {
    101             DetectorFactory.loadProfile(languageProfilesPath);
    102         } catch (LangDetectException ex) {
    103             Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
    104             Main.error(ex);
    105         }
    106     }
     100                try {
     101                        DetectorFactory.loadProfile(languageProfilesPath);
     102                } catch (LangDetectException ex) {
     103                        Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
     104                        Logging.error(ex);
     105                }
     106        }
    107107
    108     public String detect(String text) {
    109         try {
    110             Detector detector = DetectorFactory.create();
    111             detector.append(text);
    112             return detector.detect();
    113         } catch (LangDetectException ex) {
    114             Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
    115             Main.error(ex);
    116             return "en"; //default lang to return if anything goes wrong at detection
    117         }
    118     }
     108        public String detect(String text) {
     109                try {
     110                        Detector detector = DetectorFactory.create();
     111                        detector.append(text);
     112                        return detector.detect();
     113                } catch (LangDetectException ex) {
     114                        Logger.getLogger(LanguageDetector.class.getName()).log(Level.SEVERE, null, ex);
     115                        Logging.error(ex);
     116                        return "en"; //default lang to return if anything goes wrong at detection
     117                }
     118        }
    119119}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/parsers/OSMParser.java

    r32404 r33525  
    2121import org.opengis.referencing.operation.MathTransform;
    2222import org.opengis.referencing.operation.TransformException;
    23 import org.openstreetmap.josm.Main;
    2423import org.openstreetmap.josm.plugins.osmrec.container.OSMNode;
    2524import org.openstreetmap.josm.plugins.osmrec.container.OSMRelation;
    2625import org.openstreetmap.josm.plugins.osmrec.container.OSMWay;
     26import org.openstreetmap.josm.tools.Logging;
    2727import org.openstreetmap.josm.tools.Utils;
    2828import org.xml.sax.Attributes;
     
    4545public class OSMParser extends DefaultHandler {
    4646
    47     //private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OSMParser.class);
    48 
    49     //change from wgs84 to cartesian for later processing of the geometry
    50     private static final CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
    51     private static final CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
    52     private final GeometryFactory geometryFactory = new GeometryFactory();
    53     private static MathTransform transform = null;
    54     private final List<OSMNode> nodeList; //will be populated with nodes
    55     private final List<OSMRelation> relationList;
    56     private final Map<String, OSMNode> nodesWithIDs; //map containing IDs as Strings and the corresponding OSMNode objects
    57     private final List<OSMWay> wayList;  //populated with ways of the OSM file
    58     private final String osmXmlFileName;
    59     private OSMNode nodeTmp; //variable to hold the node object
    60     private OSMWay wayTmp;   //variable to hold the way object
    61     private OSMRelation relationTmp;
    62     private boolean inWay = false; //when parser is in a way node becomes true in order to track the parser position
    63     private boolean inNode = false; //becomes true when the parser is in a simple node
    64     private boolean inRelation = false; //becomes true when the parser is in a relarion node
    65 
    66     public OSMParser(String osmXmlFileName) {
    67         this.osmXmlFileName = osmXmlFileName;
    68         nodeList = new ArrayList<>();
    69         wayList = new ArrayList<>();
    70         relationList = new ArrayList<>();
    71         nodesWithIDs = new HashMap<>();
    72         try {
    73             transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
    74         } catch (FactoryException ex) {
    75             Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
    76         }
    77     }
    78 
    79     public void parseDocument() {
    80         try {
    81             Utils.newSafeSAXParser().parse(osmXmlFileName, this);
    82         } catch (ParserConfigurationException | SAXException | IOException e) {
    83             Main.error(e);
    84         }
    85     }
    86 
    87     @Override
    88     public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
    89 
    90         // if current element is an OSMNode , create new node and populate with the appropriate values
    91         if (elementName.equalsIgnoreCase("node")) {
    92             nodeTmp = new OSMNode();
    93             nodeTmp.setID(attributes.getValue("id"));
    94             nodeTmp.setUser(attributes.getValue("user"));
    95             //parse geometry
    96             double longitude = Double.parseDouble(attributes.getValue("lon"));
    97             double latitude = Double.parseDouble(attributes.getValue("lat"));
    98 
    99             Coordinate targetGeometry = null;
    100             Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
    101             try {
    102                 targetGeometry = JTS.transform(sourceCoordinate, null, transform);
    103             } catch (MismatchedDimensionException | TransformException ex) {
    104                 Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
    105             }
    106 
    107             //create geometry object
    108             Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
    109             nodeTmp.setGeometry(geom);
    110             inNode = true;
    111             inWay = false;
    112             inRelation = false;
    113 
    114         } else if (elementName.equalsIgnoreCase("way")) {
    115             wayTmp = new OSMWay();
    116             wayTmp.setID(attributes.getValue("id"));
    117 
    118             if (attributes.getValue("user") != null) {
    119                 wayTmp.setUser(attributes.getValue("user"));
    120             } else {
    121                 wayTmp.setUser("undefined");
    122             }
    123 
    124             inWay = true;
    125             inNode = false;
    126             inRelation = false;
    127         } else if (elementName.equalsIgnoreCase("relation")) {
    128             relationTmp = new OSMRelation();
    129             relationTmp.setID(attributes.getValue("id"));
    130             inRelation = true;
    131             inWay = false;
    132             inNode = false;
    133         } else if (elementName.equalsIgnoreCase("nd")) {
    134             wayTmp.addNodeReference(attributes.getValue("ref"));
    135 
    136         } else if (elementName.equalsIgnoreCase("tag")) {
    137 
    138             if (inNode) {
    139                 //if the path is in an OSMNode set tagKey and value to the corresponding node
    140                 nodeTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    141             } else if (inWay) {
    142                 //else if the path is in an OSM way set tagKey and value to the corresponding way
    143                 wayTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    144             } else if (inRelation) {
    145                 //set the key-value pairs of relation tags
    146                 relationTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
    147             }
    148         } else if (elementName.equalsIgnoreCase("member")) {
    149             relationTmp.addMemberReference(attributes.getValue("ref"));
    150         }
    151     }
    152 
    153     @Override
    154     public void endElement(String s, String s1, String element) throws SAXException {
    155         // if end of node element, add to appropriate list
    156         if (element.equalsIgnoreCase("node")) {
    157             nodeList.add(nodeTmp);
    158             nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
    159         }
    160 
    161         if (element.equalsIgnoreCase("way")) {
    162 
    163             //construct the Way geometry from each node of the node references
    164             List<String> references = wayTmp.getNodeReferences();
    165 
    166             for (String entry: references) {
    167                 Geometry geometry = nodesWithIDs.get(entry).getGeometry(); //get the geometry of the node with ID=entry
    168                 wayTmp.addNodeGeometry(geometry); //add the node geometry in this way
    169 
    170             }
    171             Geometry geom = geometryFactory.buildGeometry(wayTmp.getNodeGeometries());
    172 
    173             if ((wayTmp.getNumberOfNodes() > 3) &&
    174                     wayTmp.getNodeGeometries().get(0).equals(wayTmp.getNodeGeometries()
    175                             .get(wayTmp.getNodeGeometries().size()-1))) {
    176                 //checks if the beginning and ending node are the same and the number of nodes are more than 3.
    177                 //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
    178 
    179                 if (!((wayTmp.getTagKeyValue().containsKey("barrier")) || wayTmp.getTagKeyValue().containsKey("highway"))) {
    180                     //this is not a barrier nor a road, so construct a polygon geometry
    181 
    182                     LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
    183                     Polygon poly = new Polygon(linear, null, geometryFactory);
    184                     wayTmp.setGeometry(poly);
    185                 } else {
    186                     //it is either a barrier or a road, so construct a linear ring geometry
    187                     LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
    188                     wayTmp.setGeometry(linear);
    189                 }
    190             } else if (wayTmp.getNumberOfNodes() > 1) {
    191                 //it is an open geometry with more than one nodes, make it linestring
    192 
    193                 LineString lineString = geometryFactory.createLineString(geom.getCoordinates());
    194                 wayTmp.setGeometry(lineString);
    195             } else { //we assume all the rest geometries are points
    196                 //some ways happen to have only one point. Construct a  Point.
    197                 Point point = geometryFactory.createPoint(geom.getCoordinate());
    198                 wayTmp.setGeometry(point);
    199             }
    200             wayList.add(wayTmp);
    201         }
    202 
    203         if (element.equalsIgnoreCase("relation")) {
    204             relationList.add(relationTmp);
    205         }
    206     }
    207 
    208     public List<OSMNode> getNodeList() {
    209         return nodeList;
    210     }
    211 
    212     public List<OSMWay> getWayList() {
    213         return wayList;
    214     }
    215 
    216     public List<OSMRelation> getRelationList() {
    217         return relationList;
    218     }
    219 
    220     public Map<String, OSMNode> getNodesWithIDs() {
    221         return nodesWithIDs;
    222     }
     47        //private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OSMParser.class);
     48
     49        //change from wgs84 to cartesian for later processing of the geometry
     50        private static final CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
     51        private static final CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
     52        private final GeometryFactory geometryFactory = new GeometryFactory();
     53        private static MathTransform transform = null;
     54        private final List<OSMNode> nodeList; //will be populated with nodes
     55        private final List<OSMRelation> relationList;
     56        private final Map<String, OSMNode> nodesWithIDs; //map containing IDs as Strings and the corresponding OSMNode objects
     57        private final List<OSMWay> wayList;  //populated with ways of the OSM file
     58        private final String osmXmlFileName;
     59        private OSMNode nodeTmp; //variable to hold the node object
     60        private OSMWay wayTmp;   //variable to hold the way object
     61        private OSMRelation relationTmp;
     62        private boolean inWay = false; //when parser is in a way node becomes true in order to track the parser position
     63        private boolean inNode = false; //becomes true when the parser is in a simple node
     64        private boolean inRelation = false; //becomes true when the parser is in a relarion node
     65
     66        public OSMParser(String osmXmlFileName) {
     67                this.osmXmlFileName = osmXmlFileName;
     68                nodeList = new ArrayList<>();
     69                wayList = new ArrayList<>();
     70                relationList = new ArrayList<>();
     71                nodesWithIDs = new HashMap<>();
     72                try {
     73                        transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
     74                } catch (FactoryException ex) {
     75                        Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
     76                }
     77        }
     78
     79        public void parseDocument() {
     80                try {
     81                        Utils.newSafeSAXParser().parse(osmXmlFileName, this);
     82                } catch (ParserConfigurationException | SAXException | IOException e) {
     83                        Logging.error(e);
     84                }
     85        }
     86
     87        @Override
     88        public void startElement(String s, String s1, String elementName, Attributes attributes) throws SAXException {
     89
     90                // if current element is an OSMNode , create new node and populate with the appropriate values
     91                if (elementName.equalsIgnoreCase("node")) {
     92                        nodeTmp = new OSMNode();
     93                        nodeTmp.setID(attributes.getValue("id"));
     94                        nodeTmp.setUser(attributes.getValue("user"));
     95                        //parse geometry
     96                        double longitude = Double.parseDouble(attributes.getValue("lon"));
     97                        double latitude = Double.parseDouble(attributes.getValue("lat"));
     98
     99                        Coordinate targetGeometry = null;
     100                        Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
     101                        try {
     102                                targetGeometry = JTS.transform(sourceCoordinate, null, transform);
     103                        } catch (MismatchedDimensionException | TransformException ex) {
     104                                Logger.getLogger(OSMParser.class.getName()).log(Level.SEVERE, null, ex);
     105                        }
     106
     107                        //create geometry object
     108                        Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
     109                        nodeTmp.setGeometry(geom);
     110                        inNode = true;
     111                        inWay = false;
     112                        inRelation = false;
     113
     114                } else if (elementName.equalsIgnoreCase("way")) {
     115                        wayTmp = new OSMWay();
     116                        wayTmp.setID(attributes.getValue("id"));
     117
     118                        if (attributes.getValue("user") != null) {
     119                                wayTmp.setUser(attributes.getValue("user"));
     120                        } else {
     121                                wayTmp.setUser("undefined");
     122                        }
     123
     124                        inWay = true;
     125                        inNode = false;
     126                        inRelation = false;
     127                } else if (elementName.equalsIgnoreCase("relation")) {
     128                        relationTmp = new OSMRelation();
     129                        relationTmp.setID(attributes.getValue("id"));
     130                        inRelation = true;
     131                        inWay = false;
     132                        inNode = false;
     133                } else if (elementName.equalsIgnoreCase("nd")) {
     134                        wayTmp.addNodeReference(attributes.getValue("ref"));
     135
     136                } else if (elementName.equalsIgnoreCase("tag")) {
     137
     138                        if (inNode) {
     139                                //if the path is in an OSMNode set tagKey and value to the corresponding node
     140                                nodeTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     141                        } else if (inWay) {
     142                                //else if the path is in an OSM way set tagKey and value to the corresponding way
     143                                wayTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     144                        } else if (inRelation) {
     145                                //set the key-value pairs of relation tags
     146                                relationTmp.setTagKeyValue(attributes.getValue("k"), attributes.getValue("v"));
     147                        }
     148                } else if (elementName.equalsIgnoreCase("member")) {
     149                        relationTmp.addMemberReference(attributes.getValue("ref"));
     150                }
     151        }
     152
     153        @Override
     154        public void endElement(String s, String s1, String element) throws SAXException {
     155                // if end of node element, add to appropriate list
     156                if (element.equalsIgnoreCase("node")) {
     157                        nodeList.add(nodeTmp);
     158                        nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
     159                }
     160
     161                if (element.equalsIgnoreCase("way")) {
     162
     163                        //construct the Way geometry from each node of the node references
     164                        List<String> references = wayTmp.getNodeReferences();
     165
     166                        for (String entry: references) {
     167                                Geometry geometry = nodesWithIDs.get(entry).getGeometry(); //get the geometry of the node with ID=entry
     168                                wayTmp.addNodeGeometry(geometry); //add the node geometry in this way
     169
     170                        }
     171                        Geometry geom = geometryFactory.buildGeometry(wayTmp.getNodeGeometries());
     172
     173                        if ((wayTmp.getNumberOfNodes() > 3) &&
     174                                        wayTmp.getNodeGeometries().get(0).equals(wayTmp.getNodeGeometries()
     175                                                        .get(wayTmp.getNodeGeometries().size()-1))) {
     176                                //checks if the beginning and ending node are the same and the number of nodes are more than 3.
     177                                //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
     178
     179                                if (!((wayTmp.getTagKeyValue().containsKey("barrier")) || wayTmp.getTagKeyValue().containsKey("highway"))) {
     180                                        //this is not a barrier nor a road, so construct a polygon geometry
     181
     182                                        LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
     183                                        Polygon poly = new Polygon(linear, null, geometryFactory);
     184                                        wayTmp.setGeometry(poly);
     185                                } else {
     186                                        //it is either a barrier or a road, so construct a linear ring geometry
     187                                        LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
     188                                        wayTmp.setGeometry(linear);
     189                                }
     190                        } else if (wayTmp.getNumberOfNodes() > 1) {
     191                                //it is an open geometry with more than one nodes, make it linestring
     192
     193                                LineString lineString = geometryFactory.createLineString(geom.getCoordinates());
     194                                wayTmp.setGeometry(lineString);
     195                        } else { //we assume all the rest geometries are points
     196                                //some ways happen to have only one point. Construct a  Point.
     197                                Point point = geometryFactory.createPoint(geom.getCoordinate());
     198                                wayTmp.setGeometry(point);
     199                        }
     200                        wayList.add(wayTmp);
     201                }
     202
     203                if (element.equalsIgnoreCase("relation")) {
     204                        relationList.add(relationTmp);
     205                }
     206        }
     207
     208        public List<OSMNode> getNodeList() {
     209                return nodeList;
     210        }
     211
     212        public List<OSMWay> getWayList() {
     213                return wayList;
     214        }
     215
     216        public List<OSMRelation> getRelationList() {
     217                return relationList;
     218        }
     219
     220        public Map<String, OSMNode> getNodesWithIDs() {
     221                return nodesWithIDs;
     222        }
    223223}
  • applications/editors/josm/plugins/OSMRecPlugin/src/org/openstreetmap/josm/plugins/osmrec/personalization/HistoryParser.java

    r32404 r33525  
    2424import org.opengis.referencing.operation.MathTransform;
    2525import org.opengis.referencing.operation.TransformException;
    26 import org.openstreetmap.josm.Main;
    2726import org.openstreetmap.josm.io.OsmApi;
    2827import org.openstreetmap.josm.plugins.osmrec.container.OSMNode;
    2928import org.openstreetmap.josm.plugins.osmrec.container.OSMWay;
    3029import org.openstreetmap.josm.tools.HttpClient;
     30import org.openstreetmap.josm.tools.Logging;
    3131import org.openstreetmap.josm.tools.Utils;
    3232import org.w3c.dom.Node;
     
    4848 */
    4949public class HistoryParser {
    50     private static final String OSM_API = OsmApi.getOsmApi().getBaseUrl();
    51     private static final CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
    52     private static final CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
    53     private static final GeometryFactory geometryFactory = new GeometryFactory();
    54     private MathTransform transform;
    55     private OSMNode nodeTmp;
    56 
    57     private final List<OSMNode> nodeList;
    58     private final Map<String, OSMNode> nodesWithIDs;
    59     private final List<OSMWay> wayList;
    60     private OSMWay wayTmp;
    61     private final String username;
    62 
    63     /**
    64     * Constructs a new {@code HistoryParser}.
    65     * @param username user name
    66     */
    67     public HistoryParser(String username) {
    68         this.username = username;
    69         transform = null;
    70         try {
    71             transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
    72         } catch (FactoryException ex) {
    73             Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    74         }
    75         nodeList = new ArrayList<>();
    76         nodesWithIDs = new HashMap<>();
    77         wayList = new ArrayList<>();
    78     }
    79 
    80     public void historyParse(String timeInterval) {
    81 
    82         HashSet<String> changesetIDsList = new HashSet<>();
    83 
    84         try {
    85             String osmUrl = OSM_API + "changesets?display_name=" + username + "&time=" + timeInterval;
    86             InputStream xml = HttpClient.create(new URL(osmUrl)).connect().getContent();
    87             NodeList nodes = Utils.parseSafeDOM(xml).getElementsByTagName("changeset");
    88 
    89             Main.debug("changeset size "+ nodes.getLength());
    90             for (int i = 0; i < nodes.getLength(); i++) {
    91                 Main.debug("attributes of " + i + "th changeset");
    92                 String id = nodes.item(i).getAttributes().item(3).toString();
    93                 Main.debug("id:" + nodes.item(i).getAttributes().item(3));
    94                 id = stripQuotes(id);
    95                 changesetIDsList.add(id);
    96             }
    97 
    98             for (String id : changesetIDsList) {
    99                 getChangesetByID(id);
    100             }
    101         } catch (IOException | ParserConfigurationException | SAXException ex) {
    102             Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    103         }
    104     }
    105 
    106     private void getChangesetByID(String id) {
    107         try {
    108             String changesetByIDURL = OSM_API+ "changeset/" + id + "/download";
    109             InputStream xml = HttpClient.create(new URL(changesetByIDURL)).connect().getContent();
    110             Node osmChange = Utils.parseSafeDOM(xml).getFirstChild();
    111 
    112             //get all nodes first, in order to be able to call all nodes references and create the geometries
    113             for (int i = 0; i < osmChange.getChildNodes().getLength(); i++) {
    114                 String changeType = osmChange.getChildNodes().item(i).getNodeName();
    115                 if (!(changeType.equals("#text") || changeType.equals("delete"))) {
    116 
    117                     NodeList changeChilds = osmChange.getChildNodes().item(i).getChildNodes();
    118 
    119                     Node osmObject = changeChilds.item(1);
    120 
    121                     if (osmObject.getNodeName().equals("node")) {
    122                         //node data
    123                         nodeTmp = new OSMNode();
    124                         nodeTmp.setID(osmObject.getAttributes().getNamedItem("id").getNodeValue());
    125 
    126                         //parse geometry
    127                         double longitude = Double.parseDouble(osmObject.getAttributes().getNamedItem("lon").getNodeValue());
    128                         double latitude = Double.parseDouble(osmObject.getAttributes().getNamedItem("lat").getNodeValue());
    129                         Coordinate targetGeometry = null;
    130                         Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
    131                         try {
    132                             targetGeometry = JTS.transform(sourceCoordinate, null, transform);
    133                         } catch (MismatchedDimensionException | TransformException ex) {
    134                             Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    135                         }
    136 
    137                         //create geometry object
    138                         Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
    139                         nodeTmp.setGeometry(geom);
    140 
    141                         nodeList.add(nodeTmp);
    142                         nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
    143                     }
    144                 }
    145             }
    146 
    147             for (int i = 0; i < osmChange.getChildNodes().getLength(); i++) {
    148                 String changeType = osmChange.getChildNodes().item(i).getNodeName();
    149                 if (!(changeType.equals("#text") || changeType.equals("delete"))) {
    150                     NodeList changeChilds = osmChange.getChildNodes().item(i).getChildNodes();
    151 
    152                     Node osmObject = changeChilds.item(1);
    153                     if (osmObject.getNodeName().equals("way")) {
    154 
    155                         //get way data
    156                         wayTmp = new OSMWay();
    157                         wayTmp.setID(osmObject.getAttributes().getNamedItem("id").getNodeValue());
    158                         // extract tags, then set tags to osm object
    159                         Main.debug("\n\nWAY: " + wayTmp.getID());
    160                         for (int l = 0; l < osmObject.getChildNodes().getLength(); l++) {
    161                             String wayChild = osmObject.getChildNodes().item(l).getNodeName();
    162 
    163                             if (wayChild.equals("tag")) {
    164                                 String key = osmObject.getChildNodes().item(l).getAttributes().getNamedItem("k").getNodeValue();
    165                                 String value = osmObject.getChildNodes().item(l).getAttributes().getNamedItem("v").getNodeValue();
    166                                 System.out.println("key: " + key + " value: " + value);
    167                                 wayTmp.setTagKeyValue(key, value);
    168                             } else if (wayChild.equals("nd")) {
    169                                 wayTmp.addNodeReference(osmObject.getChildNodes().item(l).getAttributes().getNamedItem("ref").getNodeValue());
    170                             }
    171                         }
    172 
    173                         //construct the Way geometry from each node of the node references
    174                         List<String> references = wayTmp.getNodeReferences();
    175 
    176                         for (String entry: references) {
    177                             if (nodesWithIDs.containsKey(entry)) {
    178                                 Geometry geometry = nodesWithIDs.get(entry).getGeometry(); //get the geometry of the node with ID=entry
    179                                 wayTmp.addNodeGeometry(geometry); //add the node geometry in this way
    180                             } else {
    181                                 Main.debug("nodes with ids, no entry " + entry);
    182                                 getNodeFromAPI(entry);
    183                             }
    184                         }
    185 
    186                         Geometry geom = geometryFactory.buildGeometry(wayTmp.getNodeGeometries());
    187                         if ((wayTmp.getNodeGeometries().size() > 3) &&
    188                                 wayTmp.getNodeGeometries().get(0).equals(wayTmp.getNodeGeometries()
    189                                         .get(wayTmp.getNodeGeometries().size()-1))) {
    190                             //checks if the beginning and ending node are the same and the number of nodes are more than 3.
    191                             //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
    192 
    193                             if (!((wayTmp.getTagKeyValue().containsKey("barrier")) || wayTmp.getTagKeyValue().containsKey("highway"))) {
    194                                 //this is not a barrier nor a road, so construct a polygon geometry
    195 
    196                                 LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
    197                                 Polygon poly = new Polygon(linear, null, geometryFactory);
    198                                 wayTmp.setGeometry(poly);
    199                             } else {
    200                                 //it is either a barrier or a road, so construct a linear ring geometry
    201                                 LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
    202                                 wayTmp.setGeometry(linear);
    203                             }
    204                         } else if (wayTmp.getNodeGeometries().size() > 1) {
    205                             //it is an open geometry with more than one nodes, make it linestring
    206 
    207                             LineString lineString = geometryFactory.createLineString(geom.getCoordinates());
    208                             wayTmp.setGeometry(lineString);
    209                         } else { //we assume all the rest geometries are points
    210                             //some ways happen to have only one point. Construct a  Point.
    211                             Point point = geometryFactory.createPoint(geom.getCoordinate());
    212                             wayTmp.setGeometry(point);
    213                         }
    214                         wayList.add(wayTmp);
    215                     }
    216                 }
    217             }
    218         } catch (IOException | ParserConfigurationException | SAXException ex) {
    219             Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    220         }
    221     }
    222 
    223     private String stripQuotes(String id) {
    224         return id.substring(4, id.length()-1);
    225     }
    226 
    227     private void getNodeFromAPI(String nodeID) {
    228         try {
    229             String osmUrl = OSM_API + "node/" + nodeID;
    230             InputStream xml = HttpClient.create(new URL(osmUrl)).connect().getContent();
    231             NodeList nodes = Utils.parseSafeDOM(xml).getElementsByTagName("node");
    232             String lat = nodes.item(0).getAttributes().getNamedItem("lat").getNodeValue();
    233             String lon = nodes.item(0).getAttributes().getNamedItem("lon").getNodeValue();
    234 
    235             nodeTmp = new OSMNode();
    236             nodeTmp.setID(nodeID);
    237 
    238             //parse geometry
    239             double longitude = Double.parseDouble(lon);
    240             double latitude = Double.parseDouble(lat);
    241             Coordinate targetGeometry = null;
    242             Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
    243             try {
    244                 targetGeometry = JTS.transform(sourceCoordinate, null, transform);
    245             } catch (MismatchedDimensionException | TransformException ex) {
    246                 Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    247             }
    248 
    249             //create geometry object
    250             Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
    251             nodeTmp.setGeometry(geom);
    252 
    253             nodeList.add(nodeTmp);
    254             nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
    255 
    256         } catch (IOException | ParserConfigurationException | SAXException ex) {
    257             Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
    258         }
    259     }
    260 
    261     public List<OSMWay> getWayList() {
    262         return wayList;
    263     }
     50        private static final String OSM_API = OsmApi.getOsmApi().getBaseUrl();
     51        private static final CoordinateReferenceSystem sourceCRS = DefaultGeographicCRS.WGS84;
     52        private static final CoordinateReferenceSystem targetCRS = DefaultGeocentricCRS.CARTESIAN;
     53        private static final GeometryFactory geometryFactory = new GeometryFactory();
     54        private MathTransform transform;
     55        private OSMNode nodeTmp;
     56
     57        private final List<OSMNode> nodeList;
     58        private final Map<String, OSMNode> nodesWithIDs;
     59        private final List<OSMWay> wayList;
     60        private OSMWay wayTmp;
     61        private final String username;
     62
     63        /**
     64        * Constructs a new {@code HistoryParser}.
     65        * @param username user name
     66        */
     67        public HistoryParser(String username) {
     68                this.username = username;
     69                transform = null;
     70                try {
     71                        transform = CRS.findMathTransform(sourceCRS, targetCRS, true);
     72                } catch (FactoryException ex) {
     73                        Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     74                }
     75                nodeList = new ArrayList<>();
     76                nodesWithIDs = new HashMap<>();
     77                wayList = new ArrayList<>();
     78        }
     79
     80        public void historyParse(String timeInterval) {
     81
     82                HashSet<String> changesetIDsList = new HashSet<>();
     83
     84                try {
     85                        String osmUrl = OSM_API + "changesets?display_name=" + username + "&time=" + timeInterval;
     86                        InputStream xml = HttpClient.create(new URL(osmUrl)).connect().getContent();
     87                        NodeList nodes = Utils.parseSafeDOM(xml).getElementsByTagName("changeset");
     88
     89                        Logging.debug("changeset size "+ nodes.getLength());
     90                        for (int i = 0; i < nodes.getLength(); i++) {
     91                                Logging.debug("attributes of " + i + "th changeset");
     92                                String id = nodes.item(i).getAttributes().item(3).toString();
     93                                Logging.debug("id:" + nodes.item(i).getAttributes().item(3));
     94                                id = stripQuotes(id);
     95                                changesetIDsList.add(id);
     96                        }
     97
     98                        for (String id : changesetIDsList) {
     99                                getChangesetByID(id);
     100                        }
     101                } catch (IOException | ParserConfigurationException | SAXException ex) {
     102                        Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     103                }
     104        }
     105
     106        private void getChangesetByID(String id) {
     107                try {
     108                        String changesetByIDURL = OSM_API+ "changeset/" + id + "/download";
     109                        InputStream xml = HttpClient.create(new URL(changesetByIDURL)).connect().getContent();
     110                        Node osmChange = Utils.parseSafeDOM(xml).getFirstChild();
     111
     112                        //get all nodes first, in order to be able to call all nodes references and create the geometries
     113                        for (int i = 0; i < osmChange.getChildNodes().getLength(); i++) {
     114                                String changeType = osmChange.getChildNodes().item(i).getNodeName();
     115                                if (!(changeType.equals("#text") || changeType.equals("delete"))) {
     116
     117                                        NodeList changeChilds = osmChange.getChildNodes().item(i).getChildNodes();
     118
     119                                        Node osmObject = changeChilds.item(1);
     120
     121                                        if (osmObject.getNodeName().equals("node")) {
     122                                                //node data
     123                                                nodeTmp = new OSMNode();
     124                                                nodeTmp.setID(osmObject.getAttributes().getNamedItem("id").getNodeValue());
     125
     126                                                //parse geometry
     127                                                double longitude = Double.parseDouble(osmObject.getAttributes().getNamedItem("lon").getNodeValue());
     128                                                double latitude = Double.parseDouble(osmObject.getAttributes().getNamedItem("lat").getNodeValue());
     129                                                Coordinate targetGeometry = null;
     130                                                Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
     131                                                try {
     132                                                        targetGeometry = JTS.transform(sourceCoordinate, null, transform);
     133                                                } catch (MismatchedDimensionException | TransformException ex) {
     134                                                        Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     135                                                }
     136
     137                                                //create geometry object
     138                                                Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
     139                                                nodeTmp.setGeometry(geom);
     140
     141                                                nodeList.add(nodeTmp);
     142                                                nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
     143                                        }
     144                                }
     145                        }
     146
     147                        for (int i = 0; i < osmChange.getChildNodes().getLength(); i++) {
     148                                String changeType = osmChange.getChildNodes().item(i).getNodeName();
     149                                if (!(changeType.equals("#text") || changeType.equals("delete"))) {
     150                                        NodeList changeChilds = osmChange.getChildNodes().item(i).getChildNodes();
     151
     152                                        Node osmObject = changeChilds.item(1);
     153                                        if (osmObject.getNodeName().equals("way")) {
     154
     155                                                //get way data
     156                                                wayTmp = new OSMWay();
     157                                                wayTmp.setID(osmObject.getAttributes().getNamedItem("id").getNodeValue());
     158                                                // extract tags, then set tags to osm object
     159                                                Logging.debug("\n\nWAY: " + wayTmp.getID());
     160                                                for (int l = 0; l < osmObject.getChildNodes().getLength(); l++) {
     161                                                        String wayChild = osmObject.getChildNodes().item(l).getNodeName();
     162
     163                                                        if (wayChild.equals("tag")) {
     164                                                                String key = osmObject.getChildNodes().item(l).getAttributes().getNamedItem("k").getNodeValue();
     165                                                                String value = osmObject.getChildNodes().item(l).getAttributes().getNamedItem("v").getNodeValue();
     166                                                                System.out.println("key: " + key + " value: " + value);
     167                                                                wayTmp.setTagKeyValue(key, value);
     168                                                        } else if (wayChild.equals("nd")) {
     169                                                                wayTmp.addNodeReference(osmObject.getChildNodes().item(l).getAttributes().getNamedItem("ref").getNodeValue());
     170                                                        }
     171                                                }
     172
     173                                                //construct the Way geometry from each node of the node references
     174                                                List<String> references = wayTmp.getNodeReferences();
     175
     176                                                for (String entry: references) {
     177                                                        if (nodesWithIDs.containsKey(entry)) {
     178                                                                Geometry geometry = nodesWithIDs.get(entry).getGeometry(); //get the geometry of the node with ID=entry
     179                                                                wayTmp.addNodeGeometry(geometry); //add the node geometry in this way
     180                                                        } else {
     181                                                                Logging.debug("nodes with ids, no entry " + entry);
     182                                                                getNodeFromAPI(entry);
     183                                                        }
     184                                                }
     185
     186                                                Geometry geom = geometryFactory.buildGeometry(wayTmp.getNodeGeometries());
     187                                                if ((wayTmp.getNodeGeometries().size() > 3) &&
     188                                                                wayTmp.getNodeGeometries().get(0).equals(wayTmp.getNodeGeometries()
     189                                                                                .get(wayTmp.getNodeGeometries().size()-1))) {
     190                                                        //checks if the beginning and ending node are the same and the number of nodes are more than 3.
     191                                                        //the nodes must be more than 3, because jts does not allow a construction of a linear ring with less points.
     192
     193                                                        if (!((wayTmp.getTagKeyValue().containsKey("barrier")) || wayTmp.getTagKeyValue().containsKey("highway"))) {
     194                                                                //this is not a barrier nor a road, so construct a polygon geometry
     195
     196                                                                LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
     197                                                                Polygon poly = new Polygon(linear, null, geometryFactory);
     198                                                                wayTmp.setGeometry(poly);
     199                                                        } else {
     200                                                                //it is either a barrier or a road, so construct a linear ring geometry
     201                                                                LinearRing linear = geometryFactory.createLinearRing(geom.getCoordinates());
     202                                                                wayTmp.setGeometry(linear);
     203                                                        }
     204                                                } else if (wayTmp.getNodeGeometries().size() > 1) {
     205                                                        //it is an open geometry with more than one nodes, make it linestring
     206
     207                                                        LineString lineString = geometryFactory.createLineString(geom.getCoordinates());
     208                                                        wayTmp.setGeometry(lineString);
     209                                                } else { //we assume all the rest geometries are points
     210                                                        //some ways happen to have only one point. Construct a  Point.
     211                                                        Point point = geometryFactory.createPoint(geom.getCoordinate());
     212                                                        wayTmp.setGeometry(point);
     213                                                }
     214                                                wayList.add(wayTmp);
     215                                        }
     216                                }
     217                        }
     218                } catch (IOException | ParserConfigurationException | SAXException ex) {
     219                        Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     220                }
     221        }
     222
     223        private String stripQuotes(String id) {
     224                return id.substring(4, id.length()-1);
     225        }
     226
     227        private void getNodeFromAPI(String nodeID) {
     228                try {
     229                        String osmUrl = OSM_API + "node/" + nodeID;
     230                        InputStream xml = HttpClient.create(new URL(osmUrl)).connect().getContent();
     231                        NodeList nodes = Utils.parseSafeDOM(xml).getElementsByTagName("node");
     232                        String lat = nodes.item(0).getAttributes().getNamedItem("lat").getNodeValue();
     233                        String lon = nodes.item(0).getAttributes().getNamedItem("lon").getNodeValue();
     234
     235                        nodeTmp = new OSMNode();
     236                        nodeTmp.setID(nodeID);
     237
     238                        //parse geometry
     239                        double longitude = Double.parseDouble(lon);
     240                        double latitude = Double.parseDouble(lat);
     241                        Coordinate targetGeometry = null;
     242                        Coordinate sourceCoordinate = new Coordinate(longitude, latitude);
     243                        try {
     244                                targetGeometry = JTS.transform(sourceCoordinate, null, transform);
     245                        } catch (MismatchedDimensionException | TransformException ex) {
     246                                Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     247                        }
     248
     249                        //create geometry object
     250                        Geometry geom = geometryFactory.createPoint(new Coordinate(targetGeometry));
     251                        nodeTmp.setGeometry(geom);
     252
     253                        nodeList.add(nodeTmp);
     254                        nodesWithIDs.put(nodeTmp.getID(), nodeTmp);
     255
     256                } catch (IOException | ParserConfigurationException | SAXException ex) {
     257                        Logger.getLogger(HistoryParser.class.getName()).log(Level.SEVERE, null, ex);
     258                }
     259        }
     260
     261        public List<OSMWay> getWayList() {
     262                return wayList;
     263        }
    264264}
Note: See TracChangeset for help on using the changeset viewer.