示例#1
0
 /**
  * Copies the tags of object to the clipboard. The output by this function looks similar to:
  * key=value\nkey=value
  *
  * @param source The OSM data layer source
  * @param primitives The OSM primitives to copy
  */
 public static void copy(OsmDataLayer source, Collection<OsmPrimitive> primitives) {
   Set<String> values = new TreeSet<>();
   for (OsmPrimitive p : primitives) {
     for (Entry<String, String> kv : p.getKeys().entrySet()) {
       values.add(new Tag(kv.getKey(), kv.getValue()).toString());
     }
   }
   if (!values.isEmpty()) Utils.copyToClipboard(Utils.join("\n", values));
 }
示例#2
0
  public String formatAsHtmlUnorderedList(Collection<? extends OsmPrimitive> primitives) {
    return Utils.joinAsHtmlUnorderedList(
        Utils.transform(
            primitives,
            new Function<OsmPrimitive, String>() {

              @Override
              public String apply(OsmPrimitive x) {
                return x.getDisplayName(DefaultNameFormatter.this);
              }
            }));
  }
  /**
   * Inform a non-expert user about what tag conflict resolution means.
   *
   * @param primitives The primitives to be combined
   * @param normalizedTags The normalized tag collection of the primitives to be combined
   * @throws UserCancelException If the user cancels the dialog.
   */
  protected static void informAboutTagConflicts(
      final Collection<? extends OsmPrimitive> primitives, final TagCollection normalizedTags)
      throws UserCancelException {
    String conflicts =
        Utils.joinAsHtmlUnorderedList(
            Utils.transform(
                normalizedTags.getKeysWithMultipleValues(),
                new Function<String, String>() {
                  @Override
                  public String apply(String key) {
                    return tr(
                        "{0} ({1})",
                        key,
                        Utils.join(
                            tr(", "),
                            Utils.transform(
                                normalizedTags.getValues(key),
                                new Function<String, String>() {
                                  @Override
                                  public String apply(String x) {
                                    return x == null || x.isEmpty() ? tr("<i>missing</i>") : x;
                                  }
                                })));
                  }
                }));
    String msg = /* for correct i18n of plural forms - see #9110 */
        trn(
            "You are about to combine {0} objects, "
                + "but the following tags are used conflictingly:<br/>{1}"
                + "If these objects are combined, the resulting object may have unwanted tags.<br/>"
                + "If you want to continue, you are shown a dialog to fix the conflicting tags.<br/><br/>"
                + "Do you want to continue?",
            "You are about to combine {0} objects, "
                + "but the following tags are used conflictingly:<br/>{1}"
                + "If these objects are combined, the resulting object may have unwanted tags.<br/>"
                + "If you want to continue, you are shown a dialog to fix the conflicting tags.<br/><br/>"
                + "Do you want to continue?",
            primitives.size(),
            primitives.size(),
            conflicts);

    if (!ConditionalOptionPaneUtil.showConfirmationDialog(
        "combine_tags",
        Main.parent,
        "<html>" + msg + "</html>",
        tr("Combine confirmation"),
        JOptionPane.YES_NO_OPTION,
        JOptionPane.QUESTION_MESSAGE,
        JOptionPane.YES_OPTION)) {
      throw new UserCancelException();
    }
  }
 @Override
 protected String buildRequestString(final OsmPrimitiveType type, Set<Long> idPackage) {
   final Utils.Function<Long, Object> toOverpassExpression =
       new Utils.Function<Long, Object>() {
         @Override
         public Object apply(Long x) {
           return type.getAPIName() + "(" + x + ");>;";
         }
       };
   final String query =
       "(" + Utils.join("", Utils.transform(idPackage, toOverpassExpression)) + ");out meta;";
   return "interpreter?data=" + Utils.encodeUrl(query);
 }
