Extending a Simple Algorithm

Feedback


The REST service publishing mechanism section gives you an introduction to the REST service publishing mechanism. The resource information is saved in the resource configuration files and transferred to the REST application object through the REST application context. Therefore, when the HTTP request arrives at the REST application object, the proper resource can be found to handle the request. Through the process summarized above, we can know that we need to take two steps to extend a simple algorithm resource.

  1. Implementing a Simple Algorithm Class

  2. Configuring the Algorithm

1. Implementing a Simple Algorithm Class

In the REST implementation framework of SuperMap iServer, the highest-level resource class is resourceBase, from which all resources can directly or indirectly inherit.

When extending REST resource, you need to get the favorable class by inheriting from the ResourceBase class or its child class. SuperMap iServer provides a lot of abstract classes except for the ResourceBase class and the final implementation class, representing different types of resources, which provides great convenience for REST resource extension. You can find the proper abstract class according to the resource functions for extension. Also, you can decide to directly inherit from an existing resource class if the target resource is similar to an existing resource.

Please refer to the com.supermap.services.rest.resources package in JavaDoc for more information about the abstract classes for REST resources in SuperMap iServer .

As a reference for resource extension, here we list the types of implemented resource classes (see the ResourceType enumeration in JavaDoc).

Name Parent class Implemented resources
Simple algorithm resource SimpleAlgorithmResultResourceBase

symbol, clearCache, etc. of map, statistic of data

ImageResourceBase entireImage, highlightImage, image, overview, tileImage, etc.
MeasureResourceBase area, distance, etc.
Algorithm resource AlgorithmResultResource queryResult  of map, featureResult of data

Algorithm result resource

AlgorithmResultSetResource queryResults of map, featureResults of data
Directory resource CatalogListResourceBase maps, root, tempLayersSet, trackingLayers, domainComponents, domainComponentdata etc. of map, data, datasources, etc. of data, networkanalyst of networkanalyst, 3D, scenes, datas etc. of 3D
Static resource StaticResource layers, map, templayers, etc. of map, networkDataName of networkanalyst

In addition, CommonAlgorithmResultResource is a child class of the SimpleAlgorithmResultResourceBase resource. Resources implemented based on CommonAlgorithmResultResource include closestfacilities, weightMatrix, TSPPaths, serviceAreas, MTSPPaths, location, paths, etc. of the closestfacilities module, tileData, etc. of the 3D module. SimpleResource is a child class of ResourceBase. Resources implemented based on SimpleResource include scene, layers, layer, data, config, modelIndex, tileDataVersion, etc. of the 3D module.

Here, we extend the rectangleArea resource to implement the functionality of measuring a rectangular area on the map and returning the result.

Since we are going to measure area on a map, we take rectangleArea as a child resource of the map resource. The designed URI is as follows:

http://<server>:<port>/iserver/services/components-rest/rest/maps/{mapName}/rectangleArea[.<format>]

The request parameters are:

Name Type Description
rect2D Rectangle2D The rectangular area to be measured on the map.
unit Unit The unit of the measurement result.

The response structure is:

Field Type Description
area double The area of the rectangular area.
unit Unit The unit of the measurement result.

Since rectangleArea resource is similar to the impleAlgorithmResultResourceBase resource, we construct the implementation class of rectangleAreaResource by inheriting from the implementatioon class of the SimpleAlgorithmResultResourceBase abstract class. The abstract methods of the SimpleAlgorithmResultResourceBase class, as shown below, are required to be implemented. For more details, please refer to JavaDoc.

Abstract method Description
isResourceExist() Determines whether the resource is available
checkUrlParamValid(Map) Checks whether the parameters in the URI are valid. If not valid, an exception will be thrown.
createArithParamClassMappings() The type of the algorithm parameters, that is, the field and type of the request parameter.
runArithMetic(Map) Runs the algorithm and gets the result

The business logic, i.e., the measuring functionality, can be implemented by the implementation class com.supermap.services.components.impl.MapImpl (already provided by SuperMap iServer) of the map component (com.supermap.services.components.Map). In the sample class RectangleAreaResource, the constructor gets the map name and the MapImpl component. The map name is retrieved from the URI, and the MapImpl object is retrieved from the REST application context. Sample code:

package com.supermap.sample.extendREST;

import java.util.HashMap;

import org.restlet.Context;

import org.restlet.Request;

