com.esri.gpt.server.openls.provider.services.poi.DirectoryProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.gpt.server.openls.provider.services.poi.DirectoryProvider.java

Source

/* See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Esri Inc. licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.esri.gpt.server.openls.provider.services.poi;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.esri.gpt.server.csw.provider.components.OwsException;
import com.esri.gpt.server.openls.provider.components.IOperationProvider;
import com.esri.gpt.server.openls.provider.components.IProviderFactory;
import com.esri.gpt.server.openls.provider.components.IResponseGenerator;
import com.esri.gpt.server.openls.provider.components.OperationContext;
import com.esri.gpt.server.openls.provider.util.DistanceCalc;
import com.esri.gpt.server.openls.provider.util.Point;
import com.esri.gpt.server.openls.provider.util.Units;

/**
 * Provides the Openls Directory operation.
 */
public class DirectoryProvider implements IOperationProvider {

    /** class variables ========================================================= */

    /** The Logger. */
    private static Logger LOGGER = Logger.getLogger(DirectoryProvider.class.getName());

    /** constructors ============================================================ */

    /** Default constructor */
    public DirectoryProvider() {
        super();
    }

    /** methods ================================================================= */

    /**
     * Executes a parsed operation request.
     * @param context the operation context
     * @throws Exception if a processing exception occurs
     */
    private void generateResponse(OperationContext context) throws Exception {

        // initialize
        LOGGER.finer("Executing xls:Directory request...");
        IProviderFactory factory = context.getProviderFactory();

        // generate the response
        IResponseGenerator generator = factory.makeResponseGenerator(context);
        if (generator == null) {
            String msg = "IProviderFactory.makeResponseGenerator: instantiation failed.";
            LOGGER.log(Level.SEVERE, msg);
            throw new OwsException(msg);
        } else {
            generator.generateResponse(context);
        }
    }

    /**
     * Handles a URL based request (HTTP GET).
     * @param context the operation context
     * @param request the HTTP request
     * @throws Exception if a processing exception occurs
     */
    public void handleGet(OperationContext context, HttpServletRequest request) throws Exception {

    }

    /**
     * Handles an XML based request (normally HTTP POST).
     * @param context the operation context
     * @param root the root node
     * @param xpath an XPath to enable queries (properly configured with name spaces)
     * @throws Exception if a processing exception occurs
     */
    public void handleXML(OperationContext context, Node root, XPath xpath) throws Exception {

        // initialize
        LOGGER.finer("Handling xls:Directory request XML...");
        String locator = "xls:DirectoryRequest";
        Node ndReq = (Node) xpath.evaluate(locator, root, XPathConstants.NODE);
        if (ndReq != null) {
            parseRequest(context, ndReq, xpath);
        }
        try {
            executeRequest(context);
        } catch (Throwable e) {
            e.printStackTrace();
        }

        generateResponse(context);
    }

    /**
     * Parse directory request
     * @param context
     * @param ndReq
     * @param xpath
     * @throws XPathExpressionException
     */
    private void parseRequest(OperationContext context, Node ndReq, XPath xpath) throws XPathExpressionException {
        DirectoryParams params = context.getRequestOptions().getDirectoryOptions();
        HashMap<String, String> poiProperties = null;
        HashMap<String, Object> poiLocations = null;

        Node ndPoiLoc = (Node) xpath.evaluate("xls:POILocation", ndReq, XPathConstants.NODE);
        if (ndPoiLoc != null) {
            poiLocations = new HashMap<String, Object>();
            Node ndPos = (Node) xpath.evaluate("xls:Nearest/xls:Position/gml:Point/gml:pos", ndPoiLoc,
                    XPathConstants.NODE);
            if (ndPos != null) {
                String[] xy = ndPos.getTextContent().split(" ");
                Point loc = new Point(xy[0], xy[1]);
                poiLocations.put("nearest", loc);
            }
            @SuppressWarnings("unused")
            Node ndWDAL = (Node) xpath.evaluate("xls:WithinDistance/xls:POI/xls:POIAttributeList/xls:POIInfoList",
                    ndPoiLoc, XPathConstants.NODE);
            String maxDist = (String) xpath.evaluate("xls:WithinDistance/xls:MaximumDistance/@value", ndPoiLoc,
                    XPathConstants.STRING);
            if (maxDist != null) {
                poiLocations.put("withinDistance", maxDist);
            }

        }
        Node ndPoiProp = (Node) xpath.evaluate("xls:POIProperties", ndReq, XPathConstants.NODE);
        if (ndPoiProp != null) {
            NodeList nlProp = (NodeList) xpath.evaluate("xls:POIProperty", ndPoiProp, XPathConstants.NODESET);
            if (nlProp != null) {
                for (int j = 0; j < nlProp.getLength(); j++) {
                    Node ndProp = nlProp.item(j);
                    poiProperties = new HashMap<String, String>();
                    String name = (String) xpath.evaluate("@name", ndProp, XPathConstants.STRING);
                    String param = context.getRequestContext().getApplicationConfiguration()
                            .getCatalogConfiguration().getParameters().getValue(name);
                    String value = (String) xpath.evaluate("@value", ndProp, XPathConstants.STRING);
                    poiProperties.put(param, value);
                }
            }
        }
        params.setPoiLocations(poiLocations);
        params.setPoiProperties(poiProperties);
    }