示例#5
0
  /**
   * Adjusts the upload order for new relations. Child relations are uploaded first, parent
   * relations second.
   *
   * <p>This method detects cyclic dependencies in new relation. Relations with cyclic dependencies
   * can't be uploaded.
   *
   * @throws CyclicUploadDependencyException thrown, if a cyclic dependency is detected
   */
  public void adjustRelationUploadOrder() throws CyclicUploadDependencyException {
    LinkedList<OsmPrimitive> newToAdd = new LinkedList<OsmPrimitive>();
    newToAdd.addAll(Utils.filteredCollection(toAdd, Node.class));
    newToAdd.addAll(Utils.filteredCollection(toAdd, Way.class));

    List<Relation> relationsToAdd =
        new ArrayList<Relation>(Utils.filteredCollection(toAdd, Relation.class));
    List<Relation> noProblemRelations = filterRelationsNotReferringToNewRelations(relationsToAdd);
    newToAdd.addAll(noProblemRelations);
    relationsToAdd.removeAll(noProblemRelations);

    RelationUploadDependencyGraph graph = new RelationUploadDependencyGraph(relationsToAdd);
    newToAdd.addAll(graph.computeUploadOrder());
    toAdd = newToAdd;
  }
示例#6
0
 /**
  * Constructs a new {@code QuadStateCheckBox}.
  *
  * @param text the text of the check box
  * @param icon the Icon image to display
  * @param initial The initial state
  * @param allowed The allowed states
  */
 public QuadStateCheckBox(String text, Icon icon, State initial, State[] allowed) {
   super(text, icon);
   this.allowed = Utils.copyArray(allowed);
   // Add a listener for when the mouse is pressed
   super.addMouseListener(
       new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
           grabFocus();
           model.nextState();
         }
       });
   // Reset the keyboard action map
   ActionMap map = new ActionMapUIResource();
   map.put(
       "pressed",
       new AbstractAction() {
         @Override
         public void actionPerformed(ActionEvent e) {
           grabFocus();
           model.nextState();
         }
       });
   map.put("released", null);
   SwingUtilities.replaceUIActionMap(this, map);
   // set the model to the adapted model
   model = new QuadStateDecorator(getModel());
   setModel(model);
   setState(initial);
 }
示例#7
0
    @Override
    protected void realRun() throws SAXException, IOException, OsmTransferException {
      String urlString = useserver.url + java.net.URLEncoder.encode(searchExpression, "UTF-8");

      try {
        getProgressMonitor().indeterminateSubTask(tr("Querying name server ..."));
        URL url = new URL(urlString);
        synchronized (this) {
          connection = Utils.openHttpConnection(url);
        }
        connection.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect", 15) * 1000);
        InputStream inputStream = connection.getInputStream();
        InputSource inputSource = new InputSource(new InputStreamReader(inputStream, "UTF-8"));
        NameFinderResultParser parser = new NameFinderResultParser();
        SAXParserFactory.newInstance().newSAXParser().parse(inputSource, parser);
        this.data = parser.getResult();
      } catch (Exception e) {
        if (canceled)
          // ignore exception
          return;
        OsmTransferException ex = new OsmTransferException(e);
        ex.setUrl(urlString);
        lastException = ex;
      }
    }
示例#8
0
 public SaveAndUploadTask(SaveLayersModel model, ProgressMonitor monitor) {
   this.model = model;
   this.monitor = monitor;
   this.worker =
       Executors.newSingleThreadExecutor(
           Utils.newThreadFactory(getClass() + "-%d", Thread.NORM_PRIORITY));
 }
示例#9
0
 @Override
 public String toString() {
   return base
       + (Range.ZERO_TO_INFINITY.equals(range) ? "" : range)
       + Utils.join("", conds)
       + (subpart != null ? "::" + subpart : "");
 }