import org.restlet.Response;

import com.supermap.services.components.Map;

import com.supermap.services.components.MapException;

import com.supermap.services.components.commontypes.MeasureParameter;

import com.supermap.services.components.commontypes.MeasureResult;

import com.supermap.services.components.commontypes.Point2D;

import com.supermap.services.components.commontypes.Rectangle2D;

import com.supermap.services.components.commontypes.Unit;

import com.supermap.services.rest.resources.SimpleAlgorithmResultResourceBase;

import com.supermap.services.rest.util.MappingUtil;

public class RectangleAreaResource extends SimpleAlgorithmResultResourceBase{

    private String mapName;

    private MappingUtil mappingUtil;

    

    public RectangleAreaResource(Context context, Request request, Response response) {

        super(context, request, response);

        mappingUtil = new MappingUtil(this);

        this.mapName = this.mappingUtil.getMapName(this.getRequest());

        this.mapName = this.mapName.trim();

    }

    //Determines whether the resource exists

    public boolean isResourceExist(){

//      Logger.info("rectangle area resource exists");

        boolean flag = false;

        flag = this.mappingUtil.isMapExist(this.mapName);

        return flag;

    }

  //Run the algorithm and get the result

    protected Object runArithMetic(java.util.Map params){

        Object arithResult=null;

        //If the parameters are null, the area will be returned as -1

        if(params==null||0==params.size()){

            MeasureResult  result =   new MeasureResult();

            result.area = -1;

            arithResult = result ;

        }else{

                Rectangle2D rect = (Rectangle2D)params.get("rect2D");

            Unit  unit = (Unit)params.get("unit");

            //The unit can be not transferred. The default is meters

            if(unit == null){

                unit = Unit.METER;

            }

            //The measurement parameter class with the unit information stored

            MeasureParameter measureParam = new MeasureParameter();

            measureParam.unit = unit;

            //Convert Rectangle2D into Point2Ds

            Point2D leftBottom=rect.leftBottom;

            Point2D rightTop=rect.rightTop;

            Point2D leftTop=new Point2D(leftBottom.x,rightTop.y);

            Point2D rightBottom=new Point2D(rightTop.x,leftBottom.y);

            Point2D[] point2Ds={leftBottom,leftTop,rightTop,rightBottom};

            

            //The measurement result

            try {

                Map mapComponent = this.mappingUtil.getMapComponent(mapName);

                                arithResult = mapComponent.measureArea(mapName, point2Ds, measureParam);

                        } catch (MapException e) {

                                // TODO Auto-generated catch block

                                e.printStackTrace();

                        }

        }

        

        return arithResult;

    }

    //The type of the algorithm parameter, i.e., the structure of the request parameter

    protected java.util.Map<String, Class> createArithParamClassMappings(){

        java.util.Map<String, Class> paramClassMapping = new HashMap<String, Class>();

        paramClassMapping.put("rect2D", Rectangle2D.class);

        paramClassMapping.put("unit", Unit.class);

        return paramClassMapping;

    }

    

    //Determines whether the parameters in the URI are valid (omitted here)

        protected void checkUrlParamValid(java.util.Map arg0) {

                // TODO Auto-generated method stub

                

        }

}

You can find the source code for this example in %SuperMap iServer_HOME%/samples/code/ExtendREST.

After compiling, package into a Jar package, ExtendREST.jar for instance, and place the package in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib. Please note that all implementation classes, including the implementation of the extensions that will be introduced later, need to be packaged and placed in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib.

Note: SuperMap iServer REST framework uses FreeMarker to generate HTML format representation. To make the rectangleArea resource support HTML format representation, we still need to compose the *.ftl files, i.e., templates. Please refer to the existing template files in the templates directory in SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib/iserver-all-{version}.jar.

FreeMarker is a generic tool to generate text output. In SuperMap iServer REST framework, ${resource.content.*} in the *.ftl template file is the representation result field and the file name must be identical to the resource ID.

Compose the FreeMarker template file for the rectangleArea, as shown below. rectangleArea.ftl must be placed in a Jar package in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/lib. It is suggested that you place the template file in the same package with the implementation class of the resource, i.e., ExtendREST.jar. The Jar package holding the template file must be placed in the [Jar package]/templates directory.

<#include "head.ftl">

<h1>rectangleArea resource</h1>

<br>

