Recommended code patterns

This page lists some recommended code pattern for developing or using Apache SIS.

Referencing

Recommended code pattern when using the sis-referencing module.

Never explicitely swap ordinates for axis order

The axis order issue causes lot of confusion, and developers are sometime tempted to swap their ordinate values in order to comply with some expected axis ordering. It should never be necessary, since the Apache SIS referencing engine manages axis order transparently — provided that the Coordinate Reference System (CRS) definition is accurate. If a code needs to swap ordinates, this is probably an indication that the CRS has not been properly defined. Instead than patching the coordinate values, try to make sure that the Source CRS (associated to the original data) and the Target CRS (the coordinate space where to perform the work) are properly defined, and let the referencing engine performs the conversion from the source to the target CRS.

Coverages

Recommended code pattern when using the sis-coverage module.

Georeference images with affine transforms, not bounding boxes

Many users define the geographic extent of an image by its corner locations. This approach is not sufficient as it does not specify if the (x,y) axes are interchanged (see the axis order issue) or if the y axis is oriented downward. All images in SIS shall be georeferenced by at least an affine transform (more complex transforms are also possible), never by a rectangle or bounding box. In the two-dimensional case, the standard java.awt.geom.AffineTransform class can be used.

International

Recommended code pattern for internationalization.

Specify timezone

Geospatial data often cover a wide geographic area, spanning many time zones. Timezone are sometime specified as metadata in the header of data files to be read, or is sometime fixed to UTC by applications managing world-wide data. Many SIS objects have Locale and TimeZone fields. Such locale and timezone shall be given to java.text.DateFormat or java.util.Calendar constructors.

When reading dates or timestamps from a JDBC database, always use the ResultSet method accepting a Calendar argument, when such method is available. For example prefer the getTimestamp(int, Calendar) method instead than getTimestamp(int). The Calendar object shall has been created with the appropriate timezone.

Replace underscores by spaces before sorting

Before to sort programmatic names for human reading, consider replacing all occurrences of the underscore character ('_') by the space character (' '). The ASCII value of the underscore character is greater than 'Z' but lower than 'a', which sometime produce unexpected sort results. For example "Foo_bar" is sorted between "FooBar" and "Foobar". The space character produces more consistent sort results because its ASCII value is less than any printable character, so "Foo bar" is sorted before both "FooBar" and "Foobar".

Loop over character sequences using code points

Since Java 1.5, characters are no longer restricted to 16 bits. Some "characters" are actually represented using two consecutive char elements. Those "characters" are called code points. Consequently, when iterating over characters in a string, the following pattern shall be used:

for (int i=0; i<string.length();) {
    final int c = string.codePointAt(i);
    // ... do some stuff ...
    i += Character.charCount(c);
}

Logging

Apache SIS uses the java.util.logging framework with one minor difference: instead of invoking the getLogger(String) method provided by the java.util.logging.Logger class, we rather invoke the method provided by the apache.sis.util.logging.Logging class. The result is identical by default, but the SIS method gives a chance to redirect the logging to an other framework like Log4J if desired. The difference between the SIS approach and other facades like common-logging is that SIS uses the standard Java API (except for the above-cited getLogger method) instead than defining a new API.

Logger name

The name given in argument to the getLogger(String) method is usually the package name of the class emitting the log messages, but not necessarily. In particular, we do not follow this convention if the class is located in an internal package (org.apache.sis.internal.*) since those packages are considered privates. In such cases, the logger name should be the package name of the public class that use the internal class.

The reason for the above rule is that logger names are considered part of the public API, since developers use them for configuring their logging (verbosity, destination, etc.). Note that the "real" package name of the emitter is available by LogRecord.getSourceClassName().

Logging level

All logging at Level.INFO or above shall be targeted to users or administrators, not to developers. In particular Level.SEVERE shall be reserved for critical errors that compromise the application stability — it shall not be used for exceptions thrown while parsing user data (file or database).