示例#10
0
 private InputStream createInputStream(File sel) throws IOException {
   if (Utils.hasExtension(sel, "gpx.gz")) {
     return new GZIPInputStream(new FileInputStream(sel));
   } else {
     return new FileInputStream(sel);
   }
 }
 /** @see CredentialsAgent#store */
 @Override
 public void store(RequestorType requestorType, String host, PasswordAuthentication credentials)
     throws CredentialsAgentException {
   if (requestorType == null) return;
   switch (requestorType) {
     case SERVER:
       if (Utils.equal(OsmApi.getOsmApi().getHost(), host)) {
         Main.pref.put("osm-server.username", credentials.getUserName());
         if (credentials.getPassword() == null) {
           Main.pref.put("osm-server.password", null);
         } else {
           Main.pref.put("osm-server.password", String.valueOf(credentials.getPassword()));
         }
       } else if (host != null) {
         Main.pref.put("server.username." + host, credentials.getUserName());
         if (credentials.getPassword() == null) {
           Main.pref.put("server.password." + host, null);
         } else {
           Main.pref.put("server.password." + host, String.valueOf(credentials.getPassword()));
         }
       }
       break;
     case PROXY:
       Main.pref.put(ProxyPreferencesPanel.PROXY_USER, credentials.getUserName());
       if (credentials.getPassword() == null) {
         Main.pref.put(ProxyPreferencesPanel.PROXY_PASS, null);
       } else {
         Main.pref.put(
             ProxyPreferencesPanel.PROXY_PASS, String.valueOf(credentials.getPassword()));
       }
       break;
   }
 }
 /** @see CredentialsAgent#lookup */
 @Override
 public PasswordAuthentication lookup(RequestorType requestorType, String host)
     throws CredentialsAgentException {
   if (requestorType == null) return null;
   String user;
   String password;
   switch (requestorType) {
     case SERVER:
       if (Utils.equal(OsmApi.getOsmApi().getHost(), host)) {
         user = Main.pref.get("osm-server.username", null);
         password = Main.pref.get("osm-server.password", null);
       } else if (host != null) {
         user = Main.pref.get("server.username." + host, null);
         password = Main.pref.get("server.password." + host, null);
       } else {
         user = null;
         password = null;
       }
       if (user == null) return null;
       return new PasswordAuthentication(
           user, password == null ? new char[0] : password.toCharArray());
     case PROXY:
       user = Main.pref.get(ProxyPreferencesPanel.PROXY_USER, null);
       password = Main.pref.get(ProxyPreferencesPanel.PROXY_PASS, null);
       if (user == null) return null;
       return new PasswordAuthentication(
           user, password == null ? new char[0] : password.toCharArray());
   }
   return null;
 }
示例#13
0
 /**
  * Fetches the content of a help topic from the JOSM wiki.
  *
  * @param helpTopicUrl the absolute help topic URL
  * @return the content, filtered and transformed for being displayed in the internal help browser
  * @throws HelpContentReaderException thrown if problem occurs
  * @throws MissingHelpContentException thrown if this helpTopicUrl doesn't point to an existing
  *     Wiki help page
  */
 public String fetchHelpTopicContent(String helpTopicUrl, boolean dotest)
     throws HelpContentReaderException {
   if (helpTopicUrl == null) throw new MissingHelpContentException(helpTopicUrl);
   HttpURLConnection con = null;
   try {
     URL u = new URL(helpTopicUrl);
     con = Utils.openHttpConnection(u);
     con.connect();
     try (BufferedReader in =
         new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))) {
       return prepareHelpContent(in, dotest, u);
     }
   } catch (MalformedURLException e) {
     throw new HelpContentReaderException(e);
   } catch (IOException e) {
     HelpContentReaderException ex = new HelpContentReaderException(e);
     if (con != null) {
       try {
         ex.setResponseCode(con.getResponseCode());
       } catch (IOException e1) {
         // ignore
       }
     }
     throw ex;
   }
 }
示例#14
0
 @Override
 public boolean matches(Environment env) {
   Utils.ensure(
       env.isLinkContext(),
       "Requires LINK context in environment, got ''{0}''",
       env.getContext());
   return super.matches(env);
 }
示例#15
0
 protected final void onLayerSelectionChanged() {
   if (wms.getServiceUrl() != null) {
     wmsUrl.setText(
         wms.buildGetMapUrl(tree.getSelectedLayers(), (String) formats.getSelectedItem()));
     name.setText(
         wms.getServiceUrl().getHost() + ": " + Utils.join(", ", tree.getSelectedLayers()));
   }
   showBounds.setEnabled(tree.getSelectedLayers().size() == 1);
 }