<b>Description: </b> The area measurement result resource, used to represent an area measurement result.

<br>

<#if resource.content.area!= -1>

 <p>

         <table width="150px" id="userTable">

                <tr valign="left">

                <#setting number_format="#0.000000000#">

                <td style="width:50px"> <h5>area:</h5></td> <td style="width:50px"> ${resource.content.area}</td>

                </tr>

                <tr valign="left">

                <td style="width:50px"> <h5 >unit:</h5></td> <td style="width:50px">${resource.content.unit}</td>

                </tr>

         </table>

 </p>

<#else>

 <br><br>

    Please set the rect2D parameter. If not set, -1 will be returned, indicating measurement failure.

</#if>

<p>

<form method="get" >

        <table style="border:1px solid #000000;width:800;" >

           <#assign prerect2D>{leftBottom:{x:23,y:34},rightTop:{x:40,y:50}}</#assign>

            <tr><td>rect2D</td><td><textarea type="text" style="width:255px;height:50px" name="rect2D" >${prerect2D}</textarea></td></tr>

            <tr>

                <td>unit</td>

                <td>

                    <select name="unit">

                                <option value="METER" selected="selected">METER</option>

                                <option value="KILOMETER" selected="selected">KILOMETER</option>

                        </select>

                        </td>

                </tr>

            <tr><td></td><td><input type="submit" value="rect2DareaMeasure"/></td></tr>

        </table>

</form>

</p>

<br>

<br>

<hr>

<#include "tail.ftl">

2. Configuring the Algorithm

There are two ways to add the resource information to configuration file:

2.1. Add to external iserver-rest-resources.xml file

2.2. Add to function module XML file

 

2.1. Add to external iserver-rest-resources.xml file

The configuration information of the extended resource needs to be placed in %SuperMap iServer_HOME%/webapps/iserver/WEB-INF/iserver-rest-resources.xml. Therefore, the resource can be found and published as REST service when the SuperMap iServer REST service starts. The structure of the iserver-rest-resources.xml file is as follows:

<resources>

     ......

     <resource>

            ......

     </resource>

</resources>

where a <resource/> node corresponds to an item of resource information. The <components/> node is used for domain component configuration and will be introduced in detail in Publishing Domain Services as Resources section.

The structure of the <resource/> nodes for the rectangleArea resource is as follows:

<resource>

    <configID>rectangleArea</configID>

    <urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>

    <resourceType>ArithmeticResource</resourceType>

    <implementClass>com.supermap.sample.extendREST.RectangleAreaResource</implementClass>

    <extensionEncoderBeanNames></extensionEncoderBeanNames>

    <extensionDecoderBeanNames></extensionDecoderBeanNames>

    <extensionHttpActionHandlerBeanName></extensionHttpActionHandlerBeanName>

</resource>

The <resource/> nodes are introduced in detail below:

Note: In the configuration, the extensionEncoderBeanNames, extensionDecoderBeanNames, extensionActionHandlerBeanName nodes, indicating the implementations of the extended encoder, the extended decoder, and the HTTP request handler respectively, can be absent or null. If it is the case, SuperMap iServer will employ the default values.

2.2. Add to function module XML file

This method can pack the configuration information into Jar, which is convenient to administrator to configure.

This sample extends the map map module resources. Add the Jar here: ///config/resource/rest/mappingResources.xml file (See The correspondence of the resource module and the configuration file) is as follows:

<resources>

        <resource>

            <configID>rectangleArea</configID>

            <urlTemplate>/maps/{mapName}/rectangleArea</urlTemplate>

            <resourceType>ArithmeticResource</resourceType>

            <implementClass>com.supermap.sample.extendREST.RectangleAreaResource</implementClass>

        </resource>

</resources>

You can configure multiple <resources/> in the <resource/> label.

This step can be in the Java project that implements the resource class. It can be packed in the same Jar Package, such as the ExtendREST.jar.

 

Up till now, an extended resource is finished. The rectangleArea resource implements the area measurement of a rectangular area on a map. Start the service and use the URI below http://localhost:8090/iserver/services/components-rest/rest/maps/WorldMap/rectangleArea.html, taking the HTML output format as an example, to access the rectangleArea resource of the WorldMap, as shown below.

Input the coordinates of the bottom left and top right points of the rectangle in the rect2D box, select a unit, and then click rect2DareaMeasure to display the result, as shown below: