Usage KML for Java

The fluent and convenient side of the Java API for KML

The code of KML in the Java world (Listing4) seems a bit awkward and verbose. Additionally, the API makes it easy to forget to register a child element to its parent element, as done in line 18 and 19 of the same listing.

The Java API for KML has a fluent interface. The term fluent interface was first coined by Eric Evans and Martin Fowler [FOW08]. An API with only constructors, setters, and getters is easy to write and often hard to use. An API using a fluent interface is an API designed to be less verbose, more readable, and - as the name implies - to flow. The basic idea of the fluent interface is that each set-method of the class returns itself instead of void. This allows method chaining, as the class itself is returned after each method invocation.

Each class of JAK provides a with-method for each defined private field. For example, a Placemark has a <name> that can be set with this fluent method: public Placemark withName(String name). After the name is set, the method returns a reference to the current placemark object (return this).

Probably the best way to describe it is to provide a further example:

Listing 1: An example of JAK's fluent style.

 Each method returns a reference to the placemark object. There is no need to invoke each method explicitly on the placemark object anymore. The code is less verbose.

Placemark placemark = KmlFactory.createPlacemark();

placemark.withName(<span class="code-quote">"Java User Group Hessen - JUGH!"</span>)
   .withVisibility(<span class="code-keyword">true</span>)
   .withOpen(<span class="code-keyword">false</span>)
   .withDescription(<span class="code-quote">"die Java User Group Hessen"</span>)
   .withStyleUrl(<span class="code-quote">"styles.kml#jugh_style"</span>);

One problem shown in KML in the Java world (Listing 4) was that child elements needed to be explicitly bound to their parent element. The standard procedure is:

  1. Create the parent element or get its reference, e.g. a placemark (line 04).
  2. Create the child element, e.g. point (line 12).
  3. Register the child element at the parent element, e.g. placemark.setGeometry(point) (line 18).

This involves many points at which errors (at least three) can be made. To reduce this repetitive and error prone boiler code, JAK offers convenience methods prefixed with createAndAdd and createAndSet. As the name implies, it creates a new element and sets (or adds) it to its parent. They reduce the three steps or function calls into one and return the created element. This makes it easy to process it in a fluent style.

As seen on KML in the Java world#Figure 3, every Placemark contains a Geometry element. Geometry is an abstract element with several children inheriting from KML in the Java world (Figure 1).

The next figure focuses on the children derived from Geometry:

Figure 2 shows an extract of the createAndSet methods offered by the class Placemark. It offers seven convenience methods to createAndSet a concrete type derived from Geometry class. Whenever an element is able to contain zero or more elements of the same (abstract) type, the API reflects this circumstance with a slightly different naming convention. A createAndAdd method is offered instead. Placemark offers many other convenience methods to createAndSet or to createAndAdd elements that can be contained in it. There is one for each complex element that is shown in KML in the Java world#Figure 3. In the case of an abstract element, one method for each child of the abstract element is offered by JAK.
The code of the createAndSet and createAndAdd methods is simple and helps clients of the API to reduce a lot of error prone boiler code:

Listing 2: Shows an example for a createAndSet method (left side) and a createAndAdd method (right side) both contained in Placemark.

public Point createAndSetPoint() {
  Point newValue = new Point();
  this.setGeometry(newValue);
  return newValue;
}
public Style createAndAddStyle() {
  Style newValue = new Style();
  this.getStyleSelector().add(newValue);
  return newValue;
}

A similar convenience method with the prefix addTo is created for every simple element that is able to contain zero or more elements of the same type:

Listing 3: The addTo method exemplary for the Point class.

class Point {
  public Point addToCoordinates(final String coordinates) {
    this.getCoordinates().add(new Coordinate(coordinates));
    return this;
  }
  ...

The next listing shows the fluent style and all convenience methods offered by the Java API for KML. It is the counterpart to KML in the Java world (Listing 4):

Listing 4: Utilizes the fluent and convenience methods provided by JAK

Compared to KML in the Java world Listing 4 the code is less verbose and error-prone.

Kml kml = KmlFactory.createKml();
kml.createAndSetPlacemark()
   .withName("Java User Group Hessen - JUGH!")
   .withVisibility(true)
   .withOpen(false)
   .withDescription("die Java User Group Hessen")
   .withStyleUrl("styles.kml#jugh_style")
   .createAndSetPoint()
      .withExtrude(false)
      .withAltitudeMode(AltitudeMode.CLAMP_TO_GROUND)
      .addToCoordinates("9.444652669565212,51.30473589438118,0");
kml.marshal(System.out);

The naming conventions of the fluent and convenience methods presented here are applied throughout the whole Java API for KML. Once understood, they aid in writing code that is less verbose and easier to read.

Bibliography

[FOW08] MARTIN FOWLER; Fluent Interfaces; http://www.martinfowler.com/bliki/FluentInterface.html