de·caff Commons

The de·caff Commons provide a wild mix of open source Java classes used in various projects on this site.

Various blog posts here will also refer to these classes.

License

The de·caff Commons (CC for the rest of this page) are licensed under the ISC License, which reads

 Copyright © YEAR-YEAR  Andreas M. Rammelt <rammi@caff.de>

 Permission to use, copy, modify, and/or distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
 copyright notice and this permission notice appear in all copies.

 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

The module support-wmf is an excerpt of the Apache Batik project, which is provided under the Apache 2.0 License.

Requirements

The CC are pure Java, the minimal necessary Java version is 1.7.

Download

The CC come in 5 modules.

Module Jar Src Ant JDoc Purpose
caff-generics jar src ant zip / online Helper classes for functional programming in Java 7
caff-common jar src ant zip / online
(incl. the above)
Various tools, requires caff-generics above
caff-common-swing jar src ant zip / online
(incl. both above)
GUI related classes, requires both above modules.
support-wmf jar src ant zip / online Excerpt from Apache Batik to draw WMF, independent of other modules.
vector-icons Not yet finished support for hi-res icons. included in git access.

Git Access

You can also clone the complete CC git repository from javu.de:

git clone https://javu.de/caff-commons.git

Modules

caff-generics

The caff-generics module (see online javadoc) provides various helper classes for functional programming. With Java 1.8 it is no longer as useful as before, but as my customers are still stuck with 1.7 for various resaons it still has its virtues.

Types class

The main access point is the Types class, which provides dozens of static helper methods. Some examples of what is possible:

    // Types.asList() is a bit more efficient than standard
    // Arrays.asList(), as it avoids copying the whole list
    @NotNull
    public static List<String> asList(String ... texts)
    {
      return Types.asList(texts);
    }

    // The is similar functionality for primitive types,
    // under the name toList()
    @NotNull
    public static List<Integer> asList(int ... values)
    {
      return Types.toList(values);
    }

  /**
     * Get the words contained in a bunch of strings.
     * @param lines lines of file
     * @return words, sorted by natural order (case-insensitive)
     */
    @NotNull
    public static Collection<String> getWords(String[] lines) {
      return Types.mapX(new TreeSet<>(String.CASE_INSENSITIVE_ORDER), lines, Types.WORD_SPLIT);
    }

   /**
    * Show a word statistics.
    * @param lines lines of file
    */
   @NotNull
   public static CountingTreeSet<String> getWordStats(String[] lines) {
     return Types.mapX(new CountingTreeSet<>(String.CASE_INSENSITIVE_ORDER), lines, Types.WORD_SPLIT);
   }

   // apply a list of integers into their string representation:
    public static List<String> intToString(List<Integer> intList) {
      return Types.map(intList, Types.TO_STRING);
    }

    // apply a list of strings into integers, throwing an exception on problems:
    @NotNull
    public static List<Integer> stringToInt1(@NotNull List<String> strList) throws TypeConverterException {
      return Types.map(strList, Types.STR_TO_INT);
    }

    // apply a list of strings into integers, discarding unconvertable strings:
    @NotNull
    public static List<Integer> stringToInt2(@NotNull List<String> strList) {
      // toNonFragile() avoids throwing an exception, but is (with this signature) returning null instead,
      // which -- thanks to the last parameter -- is defined as the delete mark
      return Types.map(strList, Types.toNonFragile(Types.STR_TO_INT), null);
    }

    // same as before, but allowing null on input, which shall be put into output as well:
    @NotNull
    public static List<Integer> stringToInt3(@NotNull List<String> strList) {
      // the following should be a constant
      Integer mark = new Integer(42); // no need for something special, only references are compared
      // toNonFragile() avoids throwing an exception, but is (with this signature) returns 'mark' instead,
      // which -- thanks to the last parameter -- is define as the delete mark
      return Types.map(strList, Types.toNonFragile(Types.STR_TO_INT, mark), mark);
    }

    // something else: flatten a list of collections of strings:
    @NotNull
    public static List<String> getFlattened(@NotNull List<Collection<String>> incoming)
    {
      return Types.flatten(incoming); // list with all strings from all the collections in incoming
    }