    /**
     * Executes directory request
     * @param context
     * @throws java.lang.Throwable
     */
    private void executeRequest(OperationContext context) throws java.lang.Throwable {

        long t1 = System.currentTimeMillis();
        DirectoryParams params = context.getRequestOptions().getDirectoryOptions();

        try {

            String srvCfg = context.getRequestContext().getApplicationConfiguration().getCatalogConfiguration()
                    .getParameters().getValue("openls.directory");

            // HashMap<String,Point> poiLocations = params.getPoiLocations(); 

            // TODO
            /*Point location = null;
            Set<String> keys = poiLocations.keySet();
             Iterator<String> iter = keys.iterator();
             while(iter.hasNext()){
                String key = iter.next();
                location = (Point) poiLocations.get(key);
             }*/

            // MAKE THE POI REQUEST
            HashMap<String, String> poiProperties = params.getPoiProperties();
            Set<String> keys = poiProperties.keySet();
            Iterator<String> iter = keys.iterator();
            StringBuffer filter = new StringBuffer();
            while (iter.hasNext()) {
                String key = iter.next();
                QueryFilter queryFilter = new QueryFilter(key, poiProperties.get(key));
                filter.append(makePOIRequest(queryFilter));
            }

            // SUBMIT THE REQUEST
            String sUrl = srvCfg + "/query?" + filter.toString();
            LOGGER.info("REQUEST=\n" + sUrl);

            URL url = new URL(sUrl);
            URLConnection conn = url.openConnection();

            // Get the response
            String line = "";
            String sResponse = "";

            InputStream is = conn.getInputStream();

            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader rd = new BufferedReader(isr);
            while ((line = rd.readLine()) != null) {
                sResponse += line;
            }
            rd.close();
            url = null;

            parsePOIResponse(sResponse, params);

        } catch (Exception p_e) {
            LOGGER.severe("Throwing exception" + p_e.getMessage());
            throw p_e;
        } finally {
            long t2 = System.currentTimeMillis();
            LOGGER.info("PERFORMANCE: " + (t2 - t1) + " ms spent performing service");
        }
    }

    /* http://trainingcloud.arcgis.com/ArcGIS/rest/services/
     * Redlands_PointsOfInterest/MapServer/0/query?
     * text=&geometry=&geometryType
     * =esriGeometryPoint&inSR=&spatialRel=esriSpatialRelIntersects
     * &relationParam=& objectIds=&where=TYPE%3D
     * 'Bank'&time=&returnIdsOnly=false&returnGeometry=true&maxAllowableOffset=&outSR=&
     * outFields=name,match_addr,type,desc_,source,distance,objectid& f=pjson
     */
    private String makePOIRequest(QueryFilter qfilters) throws UnsupportedEncodingException {

        StringBuffer params = new StringBuffer();
        params.append("text=&geometry=&geometryType=esriGeometryPoint&inSR=&spatialRel=esriSpatialRelIntersects")
                .append("&relationParam=&objectIds=&time=&returnIdsOnly=false&returnGeometry=true&maxAllowableOffset=&outSR=&outFields=name,match_addr,type,desc_,source,distance,objectid&f=json");

        String whereClause = null;
        if (qfilters != null) {
            String[] temp = qfilters.toString().split("=");
            if (temp != null && temp.length >= 2) {
                whereClause = temp[0].trim() + "=" + java.net.URLEncoder.encode(temp[1].trim());
            }
        }
        /*for (int i = 1; i < qfilters.size(); i++) {
           QueryFilter queryFilter = (QueryFilter) qfilters.get(i);
           String[] temp = queryFilter.toString().split("=");
           if(temp != null && temp.length >=2){
        whereClause = temp[0].trim() + "=" + temp[1].trim();
           }
           whereClause += " AND " + temp[0].trim() + "=" + temp[1].trim();
        }*/

        params.append("&where=").append(whereClause);

        return params.toString();
    }