示例#16
0
    @Override
    protected void realRun() throws SAXException, IOException, OsmTransferException {
      String urlString = useserver.url + Utils.encodeUrl(searchExpression);

      try {
        getProgressMonitor().indeterminateSubTask(tr("Querying name server ..."));
        URL url = new URL(urlString);
        synchronized (this) {
          connection = HttpClient.create(url);
          connection.connect();
        }
        try (Reader reader = connection.getResponse().getContentReader()) {
          InputSource inputSource = new InputSource(reader);
          NameFinderResultParser parser = new NameFinderResultParser();
          Utils.parseSafeSAX(inputSource, parser);
          this.data = parser.getResult();
        }
      } catch (SAXParseException e) {
        if (!canceled) {
          // Nominatim sometimes returns garbage, see #5934, #10643
          Main.warn(tr("Error occured with query ''{0}'': ''{1}''", urlString, e.getMessage()));
          GuiHelper.runInEDTAndWait(
              new Runnable() {
                @Override
                public void run() {
                  HelpAwareOptionPane.showOptionDialog(
                      Main.parent,
                      tr("Name server returned invalid data. Please try again."),
                      tr("Bad response"),
                      JOptionPane.WARNING_MESSAGE,
                      null);
                }
              });
        }
      } catch (Exception e) {
        if (!canceled) {
          OsmTransferException ex = new OsmTransferException(e);
          ex.setUrl(urlString);
          lastException = ex;
        }
      }
    }
示例#17
0
文件: Lanes.java 项目: rheinz/josm
 protected void checkNumberOfLanes(final OsmPrimitive p) {
   final String lanes = p.get("lanes");
   final String forward = Utils.firstNonNull(p.get("lanes:forward"), "0");
   final String backward = Utils.firstNonNull(p.get("lanes:backward"), "0");
   try {
     if (Integer.parseInt(lanes) < Integer.parseInt(forward) + Integer.parseInt(backward)) {
       errors.add(
           new TestError(
               this,
               Severity.WARNING,
               tr(
                   "Number of {0} greater than {1}",
                   tr("{0}+{1}", "lanes:forward", "lanes:backward"), "lanes"),
               3101,
               p));
     }
   } catch (NumberFormatException ignore) {
     Main.debug(ignore.getMessage());
   }
 }
示例#18
0
 protected String formatErrorMessages() {
   StringBuilder sb = new StringBuilder();
   sb.append("<html>");
   if (errorMessages.size() == 1) {
     sb.append(errorMessages.iterator().next());
   } else {
     sb.append(Utils.joinAsHtmlUnorderedList(errorMessages));
   }
   sb.append("</html>");
   return sb.toString();
 }
示例#19
0
 @Override
 public List<String> getData() {
   return new ArrayList<>(
       Utils.filter(
           data,
           new Predicate<String>() {
             @Override
             public boolean evaluate(String object) {
               return object != null && !object.isEmpty();
             }
           }));
 }
示例#20
0
 @Override
 public String toString() {
   return "LineElemStyle{"
       + super.toString()
       + "width="
       + line.getLineWidth()
       + " realWidth="
       + realWidth
       + " color="
       + Utils.toString(color)
       + " dashed="
       + Arrays.toString(line.getDashArray())
       + (line.getDashPhase() == 0 ? "" : " dashesOffses=" + line.getDashPhase())
       + " dashedColor="
       + Utils.toString(dashesBackground)
       + " linejoin="
       + linejoinToString(line.getLineJoin())
       + " linecap="
       + linecapToString(line.getEndCap())
       + (offset == 0 ? "" : " offset=" + offset)
       + '}';
 }
示例#21
0
 private static Node parseModel(Reader r) {
   StreamTokenizer st = new StreamTokenizer(r);
   try {
     Split root = new Split();
     parseSplit(st, root);
     return root.getChildren().get(0);
   } catch (Exception e) {
     Main.error(e);
   } finally {
     Utils.close(r);
   }
   return null;
 }