In general functions and predicates (i.e. functions returning a boolean value) should be defined once and reused:

  // Filter out all strings which start with "#":
  private static final Predicate1<String> STARTS_WITH_HASH =
          new Predicate1<String>() {
            @Override
            public boolean apply(String arg)
            {
              return arg.startsWith("#");  // assuming non-null
            }
          };

  @NotNull
  public List<String> stringsWithHash(@NotNull Collection<String> strings)
  {
    return Types.filter(strings, STARTS_WITH_HASH);
  }

Empty class

Also provided is the Empty class, which provides empty array and string constants useful as special return results from methods to indicate emptiness. No need to create them over and over.

Module caff-common

Especially this module (online javadoc) contains a wide variety of different functionality.

A bit of this functionality already has made it into blog postings here on de·caff: * Enum Bit Masks

Module caff-common-swing

This module (online javadoc) mainly provides helpers for automatic settings management. This allows to define a few simple constants, and manage preferences and user editing automatically. If you happen do know my de·caff Viewer have a look at its settings dialog. The complete dialog is automatically constructed from some simple constants which define the available settings and their grouping. E.g. here is all what is behind the quite complex View tab.

  /** Internal preference property for the background color in the views. */
  private static final SwingColorPreferenceProperty   PP_BG_COLOR =
          new SwingColorPreferenceProperty(ViewSettingsProvider.PROPERTY_BACKGROUND_COLOR,
                                           "ppBgColor",
                                           Utility.getColorParameter("dxfviewer.bgcolor",
                                                                     DEFAULT_BACKGROUND_COLOR));
  /** Internal preference group for view color settings. */
  private static final EditablePreferenceGroup PG_VIEW_COLORS =
          new EditablePreferenceGroup("pgViewColors",
                                      false,
                                      PP_BG_COLOR);
  /** Internal preference property for the coordinate system on/off state.  */
  private static final SwingBooleanPreferenceProperty PP_CS_ON  =
          new SwingBooleanPreferenceProperty(ViewSettingsProvider.PROPERTY_DISPLAYING_COORDINATES_SYSTEM,
                                             "ppCsOn",
                                             true);
  /** Internal constant for south west placement of coordinates system. */
  private static final IntegerEnumValue ENUM_CS_SOUTH_WEST =
          new IntegerEnumValue("enCsSW", ViewConstants.COORDS_SW);
  /** Internal constant for south east placement of coordinates system. */
  private static final IntegerEnumValue ENUM_CS_SOUTH_EAST =
          new IntegerEnumValue("enCsSE", ViewConstants.COORDS_SE);
  /** Internal constant for north east placement of coordinates system. */
  private static final IntegerEnumValue ENUM_CS_NORTH_EAST =
          new IntegerEnumValue("enCsNE", ViewConstants.COORDS_NE);
  /** Internal constant for north west placement of coordinates system. */
  private static final IntegerEnumValue ENUM_CS_NORTH_WEST =
          new IntegerEnumValue("enCsNW", ViewConstants.COORDS_NW);
  /** Internal preference property for coordinates system placement. */
  private static final SwingEnumPreferenceProperty<Integer> PP_CS_POS =
          new SwingEnumPreferenceProperty<>(ENUM_CS_SOUTH_WEST,
                                                   ViewSettingsProvider.PROPERTY_COORDINATES_SYSTEM_POSITION,
                                                   "ppCsPos",
                                                   ENUM_CS_SOUTH_WEST,
                                                   ENUM_CS_SOUTH_EAST,
                                                   ENUM_CS_NORTH_EAST,
                                                   ENUM_CS_NORTH_WEST);
  /** Internal preference group for coordinates system settings. */
  private static final EditablePreferenceGroup PG_VIEW_CS =
          new EditablePreferenceGroup("pgViewCS",
                                      false,
                                      PP_CS_ON,
                                      PP_CS_POS);
  /** Create 3D VIEWs? */
  private static final SwingBooleanPreferenceProperty PP_3D_VIEWS =
          new SwingBooleanPreferenceProperty("USE_3D_VIEWS",
                                             "ppView3D",
                                             BasicConversionSettings.CREATE_3D_VIEWS);

  /** Create 3D VPORTs? */
  private static final SwingBooleanPreferenceProperty PP_3D_VPORTS =
          new SwingBooleanPreferenceProperty("USE_3D_VPORTS",
                                             "ppVPort3D",
                                             BasicConversionSettings.CREATE_3D_VPORTS);
  /** Internal preference property for using linestyles (needs more memory and is slower!). */
  private static final SwingBooleanPreferenceProperty PP_USING_LINESTYLES =
          new SwingBooleanPreferenceProperty(ViewSettingsProvider.PROPERTY_USING_LINESTYLES,
                                             "ppUsingLinestyles",
                                             true);
  /** Internal preference property for using point shapes (usually is slower!). */
  private static final SwingBooleanPreferenceProperty PP_USING_POINT_SHAPES =
          new SwingBooleanPreferenceProperty(ViewSettingsProvider.PROPERTY_USING_POINT_SHAPES,
                                             "ppUsingPointShapes",
                                             true);
  /** Internal preference property for enabling picking (needs more memory!). */
  private static final SwingBooleanPreferenceProperty PP_ENABLE_PICKING =
          new SwingBooleanPreferenceProperty(ViewSettingsProvider.PROPERTY_PICKING_ENABLED,
                                             "ppEnablePicking",
                                             true);
  /** Internal preference for wheel direction. */
  private static final SwingBooleanPreferenceProperty PP_INVERT_WHEEL_DIRECTION =
          new SwingBooleanPreferenceProperty(ViewSettingsProvider.PROPERTY_INVERT_WHEEL,
                                             "ppInvertWheel", Utility.areWeOnDOS());    // Default on Windows is inverted
  /** Internal preference group for miscellaneous view settings. */
  private static final EditablePreferenceGroup PG_VIEW_MISC =
          new EditablePreferenceGroup("pgViewMisc",
                                      false,
                                      PP_3D_VIEWS,
                                      PP_3D_VPORTS,
                                      PP_USING_LINESTYLES,
                                      PP_USING_POINT_SHAPES,
                                      PP_ENABLE_PICKING,
                                      PP_INVERT_WHEEL_DIRECTION);

  /** Internal preference group for view settings. */
  private static final EditablePreferenceGroup PREFERENCES_VIEW =
          new EditablePreferenceGroup("pgView",
                                      false,
                                      PG_VIEW_COLORS,
                                      PG_VIEW_CS,
                                      PG_VIEW_MISC);

Above I use the convention that PG_ is used for groups of preferences, and PP_ is used for preference properties.

Starting from the end you see the constant PREFERENCES_VIEW which groups the three settings for color, coordinate system and miscellaneous settings (which is exactly what you find in the tab as bordered panels). So if you look for the last preference group PG_VIEW_MISC you’ll just find another constant grouping 6 preference settings. E.g. the last one of these (PP_INVERT_WHEEL_DIRECTION) is a boolean property which is either true or false. The strings starting with pp and pg are i18n tags.

From the above constants the tab in the dialog is automatically created, indeed all tabs are again in another group from which the whole dialog is made in a single call. Loading the preferences and storing them is just one call to this root group each, and listeners can connect to the constants or just read their value when required. Adding another preference setting now just means adding an appropriate constant, its i18n resources and adding this constant to the group where it belongs.

Here’s the view tab as created from the above code:

Screenshot of Options View Tab