    /**
     * Parses directory request response
     * @param sResponse
     * @param params
     * @throws JSONException
     */
    private void parsePOIResponse(String sResponse, DirectoryParams params) throws JSONException {

        JSONObject jResponse = new JSONObject(sResponse);

        String xResponse = "<?xml version='1.0'?><response>" + org.json.XML.toString(jResponse) + "</response>";
        LOGGER.info("XML from JSON = " + xResponse);
        HashMap<String, Object> poiLocations = null;
        try {
            /*JSONObject fieldAliases = jResponse.getJSONObject("fieldAliases");
            ArrayList<String> fieldNames = new ArrayList<String>();
            Iterator<String> names = fieldAliases.keys();
            while(names.hasNext()){
               fieldNames.add(names.next());
            }*/
            JSONArray fields = null;
            try {
                fields = jResponse.getJSONArray("fields");
            } catch (JSONException e) {
                throw new OwsException("Error occured while processing request.");
            }
            if (fields == null) {
                return;
            }
            JSONArray pois = jResponse.getJSONArray("features");

            double X, Y, distance;
            ArrayList<POIContext> poiContexts = new ArrayList<POIContext>();
            for (int i = 0; i < pois.length(); i++) {

                JSONObject poi = pois.getJSONObject(i);
                JSONObject attrs = poi.getJSONObject("attributes");

                POIContext poiCtx = new POIContext();
                POI poiObj = new POI();

                POIInfoList poiInfoList = new POIInfoList();
                for (int k = 0; k < fields.length(); k++) {
                    JSONObject fieldInfo = fields.getJSONObject(k);
                    String field = fieldInfo.getString("name");
                    String value = attrs.getString(field);
                    POIInfo poiInfo = new POIInfo();
                    if (field.equalsIgnoreCase("name")) {
                        poiObj.setPoiName(value);
                    } else if (field.equalsIgnoreCase("objectid")) {
                        poiObj.setId(value);
                    }
                    poiInfo.setName(field);
                    poiInfo.setValue(value);
                    poiInfoList.add(poiInfo);
                }
                poiObj.setPoiAttributeList(poiInfoList);
                JSONObject geom = poi.getJSONObject("geometry");
                Point pt = null;
                if (geom != null) {
                    X = Double.parseDouble(geom.getString("x"));
                    Y = Double.parseDouble(geom.getString("y"));
                    pt = new Point(X, Y);
                    poiObj.setLocation(pt);
                }

                poiLocations = params.getPoiLocations();
                Point location = null;
                if (poiLocations != null) {
                    Set<String> keys = poiLocations.keySet();
                    Iterator<String> iter = keys.iterator();
                    while (iter.hasNext()) {
                        String key = iter.next();
                        if (key == "nearest") {
                            location = (Point) poiLocations.get(key);
                        }
                    }
                }

                if (location != null) {
                    distance = DistanceCalc.getApproxMeters(location, pt);

                    double dist_miles = Math.round(((Units.convert(distance, 5, 4)) * 10));

                    double distance_display = dist_miles / 10;

                    poiCtx.setDistance(distance_display);
                }

                poiCtx.setPoint(poiObj);

                poiContexts.add(poiCtx);
            }
            if (poiContexts.size() > 1) {
                Collections.sort(poiContexts);
                if (poiLocations.containsKey("nearest")) {
                    for (int k = poiContexts.size() - 1; k > 0; k--) {
                        poiContexts.remove(k);
                    }
                } else if (poiLocations.containsKey("withinDistance")) {
                    double dist = Double.parseDouble((String) poiLocations.get("withinDistance"));
                    for (int k = poiContexts.size() - 1; k > 0; k--) {
                        if (poiContexts.get(k).getDistance() > dist) {
                            poiContexts.remove(k);
                        }
                    }
                }
            }
            params.setPoiContexts(poiContexts);

        } catch (Exception e) {
            LOGGER.severe("Caught Exception" + e.getMessage());
            e.printStackTrace();
        }
    }
}