Custom Process Tutorial

In this tutorial you will learn how to develop and deploy a custom process within the 52°North WPS as a single Java file.The ProcessDescription file will be created for you. Note that all Formats of all Parsers/Generators that support the DataBinding you choose in method 3/4 (see below) are added to the ProcessDescription file. If you want more control over the formats your Algorithm should support you may want to choose AbstractAlgorithm and follow the respective tutorial.The AbstractSelfDescribingAlgorithm has some constraints regarding certain elements of the ProcessDescription. For example you can not specify the title and abstract of a process yourself. If you want more control (and even less programming) you could have a look at the tutorial about extending AbstractAnnotatedAlgorithm.

Before you start, you need to have the WPS source set-up. A tutorial on how to do that can be found here. In the following, we assume you use Eclipse for editing.

Set-up Files for Custom Process

  1. Create a new package: org.n52.wps.demo
  2. Add a new Class ConvexHullDemo
  3. Let the new class extend AbstractSelfDescribingAlgorithm

Implement Process

For AbstractSelfDescribingAlgorithm, you need to implement five methods:

Method 1: public List getInputIdentifiers()

This method lists all identifiers of the inputs you need. Since we want to develop a ConvexHull algorithm, we basically need only geometries.

We give this identifier the name FEATURES.

Therefore, return a list with a single string: FEATURES

List<String> list = new ArrayList();
list.add("FEATURES");
return list;

Method 2: public List getOutputIdentifiers()

This method lists all identifiers of the produced outputs. A ConvexHull algorithm produces only polygons as outputs.

Therefore we name the output: polygons

Return a list with a single string: polygons

List<String> list = new ArrayList();
list.add("polygons");
return list;

Method 3: public Class getInputDataType(String identifier)

This method lists all input datatypes for a given input data identifier.In our case, we only have one input identifier: FEATURES. The return class must be a specific binding.

Since we want to use a JTS algorithm which understands Geotools features, we want to use a GTVectorDataBinding and therefore return:

if (identifier.equalsIgnoreCase("FEATURES")) {
        return GTVectorDataBinding.class;
}
return null;

Method 4: public Class getOutputDataType(String identifier)

This method lists all output datatypes for a given output data identifier.In our case, we only have only one output identifier: polygons. Besides we know that JTS outputs Geotools features. Therefore, we return:

if (identifier.equalsIgnoreCase("polygons")) {
        return GTVectorDataBinding.class;
} 
return null;                                    

Method 5: public Map<String, IData> run(Map<String, List<IData>> inputData)

This method holds the business logic. At first we check that all necessary inputdata is present.

if (inputData == null || !inputData.containsKey("FEATURES")) {
        throw new RuntimeException("Error while allocating input parameters");
}
List<IData> dataList = inputData.get("FEATURES");
if (dataList == null || dataList.size() != 1) {
        throw new RuntimeException("Error while allocating input parameters");
}

Next, we extract the Geotools feature collection:

IData firstInputData = dataList.get(0);
FeatureCollection featureCollection = ((GTVectorDataBinding) firstInputData).getPayload();

And iterate over the features in order to extract all coordinates which will be stored in a list called coordinateList:

FeatureIterator iter = featureCollection.features();
List<Coordinate> coordinateList = new ArrayList<Coordinate>();
int counter = 0;
while (iter.hasNext()) {
                SimpleFeature feature = (SimpleFeature) iter.next();
                if (feature.getDefaultGeometry() == null) {
                        throw new NullPointerException("defaultGeometry is null in feature id: "+ feature.getID());
                }
                Geometry geom = (Geometry) feature.getDefaultGeometry();
                Coordinate[] coordinateArray = geom.getCoordinates();
                for(Coordinate coordinate : coordinateArray){
                        coordinateList.add(coordinate);
                }
}
iter.close();

In the next step, we convert the coordinateList to an array, because this is required as input for the JTS function.

Coordinate[] coordinateArray = new Coordinate[coordinateList.size()];
for(int i = 0; i<coordinateList.size(); i++){
        coordinateArray[i] = coordinateList.get(i);
}

Now, we are ready to create a ConvexHull.

com.vividsolutions.jts.algorithm.ConvexHull convexHull = new com.vividsolutions.jts.algorithm.ConvexHull(coordinateArray, new GeometryFactory());
Geometry geometry = convexHull.getConvexHull();

And create a new Geotools feature with the output geometry via:

String uuid = UUID.randomUUID().toString();
SimpleFeatureType featureType = GTHelper.createFeatureType(geometry, uuid, featureCollection.getSchema().getCoordinateReferenceSystem());
GTHelper.createGML3SchemaForFeatureType(featureType);
Feature feature = GTHelper.createFeature("0", geometry, featureType);

We now create a feature collection and put the resultfeature in it.

SimpleFeatureCollection fOut = DefaultFeatureCollections.newCollection();
fOut.add((SimpleFeature) feature);

The last step is to create the standard output hashmap which holds the name of the output identifier and an IData object.In our case we create a GTVectordataBinding.

HashMap<String, IData> result = new HashMap<String, IData>();
result.put("polygons", new GTVectorDataBinding(fOut));
return result;

Save the source code and compile it. You may need to "Organize imports" to add all required classes.

You can download the complete Java class here.

Deploy the process

See here.

Execute the process

See here.
Topic attachments
I Attachment Action Size Date Who Comment
ConvexHullDemo.javajava ConvexHullDemo.java manage 4 K 07 Jun 2013 - 12:15 BenjaminPross  
deploy1.pngpng deploy1.png manage 35 K 15 Aug 2014 - 13:41 BenjaminPross  
deploy2.pngpng deploy2.png manage 30 K 07 Jun 2013 - 13:24 BenjaminPross  
deploy3.pngpng deploy3.png manage 40 K 07 Jun 2013 - 13:41 BenjaminPross  
Topic revision: r10 - 15 Aug 2014, BenjaminPross
Legal Notice | Privacy Statement


This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki? Send feedback