GSIP 98 - replace old KML module with new one

Overview

The current KML module is seeing low maintenance due to convoluted class structure and abundance of internal hacks. Replace it with a full clean refactor with improved functionality, better speed and higher testing coverage.

Proposed By

Andrea Aime

Assigned to Release

2.4.0

State

Choose one of: Under Discussion, In Progress, Completed, Rejected, Deferred

Motivation

The current KML module has not seen new features in a long while, and very little maintenance of any kind. Some features stopped working (e.g., some variants of the superoverlay mode), others are fragile, but developers are not keen to put their hands in the module since the code is rather convoluted, relying on large utilities classes, and with complex dependencies among the various XML translators.
Also, while understood by Google Earth, the generated KML is not compliant with the OGC KML schemas in various places.

A rewrite from the ground was devised to obtain the following objectives:

  • strict adherence to the OGC KML schemas
  • better object oriented structure, with smaller classes, each one dedicated to a specific purpose and with minimal dependencies
  • easier maintenance
  • easier to plug into the KML generation to add extra bits, easier to build new types of KML based outputs leveraging the existing insfrastructure
  • higher performance
  • higher testing levels

Introduction to the KML2 module

The module builds KML documents as object model trees based on the JAK library (https://code.google.com/p/javaapiforkml/) and uses the JDK own JAXB library to then serialize the resulting tree. Tests have been made to make sure JAXB is not affecting WFS CITE tests, and the usage of JAXB ensures the output is schema compliant.

There are three KML object model builders in the codebase, two of them building a small KML made mostly of links, and one that is streaming, based on lists that are evaluated as they are traversed: https://github.com/geoserver/geoserver/tree/master/src/community/kml2/src/main/java/org/geoserver/kml/builder

For example, the simple network link builder just builds a kml with a networklink for each layer: https://github.com/geoserver/geoserver/blob/master/src/community/kml2/src/main/java/org/geoserver/kml/builder/SimpleNetworkLinkBuilder.java

The StreamingKMLBuilder instead builds a KML document containing a list of folders (one per layer) that is generated as the list itself is traversed, which in turn contains placemarks that are also generated as the list of placemarks is traversed: https://github.com/geoserver/geoserver/blob/master/src/community/kml2/src/main/java/org/geoserver/kml/builder/StreamingKMLBuilder.java

The streaming behavior is based on the Sequence construct, a simplified iterator, and classes that wrap it to build enough List behavior to allow JAXB to encode the output: https://github.com/geoserver/geoserver/tree/master/src/community/kml2/src/main/java/org/geoserver/kml/sequence

The feature sequence factory and its sequence is the best example of how the streaming encoding works: https://github.com/geoserver/geoserver/blob/master/src/community/kml2/src/main/java/org/geoserver/kml/sequence/FeatureSequenceFactory.java

The interesting bit here is that a basic Placemark is built, and then its contents are actually filled by pluggable decorators that do add the geometry, title, description, style and so on: https://github.com/geoserver/geoserver/tree/master/src/community/kml2/src/main/java/org/geoserver/kml/decorator
This makes it easy to add new content in placemarks, but it also allows to completely separate GeoSearch as a clear cut plugin.

The regionation code is still there, and has been isolated in its own package: https://github.com/geoserver/geoserver/tree/master/src/community/kml2/src/main/java/org/geoserver/kml/regionate

All the crufty code to load the data and parse the styles have been factored out in a bunch of small Visitor classes, plus a KMLFeatureAccessor that binds them all togheter: https://github.com/geoserver/geoserver/tree/master/src/community/kml2/src/main/java/org/geoserver/kml/utils

Proposal

We propose to swap the current KML module with the KML2 community module found in community land.

The module has all the tests than the previous one, a code coverage of 86% (the old KML module had one of 79%) and besides the benefits for the developers, it provides the following extra benefits to the users:

  • a new WFS KML output format leveraging the extended data with schema KML construct
  • faster KML generation, almost on par with the GML2 output formats, due to several internal optimizations (e.g., templates presence is evaluated just once per encoding, as opposed to once per feature)
  • schema compliant KML output

Moreover, the module has been manually tested against the GeoServer KML documentation, making sure every advertised behavior works as expected. During the process we found several bits that do not work as advertised in the old KML module, for example, the KML reflector always generate a kmz extension, even if the output is really a KML file, another example is the superverlays in raster mode (either raster layer, or vector layer forced to raster), which simply fail to generate the link hierarchy.
All of the above has been fixed in the kml2 module.

Feedback

This section should contain feedback provided by PSC members who may have a problem with the proposal.

Backwards Compatibility

No backwards compatibility issue, kml2 has been designed to match the old kml module feature by feature

Voting

Alessio Fabiani: +1
Andrea Aime: +1
Ben Caradoc-Davies: +1
Christian Mueller:
Gabriel Roldán:
Jody Garnett:
Jukka Rahkonen:
Justin Deoliveira: +1
Phil Scadden: +1
Simone Giannecchini:

Links

[JIRA Task|]
[Email Discussion|]
[Wiki Page|]

Added by Andrea Aime, last edited by Andrea Aime on Jul 05, 2013  (view change)
View Attachments (0) Info