示例#22
0
文件: Lanes.java 项目: rheinz/josm
 protected void checkNumberOfLanesByKey(final OsmPrimitive p, String lanesKey, String message) {
   final Collection<String> keysForPattern =
       Utils.filter(
           p.keySet(), Predicates.stringContainsPattern(Pattern.compile(":" + lanesKey + "$")));
   if (keysForPattern.size() < 1) {
     // nothing to check
     return;
   }
   final Set<Integer> lanesCount =
       new HashSet<Integer>(
           Utils.transform(
               keysForPattern,
               new Utils.Function<String, Integer>() {
                 @Override
                 public Integer apply(String key) {
                   return getLanesCount(p.get(key));
                 }
               }));
   if (lanesCount.size() > 1) {
     // if not all numbers are the same
     errors.add(new TestError(this, Severity.WARNING, message, 3100, p));
   } else if (lanesCount.size() == 1 && p.hasKey(lanesKey)) {
     // ensure that lanes <= *:lanes
     try {
       if (Integer.parseInt(p.get(lanesKey)) > lanesCount.iterator().next()) {
         errors.add(
             new TestError(
                 this,
                 Severity.WARNING,
                 tr("Number of {0} greater than {1}", lanesKey, "*:" + lanesKey),
                 3100,
                 p));
       }
     } catch (NumberFormatException ignore) {
       Main.debug(ignore.getMessage());
     }
   }
 }
示例#23
0
  public void removeCurrentPhotoFromDisk() {
    ImageEntry toDelete;
    if (data != null && !data.isEmpty() && currentPhoto >= 0 && currentPhoto < data.size()) {
      toDelete = data.get(currentPhoto);

      int result =
          new ExtendedDialog(
                  Main.parent,
                  tr("Delete image file from disk"),
                  new String[] {tr("Cancel"), tr("Delete")})
              .setButtonIcons(new String[] {"cancel", "dialogs/delete"})
              .setContent(
                  new JLabel(
                      tr(
                          "<html><h3>Delete the file {0} from disk?<p>The image file will be permanently lost!</h3></html>",
                          toDelete.getFile().getName()),
                      ImageProvider.get("dialogs/geoimage/deletefromdisk"),
                      SwingConstants.LEFT))
              .toggleEnable("geoimage.deleteimagefromdisk")
              .setCancelButton(1)
              .setDefaultButton(2)
              .showDialog()
              .getValue();

      if (result == 2) {
        data.remove(currentPhoto);
        if (currentPhoto >= data.size()) {
          currentPhoto = data.size() - 1;
        }
        if (currentPhoto >= 0) {
          ImageViewerDialog.showImage(this, data.get(currentPhoto));
        } else {
          ImageViewerDialog.showImage(this, null);
        }

        if (Utils.deleteFile(toDelete.getFile())) {
          Main.info("File " + toDelete.getFile() + " deleted. ");
        } else {
          JOptionPane.showMessageDialog(
              Main.parent,
              tr("Image file could not be deleted."),
              tr("Error"),
              JOptionPane.ERROR_MESSAGE);
        }

        updateOffscreenBuffer = true;
        Main.map.repaint();
      }
    }
  }
示例#24
0
 /**
  * Get a string representation of all layers suitable for the {@code source} changeset tag.
  *
  * @return A String of sources separated by ';'
  */
 public String getLayerInformationForSourceTag() {
   final Collection<String> layerInfo = new ArrayList<>();
   if (!getLayersOfType(GpxLayer.class).isEmpty()) {
     // no i18n for international values
     layerInfo.add("survey");
   }
   for (final GeoImageLayer i : getLayersOfType(GeoImageLayer.class)) {
     layerInfo.add(i.getName());
   }
   for (final ImageryLayer i : getLayersOfType(ImageryLayer.class)) {
     layerInfo.add(
         ImageryInfo.ImageryType.BING.equals(i.getInfo().getImageryType()) ? "Bing" : i.getName());
   }
   return Utils.join("; ", layerInfo);
 }
示例#25
0
 /**
  * Alerts the user if an unselected plugin is still required by another plugins
  *
  * @param parent The parent Component used to display error popup
  * @param plugin the plugin
  * @param otherPlugins the other plugins
  */
 private static void alertPluginStillRequired(
     Component parent, String plugin, Set<String> otherPlugins) {
   StringBuilder sb = new StringBuilder();
   sb.append("<html>");
   sb.append(
       trn(
           "Plugin {0} is still required by this plugin:",
           "Plugin {0} is still required by these {1} plugins:",
           otherPlugins.size(),
           plugin,
           otherPlugins.size()));
   sb.append(Utils.joinAsHtmlUnorderedList(otherPlugins));
   sb.append("</html>");
   JOptionPane.showMessageDialog(
       parent, sb.toString(), tr("Warning"), JOptionPane.WARNING_MESSAGE);
 }
示例#26
0
文件: Way.java 项目: codesman/josm
  /**
   * Adds a node to the end of the list of nodes. Ignored, if n is null.
   *
   * @param n the node. Ignored, if null
   * @throws IllegalStateException if this way is marked as incomplete. We can't add a node to an
   *     incomplete way
   * @since 1313
   */
  public void addNode(Node n) {
    if (n == null) return;

    boolean locked = writeLock();
    try {
      if (isIncomplete())
        throw new IllegalStateException(
            tr("Cannot add node {0} to incomplete way {1}.", n.getId(), getId()));
      clearCachedStyle();
      n.addReferrer(this);
      nodes = Utils.addInArrayCopy(nodes, n);
      n.clearCachedStyle();
      fireNodesChanged();
    } finally {
      writeUnlock(locked);
    }
  }
示例#27
0
 /**
  * Builds the style sheet used in the internal help browser
  *
  * @return the style sheet
  */
 protected StyleSheet buildStyleSheet() {
   StyleSheet ss = new StyleSheet();
   BufferedReader reader =
       new BufferedReader(
           new InputStreamReader(getClass().getResourceAsStream("/data/help-browser.css")));
   StringBuffer css = new StringBuffer();
   try {
     String line = null;
     while ((line = reader.readLine()) != null) {
       css.append(line);
       css.append("\n");
     }
   } catch (Exception e) {
     Main.error(
         tr("Failed to read CSS file ''help-browser.css''. Exception is: {0}", e.toString()));
     e.printStackTrace();
     return ss;
   } finally {
     Utils.close(reader);
   }
   ss.addRule(css.toString());
   return ss;
 }
示例#28
0
    public SearchKeywordRow addKeyword(
        String displayText, final String insertText, String description, String... examples) {
      JLabel label =
          new JLabel(
              "<html>"
                  + "<style>td{border:1px solid gray; font-weight:normal;}</style>"
                  + "<table><tr><td>"
                  + displayText
                  + "</td></tr></table></html>");
      add(label);
      if (description != null || examples.length > 0) {
        label.setToolTipText(
            "<html>"
                + description
                + (examples.length > 0
                    ? Utils.joinAsHtmlUnorderedList(Arrays.asList(examples))
                    : "")
                + "</html>");
      }
      if (insertText != null) {
        label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        label.addMouseListener(
            new MouseAdapter() {

              @Override
              public void mouseClicked(MouseEvent e) {
                try {
                  JTextComponent tf = hcb.getEditorComponent();
                  tf.getDocument().insertString(tf.getCaretPosition(), ' ' + insertText, null);
                } catch (BadLocationException ex) {
                  throw new JosmRuntimeException(ex.getMessage(), ex);
                }
              }
            });
      }
      return this;
    }
示例#29
0
 @Override
 public void receiveSearchResult(
     DataSet ds, Collection<OsmPrimitive> result, int foundMatches, SearchSetting setting) {
   ds.setSelected(result);
   if (foundMatches == 0) {
     final String msg;
     final String text = Utils.shortenString(setting.text, MAX_LENGTH_SEARCH_EXPRESSION_DISPLAY);
     if (setting.mode == SearchMode.replace) {
       msg = tr("No match found for ''{0}''", text);
     } else if (setting.mode == SearchMode.add) {
       msg = tr("Nothing added to selection by searching for ''{0}''", text);
     } else if (setting.mode == SearchMode.remove) {
       msg = tr("Nothing removed from selection by searching for ''{0}''", text);
     } else if (setting.mode == SearchMode.in_selection) {
       msg = tr("Nothing found in selection by searching for ''{0}''", text);
     } else {
       msg = null;
     }
     Main.map.statusLine.setHelpText(msg);
     JOptionPane.showMessageDialog(Main.parent, msg, tr("Warning"), JOptionPane.WARNING_MESSAGE);
   } else {
     Main.map.statusLine.setHelpText(tr("Found {0} matches", foundMatches));
   }
 }
