arcgissamples\soe\JavaSimpleRESTSOEWithProperties.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Simple REST SOE With properties sample
arcgissamples\soe\JavaSimpleRESTSOEWithProperties.java
/* Copyright 2015 ESRI
* 
* All rights reserved under the copyright laws of the United States
* and applicable international laws, treaties, and conventions.
* 
* You may freely redistribute and use this sample code, with or
* without modification, provided you include the original copyright
* notice and use restrictions.
* 
* See the use restrictions at <your ArcGIS install location>/DeveloperKit10.4/userestrictions.txt.
* 
*/
package arcgissamples.soe;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.esri.arcgis.carto.IMapLayerInfo;
import com.esri.arcgis.carto.IMapLayerInfos;
import com.esri.arcgis.carto.IMapServer3;
import com.esri.arcgis.carto.IMapServerDataAccess;
import com.esri.arcgis.carto.IMapServerInfo;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.interop.extn.ServerObjectExtProperties;
import com.esri.arcgis.server.IServerObjectExtension;
import com.esri.arcgis.server.IServerObjectHelper;
import com.esri.arcgis.server.json.JSONArray;
import com.esri.arcgis.server.json.JSONException;
import com.esri.arcgis.server.json.JSONObject;
import com.esri.arcgis.system.ILog;
import com.esri.arcgis.system.IObjectConstruct;
import com.esri.arcgis.system.IPropertySet;
import com.esri.arcgis.system.IRESTRequestHandler;
import com.esri.arcgis.system.ServerUtilities;

@ArcGISExtension
@ServerObjectExtProperties(displayName = "Java Simple REST SOE With Properties", description = "Java Simple REST SOE With Properties", properties = {
  "layerType=feature", "returnFormat=json", "maxNumFeatures=100",
  "isEditable=false" })
