Development Guidelines

Table of content

  1. How your code should look like
  2. How your formatting should look like
  3. How your javadoc should look like
  4. Internationalization

How your code should look like

  • make sure the code is Java 8 compatible
  • Document your code using inline comments and javadoc. Many people will thank you :)
  • Try to avoid public fields
  • JOSM has a lot of helper methods in the Utils, GuiUtils, Geometry ... classes. Use them if you need
  • Check parameters. You can use Objects.requireNonNull.
  • Don't write for performance - write for readability. Use Streams, Functions and other Java 8 features if they make the code more readable.

Threading / Locking

  • JOSM uses various locking mechanisms, depending on the object.
  • The data sets are protected by a RW lock. Some methods do not automatically lock for performance reasons. Make sure to acquire the locks required for your changes.
  • GUI components should only be modified in the EDT thread
  • Prefer to use SwingUtils.invokeLater if you need to run anything on the UI thread
  • Many listeners already run in the EDT thread (layer changes) or have a central manager that allows you to register listeners that run in EDT (dataset changes, selection changes).

How your formatting should look like

  • make sure there is no trailing white space
  • don't use multiple consecutive empty lines
  • JOSM uses 4 characters indentation and no tab stops. If you use Notepad++ you can change the default indentation in the "Preferences" -> "Language" -> "Tab Settings" -> check "Replace by spaces" (this is permanent) or with the "change indentation settings" button in the toolbar (this is a temopary setting and requires the plugin "Customize Toolbar").
  • add curly brackets for each if, unless it is followed by return (or maybe throw)
  • You should use checkstyle before patch/commit: ant checkstyle and check checkstyle-josm.xml; if you find running checkstyle slow for all files, run for changed files only:
      # make sure build2 dir exists, if it does not run 'ant checkstyle-compile' before
      svn diff --summarize | awk '{ print $2 }' | grep "^[a-z]" | xargs \
        java -classpath "build2:tools/checkstyle/checkstyle-all.jar" \
 -c tools/checkstyle/josm_checks.xml
      # or
      git diff --name-only | xargs \
        java -classpath "build2:tools/checkstyle/checkstyle-all.jar" \
 -c tools/checkstyle/josm_checks.xml

How your javadoc should look like

  • The Oracle Javadoc style guide is used as the base guide
  • @since is used for public classes and methods (visible to plugin developers) with the JOSM revision that introduced the element. Example: @since 5408
    • @since is updated / added when a public method signature changes or if a class is renamed.
    • @since can be omitted for public methods and fields introduced at the same time as the class, provided they do not have changed and the class is correctly documented.
    • There can be multiple @since tags, e.g. for adding interfaces to a class. The reason for those tags should be added Example: @since 12345 @FunctionalIterface was added
    • If you submit a patch and don't know the revision, add @since xxx any way. It can then be replaced when merging your patch.
  • @throws is preferred to @exception
  • check your changes before patch/commit by generating javadoc: ant javadoc, browse output messages; if you find running javadoc slow for all files, run for changed files only:
    svn diff --summarize | awk '{ print $2 }' | xargs javadoc -d javadoc
    # or
    git diff --name-only | xargs javadoc -d javadoc

Configuring Eclipse


  • make sure you use tr(...) for all localized strings
    import import static;
    // use tr(...) for exception messages
    throw new Exception(tr("error message always in tr()"));
    // use tr(...) for labels, title, tooltip texts and the like
    new JLabel(tr("Label always in tr()"));
    // etc.
  • never assemble localized messages with +. Use format placeholders instead.

DONT new JLabel(tr("My Label " + labelId));

DO new JLabel(tr("My Label {0}",labelId));

Only exception: + can be used to break long lines of non-variable texts. The placeholders are mandatory in simple translations.

  • When using apostrophe in the source string, it needs to be escaped by another apostrophe (Like backslash in C):
    new JButton(tr("Don''t press me!"))
  • A translation context can be set with trc(...). Additional hints to translators are given by java comments at the function:
    /* I18n: house number, street as parameter; place number first for visibility */
    msg = tr("House number {0} at {1}", s, t);
  • Use trn(...) to let translators choose the language specific plural:
    msg = trn("Object deleted", "Objects deleted", del.size();
    // or with placeholders:
    new JButton(trn(/* I18n: times needed, some name as parameter */ 
                        "Press {1} {0} times!", n, n, someName))
    // The English singular source string must be given for identification 
    // even when its logically invalid and won't occur. For consistency 
    // the number placeholder should be set in it.
    msg = trn("Combine {0} way", "Combine {0} ways", n, n);

In plural segments no placeholder is mandatory for translators.

Back to Developers Guide

Last modified 14 months ago Last modified on 2022-08-12T16:48:46+02:00

Attachments (4)

Download all attachments as: .zip