示例#30
0
    @Override
    protected void realRun() throws SAXException, IOException, OsmTransferException {
      if (files == null || files.isEmpty()) return;

      /** Find the importer with the chosen file filter */
      FileImporter chosenImporter = null;
      for (FileImporter importer : ExtensionFileFilter.importers) {
        if (fileFilter == importer.filter) {
          chosenImporter = importer;
        }
      }
      /**
       * If the filter hasn't been changed in the dialog, chosenImporter is null now. When the
       * filter has been set explicitly to AllFormatsImporter, treat this the same.
       */
      if (chosenImporter instanceof AllFormatsImporter) {
        chosenImporter = null;
      }
      getProgressMonitor().setTicksCount(files.size());

      if (chosenImporter != null) {
        // The importer was explicitly chosen, so use it.
        List<File> filesNotMatchingWithImporter = new LinkedList<File>();
        List<File> filesMatchingWithImporter = new LinkedList<File>();
        for (final File f : files) {
          if (!chosenImporter.acceptFile(f)) {
            if (f.isDirectory()) {
              SwingUtilities.invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      JOptionPane.showMessageDialog(
                          Main.parent,
                          tr(
                              "<html>Cannot open directory ''{0}''.<br>Please select a file.</html>",
                              f.getAbsolutePath()),
                          tr("Open file"),
                          JOptionPane.ERROR_MESSAGE);
                    }
                  });
              // TODO when changing to Java 6: Don't cancel the
              // task here but use different modality. (Currently 2 dialogs
              // would block each other.)
              return;
            } else {
              filesNotMatchingWithImporter.add(f);
            }
          } else {
            filesMatchingWithImporter.add(f);
          }
        }

        if (!filesNotMatchingWithImporter.isEmpty()) {
          alertFilesNotMatchingWithImporter(filesNotMatchingWithImporter, chosenImporter);
        }
        if (!filesMatchingWithImporter.isEmpty()) {
          importData(chosenImporter, filesMatchingWithImporter);
        }
      } else {
        // find appropriate importer
        MultiMap<FileImporter, File> importerMap = new MultiMap<FileImporter, File>();
        List<File> filesWithUnknownImporter = new LinkedList<File>();
        List<File> urlFiles = new LinkedList<File>();
        FILES:
        for (File f : files) {
          for (FileImporter importer : ExtensionFileFilter.importers) {
            if (importer.acceptFile(f)) {
              importerMap.put(importer, f);
              continue FILES;
            }
          }
          if (urlFileFilter.accept(f)) {
            urlFiles.add(f);
          } else {
            filesWithUnknownImporter.add(f);
          }
        }
        if (!filesWithUnknownImporter.isEmpty()) {
          alertFilesWithUnknownImporter(filesWithUnknownImporter);
        }
        List<FileImporter> importers = new ArrayList<FileImporter>(importerMap.keySet());
        Collections.sort(importers);
        Collections.reverse(importers);

        Set<String> fileHistory = new LinkedHashSet<String>();
        Set<String> failedAll = new HashSet<String>();

        for (FileImporter importer : importers) {
          List<File> files = new ArrayList<File>(importerMap.get(importer));
          importData(importer, files);
          // suppose all files will fail to load
          List<File> failedFiles = new ArrayList<File>(files);

          if (recordHistory && !importer.isBatchImporter()) {
            // remove the files which didn't fail to load from the failed list
            failedFiles.removeAll(successfullyOpenedFiles);
            for (File f : successfullyOpenedFiles) {
              fileHistory.add(f.getCanonicalPath());
            }
            for (File f : failedFiles) {
              failedAll.add(f.getCanonicalPath());
            }
          }
        }

        for (File urlFile : urlFiles) {
          try {
            BufferedReader reader = new BufferedReader(new FileReader(urlFile));
            String line;
            while ((line = reader.readLine()) != null) {
              Matcher m = Pattern.compile(".*(http://.*)").matcher(line);
              if (m.matches()) {
                String url = m.group(1);
                Main.main.menu.openLocation.openUrl(false, url);
              }
            }
            Utils.close(reader);
          } catch (Exception e) {
            Main.error(e);
          }
        }

        if (recordHistory) {
          Collection<String> oldFileHistory = Main.pref.getCollection("file-open.history");
          fileHistory.addAll(oldFileHistory);
          // remove the files which failed to load from the list
          fileHistory.removeAll(failedAll);
          int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
          Main.pref.putCollectionBounded("file-open.history", maxsize, fileHistory);
        }
      }
    }