public class JavaSimpleRESTSOEWithProperties implements IServerObjectExtension,
  IObjectConstruct, IRESTRequestHandler {
    private static final long serialVersionUID = 1L;
    private IServerObjectHelper soHelper;
    private ILog serverLog;
    private IMapServerDataAccess mapServerDataAccess;
    private IMapLayerInfos layerInfos;

    // properties
    private String layerType, returnFormat;
    private int maxNumFeatures;
    private boolean isEditable;

    public JavaSimpleRESTSOEWithProperties() throws Exception {
  super();
    }

    /**
     * init() is called once, when the instance of the SOE is created.
     */
    public void init(IServerObjectHelper soh) throws IOException,
      AutomationException {
  /*
   * An SOE should get the Server Object from the Server Object Helper in
   * order to make any method calls on the Server Object and release the
   * reference after making the method calls.
   */
  this.soHelper = soh;
  this.serverLog = ServerUtilities.getServerLogger();
  this.mapServerDataAccess = (IMapServerDataAccess) this.soHelper
    .getServerObject();
  IMapServer3 ms = (IMapServer3) this.mapServerDataAccess;
  IMapServerInfo mapServerInfo = ms.getServerInfo(ms.getDefaultMapName());
  this.layerInfos = mapServerInfo.getMapLayerInfos();

  serverLog.addMessage(3, 200, "Initialized " + this.getClass().getName()
    + " SOE.");
    }

    /**
     * shutdown() is called once when the Server Object's context is being shut
     * down and is about to go away.
     */
    public void shutdown() throws IOException, AutomationException {
  /*
   * The SOE should release its reference on the Server Object Helper.
   */
  serverLog.addMessage(3, 200, "Shutting down "
    + this.getClass().getName() + " SOE.");
  this.soHelper = null;
  this.serverLog = null;
  this.mapServerDataAccess = null;
    }

    /****************************************************************************************************************************
     * IObjectConstruct: This is an optional interface for SOEs. If your SOE
     * includes configuration properties or requires any additional
     * initialization logic, you need to implement the IObjectConstruct
     * interface.
     * 
     * This interface includes a single method called construct().
     ****************************************************************************************************************************/
    /**
     * construct() is called only once, when the SOE is created, after
     * IServerObjectExtension.init() is called. This method hands back the
     * configuration properties for the SOE as a property set. You should
     * include any expensive initialization logic for your SOE within your
     * implementation of construct().
     */
    public void construct(IPropertySet propertySet) throws IOException {
  String lType = (String) propertySet.getProperty("layerType");
  if (lType.equalsIgnoreCase("feature")
    || lType.equalsIgnoreCase("raster")
    || lType.equalsIgnoreCase("all")) {
      this.layerType = lType;
  } else {
      this.layerType = "feature";
  }

  String format = (String) propertySet.getProperty("returnFormat");
  if (format.equalsIgnoreCase("json") || format.equalsIgnoreCase("html")
    || format.equalsIgnoreCase("text")) {
      this.returnFormat = format;
  } else {
      this.returnFormat = "json";
  }

  int maxFeatures = Integer.parseInt((String) propertySet
    .getProperty("maxNumFeatures"));
  if (maxFeatures <= 0) {
      this.maxNumFeatures = 100;
  } else {
      this.maxNumFeatures = maxFeatures;
  }

  String editableStringValue = (String) propertySet
    .getProperty("isEditable");
  if (editableStringValue.equalsIgnoreCase("true")
    || editableStringValue.equalsIgnoreCase("false")) {
      this.isEditable = Boolean.parseBoolean((String) propertySet
        .getProperty("isEditable"));
  } else {
      this.isEditable = false;
  }
    }

    /**
     * Returns JSON representation of root resource's description.
     * 
     * @return String JSON representation of root resource's description.
     */
    private byte[] getRootResource() throws Exception {
  JSONObject json = new JSONObject();
  json.put("name", "Java Simple REST SOE With Properties");
  json.put(
    "description",
    "Simple REST SOE with 1 sub-resource called \"layers\" and 1 property called layerType.");
  json.put(
    "usage",
    "The \"layers\" subresource returns all layers of a certain type in the map service.\n"
      + "The layerType property defines the type of layers are returned by the \"layers\" subresource.");
  return json.toString().getBytes("utf-8");
    }

    /**
     * Returns JSON representation of specified sub-resource.
     * 
     * @return String JSON representation of specified resource.
     */
    private byte[] getSubresourceLayers(Map<String, String> responsePropertiesMap) throws Exception {
  JSONObject json = new JSONObject();
  json.put("layers", new String(getLayersInfo()));
  
  responsePropertiesMap.put("Content-Type", "application/json");
  
  return json.toString().getBytes("utf-8");
    }

    /**
     * Returns properties and their current values
     * 
     * @return String JSON representation of specified resource.
     */
    private byte[] getSubresourceProperties(Map<String, String> responsePropertiesMap) throws Exception {
  JSONObject json = new JSONObject();
  json.put("layerType", this.layerType);
  json.put("returnFormat", this.returnFormat);
  json.put("maxNumFeatures", this.maxNumFeatures);
  json.put("isEditable", this.isEditable);
  
  responsePropertiesMap.put("Content-Type", "application/json");
  
  return json.toString().getBytes("utf-8");
    }

    /**
     * Returns info about layers in associated map service
     * 
     * @return
     * @throws Exception
     */
    public byte[] getLayersInfo() throws Exception {
  String aoLayerType = "";
  if (this.layerType.equalsIgnoreCase("feature")) {
      aoLayerType = "Feature Layer";
  } else if (this.layerType.equalsIgnoreCase("raster")) {
      aoLayerType = "Raster Layer";
  } else if (this.layerType.equalsIgnoreCase("dataset")) {
      aoLayerType = "Network Dataset Layer";
  } else {
      return ServerUtilities
        .sendError(
          1,
          "Propety layerType has invalid value.",
          new String[] { "Acceptable values are \"feature\", \"raster\", and \"dataset\"." })
        .getBytes("utf-8");
  }

  int layerTypeCount = 0;
  JSONObject json = new JSONObject();
  JSONArray layerArray = new JSONArray();
  for (int i = 0; i < layerInfos.getCount(); i++) {
      IMapLayerInfo layerInfo = layerInfos.getElement(i);
      String lType = layerInfo.getType();
      if (lType.equalsIgnoreCase(aoLayerType)) {
    JSONObject layerJSON = new JSONObject();
    layerJSON.put("name", layerInfo.getName());
    layerJSON.put("type", lType);
    layerJSON.put("id", layerInfo.getID());
    layerJSON.put("description", layerInfo.getDescription());
    layerArray.put(layerTypeCount, layerJSON);
    layerTypeCount++;
      }
  }
  json.put(this.layerType + " layerCount", layerTypeCount);
  json.put("layersInfo", layerArray);

  if (this.returnFormat.equalsIgnoreCase("html")) {
      return convertJSONToHTML(json).getBytes();
  } else if (this.returnFormat.equalsIgnoreCase("text")) {
      return convertJSONToText(json).getBytes();
  }

  return json.toString().getBytes();
    }

    /**
     * Converts JSON to plain text
     * 
     * @param json
     * @return String
     */
    private String convertJSONToText(JSONObject json) {
  String text = this.layerType + " layerCount: "
    + json.getString(this.layerType + " layerCount");
  text += " Layers:";

  JSONArray layersArray = json.getJSONArray("layersInfo");
  for (int i = 0; i < layersArray.length(); i++) {
      JSONObject layerJSON = layersArray.getJSONObject(i);
      text += "Name: " + layerJSON.getString("name") + " Type: "
        + layerJSON.getString("type") + " ID: "
        + layerJSON.getString("id") + " Description: "
        + layerJSON.getString("description") + ";";
  }

  return text;
    }

    /**
     * Converts JSON to HTML
     * 
     * @param json
     * @return
     */
    private String convertJSONToHTML(JSONObject json) {
  String html = "<table>";

  html += "<tr>" + "<td>" + this.layerType + " layerCount</td>" + "<td>"
    + json.getString(this.layerType + " layerCount") + "</td>"
    + "</tr>";

  html += "<tr><td colspan='2'>Layers</td></tr>";
  JSONArray layersArray = json.getJSONArray("layersInfo");
  for (int i = 0; i < layersArray.length(); i++) {
      JSONObject layerJSON = layersArray.getJSONObject(i);
      html += "<tr>" + "<td>" + layerJSON.getString("name") + "</td>"
        + "<td>" + "<b>Type:</b> " + layerJSON.getString("type")
        + "<br>" + "<b>ID:</b>" + layerJSON.getString("id")
        + "<br>" + "<b>Description:</b>"
        + layerJSON.getString("description") + "</td>" + "</tr>";
  }

  html += "</table>";

  return html;
    }

    /**
     * Returns JSON representation of specified resource.
     * 
     * @return String JSON representation of specified resource.
     */
    private byte[] getResource(String resourceName, Map<String, String> responsePropertiesMap) throws Exception {
  if (resourceName.equalsIgnoreCase("") || resourceName.length() == 0) {
      return getRootResource();
  } else if (resourceName.equalsIgnoreCase("layers")) {
      return getSubresourceLayers(responsePropertiesMap);
  } else if (resourceName.equalsIgnoreCase("properties")) {
      return getSubresourceProperties(responsePropertiesMap);
  }

  return null;
    }

    /*************************************************************************************
     * IRESTRequestHandler methods:
     *************************************************************************************/
    /**
     * This method handles REST requests by determining whether an operation or
     * resource has been invoked and then forwards the request to appropriate
     * methods.
     */
    @Override
    public byte[] handleRESTRequest(String capabilities, String resourceName,
      String operationName, String operationInput, String outputFormat,
      String requestProperties, String[] responseProperties)
      throws IOException, AutomationException {

  Map<String, String> responsePropertiesMap = new HashMap<String, String>();
  try {
      // if no operationName is specified send description of specified
      // resource
      byte[] response = null;      
      if (operationName.length() == 0) {
    response = getResource(resourceName, responsePropertiesMap);
      } else {
    response = ServerUtilities.sendError(1,
      "No operations defined for this SOE",
      new String[] { "No details specified." })
      .getBytes("utf-8");
      }
      
      //collect response properties that may have changed in subresources or operations
      JSONObject responsePropertiesJSON = new JSONObject(responsePropertiesMap);
      responseProperties[0] = responsePropertiesJSON.toString();
    
      return response;
  } catch (Exception e) {
      this.serverLog.addMessage(1, 500, e.getMessage());
      return ServerUtilities.sendError(1,
        "Exception occurred: " + e.getMessage(),
        new String[] { "No details specified." }).getBytes(
        "utf-8");
  }
    }

    /**
     * This method returns the resource hierarchy of a REST based SOE in JSON
     * format.
     */
    public String getSchema() throws IOException, AutomationException {
  try {
      JSONObject _SimpleRESTSOEWithProperties = ServerUtilities
        .createResource("JavaSimpleRESTSOEWithProperties",
          "JavaSimpleRESTSOEWithProperties description",
          false, false);
      JSONArray _SimpleRESTSOEWithProperties_SubResourceArray = new JSONArray();
      JSONObject _layers = ServerUtilities.createResource("layers",
        "layers description", false, false);
      JSONObject _properties = ServerUtilities.createResource(
        "properties", "properties and their current values", false,
        false);
      _SimpleRESTSOEWithProperties_SubResourceArray.put(_layers);
      _SimpleRESTSOEWithProperties_SubResourceArray.put(_properties);
      _SimpleRESTSOEWithProperties.put("resources",
        _SimpleRESTSOEWithProperties_SubResourceArray);
      return _SimpleRESTSOEWithProperties.toString();
  } catch (JSONException e) {
      e.printStackTrace();
  }
  return null;
    }
}