com.esri.geoevent.solutions.processor.queryreport.QueryReportProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.geoevent.solutions.processor.queryreport.QueryReportProcessor.java

Source

package com.esri.geoevent.solutions.processor.queryreport;

/*
 * #%L
 * Esri :: AGES :: Solutions :: Processor :: Geometry
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2013 - 2014 Esri
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.TypeReference;
import org.joda.time.DateTime;

import com.esri.core.geometry.Envelope;
import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.GeometryEngine;
import com.esri.core.geometry.LinearUnit;
import com.esri.core.geometry.MapGeometry;
import com.esri.core.geometry.MultiPath;
import com.esri.core.geometry.Point;
import com.esri.core.geometry.Polygon;
import com.esri.core.geometry.Polyline;
import com.esri.core.geometry.Segment;
import com.esri.core.geometry.SpatialReference;
import com.esri.core.geometry.Unit;
import com.esri.ges.core.component.ComponentException;
import com.esri.ges.core.geoevent.DefaultFieldDefinition;
import com.esri.ges.core.geoevent.FieldDefinition;
import com.esri.ges.core.geoevent.FieldType;
import com.esri.ges.core.geoevent.GeoEvent;
import com.esri.ges.core.geoevent.GeoEventDefinition;
import com.esri.ges.core.geoevent.GeoEventPropertyName;
import com.esri.ges.core.validation.ValidationException;
import com.esri.ges.manager.datastore.agsconnection.ArcGISServerConnection;
import com.esri.ges.manager.datastore.agsconnection.ArcGISServerType;
import com.esri.ges.manager.datastore.agsconnection.Field;
import com.esri.ges.manager.datastore.agsconnection.Layer;
import com.esri.ges.manager.datastore.agsconnection.ArcGISServerConnectionManager;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.messaging.GeoEventCreator;
import com.esri.ges.messaging.Messaging;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;

public class QueryReportProcessor extends GeoEventProcessorBase {
    //private enum SortType {Name, Distance};
    //public SortType currentSort = SortType.Name;
    private static final Log LOG = LogFactory.getLog(QueryReportProcessor.class);
    private Tokenizer tokenizer = new Tokenizer();
    private Map<String, String> eventTokenMap = new HashMap<String, String>();
    public GeoEventDefinitionManager manager;
    public ArcGISServerConnectionManager connectionManager;
    public Messaging messaging;
    private SpatialReference srIn;
    private SpatialReference srBuffer;
    private SpatialReference srOut;
    private double radius;
    private String units;
    private int inwkid;
    private int outwkid;
    private int bufferwkid;
    private String geoSrc;
    private Boolean useCentroid;
    private String eventfld;
    private Boolean useTimeStamp;
    private String file;
    private String host;
    String outDefName;
    String connName;
    private ArcGISServerConnection conn;
    private String folder;
    private String service;
    private String lyrName;
    private Layer layer;
    private String layerId;
    private String field;
    //Field[] fields;
    private Boolean calcDist;
    private String wc;
    private String lyrHeaderCfg;
    private String distToken = "";
    private Boolean sortByDist;
    private String distUnits = "";
    //String token;
    private String sortField;
    private String itemConfig;
    private String title;
    private String header;
    private com.esri.core.geometry.Geometry inGeometry;
    private GeoEvent currentEvent = null;
    private String ts;
    private String time;
    private String endpoint = null;
    private String token;

    public QueryReportProcessor(GeoEventProcessorDefinition definition, GeoEventDefinitionManager m,
            ArcGISServerConnectionManager cm, Messaging msg) throws ComponentException {
        super(definition);
        manager = m;
        connectionManager = cm;
        messaging = msg;
        geoEventMutator = true;
    }

    @Override
    public void shutdown() {
        // Destruction Phase
        super.shutdown();
    }

    @Override
    public boolean isGeoEventMutator() {
        return true;
    }

    @Override
    public void afterPropertiesSet() {
        radius = (Double) properties.get("radius").getValue();
        units = properties.get("units").getValue().toString();
        //inwkid = (Integer) properties.get("wkidin").getValue();
        outwkid = (Integer) properties.get("wkidout").getValue();
        bufferwkid = (Integer) properties.get("wkidbuffer").getValue();
        geoSrc = properties.get("geosrc").getValueAsString();
        useCentroid = (Boolean) properties.get("usecentroid").getValue();
        eventfld = properties.get("geoeventdef").getValue().toString();
        useTimeStamp = (Boolean) properties.get("usetimestamp").getValue();

        DateTime dt = DateTime.now();
        ts = ((Integer) dt.getYear()).toString() + ((Integer) dt.getMonthOfYear()).toString()
                + ((Integer) dt.getDayOfMonth()).toString() + ((Integer) dt.getHourOfDay()).toString()
                + ((Integer) dt.getMinuteOfHour()).toString() + ((Integer) dt.getSecondOfMinute()).toString();
        time = ((Integer) dt.getYear()).toString() + "/" + ((Integer) dt.getMonthOfYear()).toString() + "/"
                + ((Integer) dt.getDayOfMonth()).toString() + " " + ((Integer) dt.getHourOfDay()).toString() + ":"
                + ((Integer) dt.getMinuteOfHour()).toString() + ":" + ((Integer) dt.getSecondOfMinute()).toString();
        file = properties.get("filename").getValueAsString() + ts + ".html";
        host = properties.get("host").getValueAsString();
        outDefName = properties.get("gedname").getValueAsString();
        connName = properties.get("connection").getValueAsString();
        folder = properties.get("folder").getValueAsString();
        service = properties.get("service").getValueAsString();
        lyrName = properties.get("layer").getValueAsString();
        try {
            conn = connectionManager.getArcGISServerConnection(connName);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            ValidationException ve = new ValidationException("Unable to make connection to ArcGIS Server");
            LOG.error(ve.getMessage());
            try {
                throw ve;
            } catch (ValidationException e1) {

                e1.printStackTrace();
            }
        }
        layer = conn.getLayer(folder, service, lyrName, ArcGISServerType.FeatureServer);
        layerId = ((Integer) layer.getId()).toString();
        field = properties.get("field").getValueAsString();
        sortField = properties.get("sortfield").getValueAsString();
        if (!properties.get("endpoint").getValueAsString().isEmpty()) {
            endpoint = properties.get("endpoint").getValueAsString();
        }
        try {
            token = conn.getDecryptedToken();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //fields = conn.getFields(folder, service, layer.getId(), ArcGISServerType.FeatureServer);
        calcDist = (Boolean) properties.get("calcDistance").getValue();
        wc = properties.get("wc").getValueAsString();
        lyrHeaderCfg = properties.get("lyrheader").getValueAsString();
        sortByDist = false;
        if (calcDist) {
            sortByDist = (Boolean) properties.get("sortdist").getValue();
            distToken = "${distance.value}";
            distUnits = properties.get("dist_units").getValueAsString();
        }
        //token = properties.get("field-token").getValueAsString();
        itemConfig = properties.get("item-config").getValueAsString();
        title = properties.get("title").getValueAsString();
        Object objHeader = properties.get("header");
        header = null;
        if (objHeader != null) {
            header = properties.get("header").getValueAsString();
        }
    }

    @Override
    public synchronized void validate() throws ValidationException {
        if (radius <= 0) {
            ValidationException ve = new ValidationException("Radius cannot be less than or equal to 0");
            LOG.error(ve.getMessage());
            throw ve;
        }

        try {
            srBuffer = SpatialReference.create(bufferwkid);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            ValidationException ve = new ValidationException("Invalid wkid");
            LOG.error(ve.getMessage());
            throw ve;
        }
        try {
            srOut = SpatialReference.create(outwkid);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            ValidationException ve = new ValidationException("Invalid wkid");
            LOG.error(ve.getMessage());
            throw ve;
        }

    }

    @Override
    public GeoEvent process(GeoEvent ge) throws Exception {
        //CreateQueryMap();
        if (!ge.getGeoEventDefinition().getTagNames().contains("GEOMETRY")) {
            return null;
        }
        srIn = ge.getGeometry().getSpatialReference();
        inwkid = srIn.getID();
        currentEvent = ge;
        List<FieldDefinition> fldDefs = ge.getGeoEventDefinition().getFieldDefinitions();
        for (FieldDefinition fd : fldDefs) {
            if (fd.getType() != FieldType.Geometry && fd.getType() != FieldType.Group) {
                String n = fd.getName();
                String tk = tokenizer.tokenize("geoevent." + n);
                eventTokenMap.put(tk, n);
            }

        }
        ArrayList<Object> queries = CreateQueries();

        MapGeometry geo = ge.getGeometry();
        MapGeometry inGeo = null;
        if (geoSrc.equals("Buffer")) {

            Geometry rtGeo = constructGeometry(geo);
            if (useCentroid) {
                if (geo.getGeometry().getType() == Geometry.Type.Point) {
                    inGeometry = rtGeo;
                } else {
                    Envelope env = new Envelope();
                    rtGeo.queryEnvelope(env);
                    inGeometry = env.getCenter();
                }
            } else {
                inGeometry = constructGeometry(geo);
            }

            Unit u = queryUnit(units);
            inGeo = constructBuffer(geo.getGeometry(), radius, u);
        } else if (geoSrc.equals("Event_Definition")) {
            String geostr = (String) ge.getField(eventfld);
            MapGeometry g = constructGeometryFromString(geostr);
            Geometry polyGeo = constructGeometry(g);
            if (useCentroid) {
                Envelope env = new Envelope();
                polyGeo.queryEnvelope(env);
                inGeometry = env.getCenter();
            } else {
                inGeometry = polyGeo;
            }
            com.esri.core.geometry.Geometry projGeo = GeometryEngine.project(polyGeo, srBuffer, srOut);
            inGeo = new MapGeometry(projGeo, srOut);
            //String json = GeometryEngine.geometryToJson(srOut, projGeo);
        } else {

            Geometry polyGeo = constructGeometry(geo);
            if (useCentroid) {
                Envelope env = new Envelope();
                polyGeo.queryEnvelope(env);
                inGeometry = env.getCenter();
            } else {
                inGeometry = polyGeo;
            }
            com.esri.core.geometry.Geometry projGeo = GeometryEngine.project(polyGeo, srBuffer, srOut);
            //String json = GeometryEngine.geometryToJson(srOut, projGeo);
            inGeo = new MapGeometry(projGeo, srOut);

        }
        Geometry newGeo = inGeo.getGeometry();
        String jsonGeo = GeometryEngine.geometryToJson(srOut.getID(), newGeo);
        String geotype = GeometryUtility.parseGeometryType(newGeo.getType());
        HashMap<String, Object> responseMap = ExecuteRestQueries(jsonGeo, geotype, queries);
        String timestamp = "";
        if (useTimeStamp) {
            timestamp = time;
        }

        ParseResponses(timestamp, file, responseMap);

        if (host.contains("http://")) {
            host.replace("http://", "");
        }
        if (host.contains(":6180")) {
            host.replace(":6180", "");
        }
        String url = "http://" + host + ":6180/geoevent/assets/reports/" + file;
        GeoEventDefinition geoDef = ge.getGeoEventDefinition();

        GeoEventDefinition edOut;
        if ((edOut = manager.searchGeoEventDefinition(outDefName, getId())) == null) {
            List<FieldDefinition> fds = Arrays
                    .asList(((FieldDefinition) new DefaultFieldDefinition("url", FieldType.String)));
            edOut = geoDef.augment(fds);
            edOut.setOwner(getId());
            edOut.setName(outDefName);
            manager.addGeoEventDefinition(edOut);
        }
        GeoEventCreator geoEventCreator = messaging.createGeoEventCreator();
        GeoEvent geOut = geoEventCreator.create(edOut.getGuid(), new Object[] { ge.getAllFields(), url });
        geOut.setProperty(GeoEventPropertyName.TYPE, "message");
        geOut.setProperty(GeoEventPropertyName.OWNER_ID, getId());
        geOut.setProperty(GeoEventPropertyName.OWNER_ID, definition.getUri());

        for (Map.Entry<GeoEventPropertyName, Object> property : ge.getProperties())
            if (!geOut.hasProperty(property.getKey()))
                geOut.setProperty(property.getKey(), property.getValue());
        //queries.clear();
        //responseMap.clear();
        return geOut;

    }

    private Unit queryUnit(String units) {
        UnitConverter uc = new UnitConverter();
        String cn = uc.findConnonicalName(units);
        int unitout = uc.findWkid(cn);
        Unit u = LinearUnit.create(unitout);
        return u;
    }

    private Geometry constructGeometry(MapGeometry geo) throws Exception {
        try {

            Geometry geoIn = geo.getGeometry();
            return GeometryEngine.project(geoIn, srIn, srBuffer);
        } catch (Exception e) {
            LOG.error(e.getMessage());
            LOG.error(e.getStackTrace());
            throw (e);
        }
    }

    private MapGeometry constructGeometryFromString(String geoString) {
        String[] pairs = geoString.split(" ");

        Polygon polygon = new Polygon();
        Boolean firstit = true;
        for (String coords : pairs) {

            String[] tuple = coords.split(",");
            Double x = Double.parseDouble(tuple[0]);
            Double y = Double.parseDouble(tuple[1]);
            Point p = new Point(x, y);
            Double z = Double.NaN;
            if (tuple.length > 2) {
                z = Double.parseDouble(tuple[2]);
                p.setZ(z);
            }
            if (firstit) {
                polygon.startPath(p);
                firstit = false;
            } else {
                polygon.lineTo(p);
            }
        }
        polygon.closeAllPaths();
        MapGeometry mapgeo = new MapGeometry(polygon, srOut);
        return mapgeo;
    }

    private MapGeometry constructBuffer(Geometry geo, double radius, Unit u)
            throws JsonParseException, IOException {

        Polygon buffer = GeometryEngine.buffer(inGeometry, srBuffer, radius, u);
        Geometry bufferout = GeometryEngine.project(buffer, srBuffer, srOut);
        MapGeometry mapGeo = new MapGeometry(bufferout, srOut);
        return mapGeo;
        //String json = GeometryEngine.geometryToJson(srOut, bufferout);
        //return spatial.fromJson(json);

    }

    public ArrayList<Object> CreateQueries() {
        ArrayList<Object> queries = new ArrayList<Object>();
        URL url = conn.getUrl();
        String curPath = null;
        if (endpoint != null) {
            curPath = endpoint;
        } else {
            String baseUrl = url.getProtocol() + "://" + url.getHost() + ":" + url.getPort() + url.getPath()
                    + "rest/services/";
            curPath = baseUrl + "/" + folder + "/" + service + "/FeatureServer/" + layerId;
        }
        String restpath = curPath + "/query?";
        HashMap<String, Object> query = new HashMap<String, Object>();
        HashMap<String, String> fieldMap = new HashMap<String, String>();

        String fldsString = field;
        String[] fieldArray = fldsString.split(",");
        for (String f : fieldArray) {
            String tk = tokenizer.tokenize(f);
            fieldMap.put(f, tk);
        }

        query.put("restpath", restpath);
        query.put("path", curPath);
        query.put("whereclause", wc);
        query.put("fields", fldsString);
        //query.put("outfields", fields);
        query.put("tokenMap", fieldMap);
        query.put("headerconfig", lyrHeaderCfg);
        query.put("usingdist", calcDist);
        query.put("sortbydist", sortByDist);
        query.put("distunits", distUnits);
        query.put("disttoken", distToken);
        query.put("itemconfig", itemConfig);
        query.put("layer", layer.getName());
        UUID uid = UUID.randomUUID();
        query.put("id", uid);
        queries.add(query);
        return queries;
    }

    private HashMap<String, Object> ExecuteRestQueries(String jsonGeometry, String geoType,
            ArrayList<Object> queries) throws UnsupportedEncodingException {
        String contentType = "application/json";
        HttpClient httpclient = HttpClientBuilder.create().build();
        HashMap<String, Object> responseMap = new HashMap<String, Object>();
        for (int i = 0; i < queries.size(); ++i) {
            @SuppressWarnings("unchecked")
            HashMap<String, Object> query = (HashMap<String, Object>) queries.get(i);
            String path = (String) query.get("restpath");
            String wc = URLEncoder.encode((String) query.get("whereclause"), "UTF-8");
            String geo = URLEncoder.encode(jsonGeometry, "UTF-8");
            String fields = (String) query.get("fields");
            @SuppressWarnings("unchecked")
            HashMap<String, String> tokenMap = (HashMap<String, String>) query.get("tokenMap");
            String itemConfig = (String) query.get("itemconfig");
            //
            String args = "where=" + wc + "&objectIds=&time=&geometry=" + geo + "&geometryType=" + geoType
                    + "&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=*"
                    //+ fields
                    + "&returnGeometry=true&maxAllowableOffset=&geometryPrecision=&outSR=&gdbVersion=&returnDistinctValues=false&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&f=json";
            if (token != null) {
                args += "&token=" + token;
            }
            String uri = path + args;
            try {
                HttpPost httppost = new HttpPost(uri);
                httppost.setHeader("Accept", contentType);
                HttpResponse response = httpclient.execute(httppost);

                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream instream = entity.getContent();
                    try {
                        // instream.read();
                        BufferedReader br = new BufferedReader(new InputStreamReader((instream)));
                        String output = "";
                        String ln;
                        while ((ln = br.readLine()) != null) {
                            output += ln;
                        }
                        //JsonFactory jf = new JsonFactory();
                        //JsonParser jp = jf.createJsonParser(output);
                        //FeatureSet fset = FeatureSet.fromJson(jp);
                        Map<String, Object> map = new HashMap<String, Object>();
                        ObjectMapper mapper = new ObjectMapper();
                        map = mapper.readValue(output, new TypeReference<HashMap<String, Object>>() {
                        });
                        HashMap<String, Object> tuple = new HashMap<String, Object>();
                        String lyr = (String) query.get("layer");
                        String lyrheadercfg = (String) query.get("headerconfig");
                        Boolean calcdist = (Boolean) query.get("usingdist");
                        Boolean sortByDist = (Boolean) query.get("sortbydist");
                        String distToken = (String) query.get("disttoken");
                        String distUnits = (String) query.get("distunits");
                        String id = query.get("id").toString();
                        tuple.put("fset", map);
                        tuple.put("tokenmap", tokenMap);
                        tuple.put("config", itemConfig);
                        tuple.put("layer", lyr);
                        tuple.put("lyrheader", lyrheadercfg);
                        tuple.put("sortbydist", sortByDist);
                        tuple.put("calcdist", calcdist);
                        tuple.put("distunits", distUnits);
                        tuple.put("disttoken", distToken);
                        responseMap.put(id, tuple);

                    } catch (IOException ex) {
                        // In case of an IOException the connection will be
                        // released
                        // back to the connection manager automatically
                        LOG.error(ex);
                        throw ex;
                    } catch (RuntimeException ex) {
                        // In case of an unexpected exception you may want to
                        // abort
                        // the HTTP request in order to shut down the underlying
                        // connection immediately.
                        LOG.error(ex);
                        httppost.abort();
                        throw ex;
                    } catch (Exception ex) {

                        LOG.error(ex);
                        httppost.abort();
                        throw ex;
                    } finally {
                        // Closing the input stream will trigger connection
                        // release
                        try {
                            instream.close();
                        } catch (Exception ignore) {
                        }
                    }
                }

            } catch (Exception ex) {
                LOG.error(ex);
                ex.printStackTrace();
            }

        }
        return responseMap;
    }

    private Geometry generateGeoFromMap(Map<String, Object> objGeo) {
        Geometry geo = null;
        if (objGeo.containsKey("rings")) {
            ArrayList<ArrayList<ArrayList<String>>> rings = (ArrayList<ArrayList<ArrayList<String>>>) objGeo
                    .get("rings");
            geo = generatePolygon(rings);
        } else if (objGeo.containsKey("paths")) {
            ArrayList<ArrayList<ArrayList<String>>> paths = (ArrayList<ArrayList<ArrayList<String>>>) objGeo
                    .get("paths");
            geo = generatePolyLine(paths);
        } else if (objGeo.containsKey("points")) {

        } else {
            Double x = Double.valueOf(objGeo.get("x").toString());
            Double y = Double.valueOf(objGeo.get("y").toString());
            if (objGeo.size() > 2) {
                Double z = Double.valueOf(objGeo.get("z").toString());
                geo = generate3DPoint(x, y, z);
            } else {
                geo = generatePoint(x, y);
            }
        }
        return geo;
    }

    private Point generatePoint(Double x, Double y) {
        Point p = new Point(x, y);
        return p;
    }

    private Point generate3DPoint(Double x, Double y, Double z) {
        Point p = new Point(x, y, z);
        return p;
    }

    private Polyline generatePolyLine(ArrayList<ArrayList<ArrayList<String>>> paths) {
        Polyline polyln = new Polyline();
        for (ArrayList<ArrayList<String>> path : paths) {
            Boolean firstPt = true;
            for (ArrayList<String> strPt : path) {
                Point p = null;
                if (strPt.size() > 2) {
                    Double x = Double.valueOf(strPt.get(0));
                    Double y = Double.valueOf(strPt.get(1));
                    Double z = Double.valueOf(strPt.get(2));
                    p = generate3DPoint(x, y, z);
                } else {
                    Double x = Double.valueOf(strPt.get(0));
                    Double y = Double.valueOf(strPt.get(1));
                    p = generatePoint(x, y);
                }
                if (firstPt) {
                    polyln.startPath(p);
                    firstPt = false;
                } else {
                    polyln.lineTo(p);
                }
            }
        }
        return polyln;
    }

    private Polygon generatePolygon(ArrayList<ArrayList<ArrayList<String>>> paths) {
        Polygon polygon = new Polygon();
        for (ArrayList<ArrayList<String>> path : paths) {
            Boolean firstPt = true;
            for (ArrayList<String> strPt : path) {
                Point p = null;
                if (strPt.size() > 2) {
                    Double x = Double.valueOf(strPt.get(0));
                    Double y = Double.valueOf(strPt.get(1));
                    Double z = Double.valueOf(strPt.get(2));
                    p = generate3DPoint(x, y, z);
                } else {
                    Double x = Double.valueOf(strPt.get(0));
                    Double y = Double.valueOf(strPt.get(1));
                    p = generatePoint(x, y);
                }
                if (firstPt) {
                    polygon.startPath(p);
                    firstPt = false;
                } else {
                    polygon.lineTo(p);
                }
            }
        }
        polygon.closeAllPaths();
        return polygon;
    }

    private String GetDistAsString(Map<String, Object> objGeo, SpatialReference inputSr, String units)
            throws JsonParseException, IOException {
        Geometry geo = generateGeoFromMap(objGeo);
        com.esri.core.geometry.Geometry curGeo;

        if (!inputSr.equals(srBuffer)) {
            curGeo = GeometryEngine.project(geo, inputSr, srBuffer);
        } else {
            curGeo = geo;
        }
        double tmpDist = GeometryEngine.distance(inGeometry, curGeo, srBuffer);
        UnitConverter uc = new UnitConverter();
        int inUnitWkid = uc.findWkid(srBuffer.getUnit().getName());
        String cn = uc.findConnonicalName(units);
        int outUnitWkid = uc.findWkid(cn);
        double dist;
        if (inUnitWkid != outUnitWkid) {
            dist = uc.Convert(tmpDist, inUnitWkid, outUnitWkid);
        } else {
            dist = tmpDist;
        }

        DecimalFormat df = new DecimalFormat("#.00");
        return df.format(dist);
    }

    private void ParseResponses(String timestamp, String file, HashMap<String, Object> responseMap)
            throws JsonParseException, IOException {
        Map<String, List<String>> nameSortMap = new HashMap<String, List<String>>();
        Map<Double, List<String>> distSortMap = new HashMap<Double, List<String>>();
        ArrayList<String> nSortList = new ArrayList<String>();
        ArrayList<Double> dSortList = new ArrayList<Double>();
        Set<String> keys = responseMap.keySet();
        Iterator<String> it = keys.iterator();
        String body = "";
        while (it.hasNext()) {
            String k = it.next();
            @SuppressWarnings("unchecked")
            HashMap<String, Object> response = (HashMap<String, Object>) responseMap.get(k);
            @SuppressWarnings("unchecked")
            Map<String, Object> fset = (HashMap<String, Object>) response.get("fset");
            String cfg = (String) response.get("config");
            @SuppressWarnings("unchecked")
            HashMap<String, Object> tokenmap = (HashMap<String, Object>) response.get("tokenmap");
            String layer = (String) response.get("layer");
            //String featuresAsString = fset.get("features").toString();
            List<HashMap<String, Object>> features = (ArrayList<HashMap<String, Object>>) fset.get("features");
            ObjectMapper om = new ObjectMapper();
            //List<Object> features = new ArrayList<Object>();
            //Graphic[] features = fset.getGraphics();
            //List<String> features = om.readValue(featuresAsString, TypeFactory.defaultInstance().constructCollectionType(List.class, String.class));
            String lyrHeader = (String) response.get("lyrheader");
            if (!lyrHeader.isEmpty()) {
                lyrHeader = "<b>" + lyrHeader + "</b>";
            }
            String items = "";

            items += "<b>" + layer.toUpperCase() + ": </b>";

            Boolean usingDist = (Boolean) response.get("calcdist");
            Boolean sortByDist = (Boolean) response.get("sortbydist");
            String distUnits = (String) response.get("distunits");
            String distToken = (String) response.get("disttoken");
            Map<String, Object> srmap = (HashMap<String, Object>) fset.get("spatialReference");
            ;
            Integer wkid = (Integer) srmap.get("wkid");
            //SpatialReference fsetSr = fset.getSpatialReference();
            SpatialReference fsetSr = SpatialReference.create(wkid);
            for (int i = 0; i < features.size(); ++i) {
                HashMap<String, Object> f = features.get(i);
                Map<String, Object> att = (Map<String, Object>) f.get("attributes");
                Map<String, Object> objGeo = (Map<String, Object>) f.get("geometry");
                //String geoString = f.get("geometry").toString();
                Set<String> fields = tokenmap.keySet();
                Iterator<String> itFields = fields.iterator();
                String item = cfg;
                Double distVal = null;
                if (usingDist) {
                    String d = this.GetDistAsString(objGeo, fsetSr, distUnits);
                    if (sortByDist) {
                        distVal = Double.valueOf(d);
                    }
                    item = item.replace(distToken, d);
                }
                String attVal = null;
                String sortAttVal = null;
                while (itFields.hasNext()) {
                    String fldname = itFields.next();
                    String token = (String) tokenmap.get(fldname);
                    attVal = att.get(fldname).toString();
                    if (!sortByDist) {
                        if (fldname.equals(sortField)) {
                            sortAttVal = attVal;
                        }
                    }
                    item = item.replace(token, attVal);

                }
                if (!sortByDist) {
                    if (!nameSortMap.containsKey(sortAttVal)) {
                        List<String> l = new ArrayList<String>();
                        l.add(item);
                        nameSortMap.put(sortAttVal, l);
                        nSortList.add(sortAttVal);
                    } else {
                        List<String> l = nameSortMap.get(sortAttVal);
                        l.add(item);
                        Collections.sort(l);
                    }
                } else {
                    if (!distSortMap.containsKey(distVal)) {
                        List<String> l = new ArrayList<String>();
                        l.add(item);
                        distSortMap.put(distVal, l);
                        dSortList.add(distVal);
                    } else {
                        List<String> l = distSortMap.get(distVal);
                        l.add(item);
                        Collections.sort(l);
                    }
                }
            }
            String sortedItems = "";
            if (!sortByDist) {
                Collections.sort(nSortList);
                sortedItems = ConstructSortedItemsByName(nameSortMap, nSortList);
            } else {
                Collections.sort(dSortList);
                sortedItems = ConstructSortedItemsByDistance(distSortMap, dSortList);
            }
            //String sortedItems = ConstructSortedItems(sortByDist);
            items = sortedItems;
            body += lyrHeader + "<br>" + items;
        }
        String content = "";
        //File file = new File("C:/Dev/Java/DefenseSolution/defense-geometry-processor/src/main/resources/ReportTemplate.html"); //for ex foo.txt
        try {
            //String name = this.getClass().getName();
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("ReportTemplate.html");
            //FileInputStream is = new FileInputStream(file);
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ln;
            while ((ln = br.readLine()) != null) {
                content += ln;
            }

            if (!timestamp.isEmpty()) {
                String tsToken = "${timestamp.value}";
                title = title.replace(tsToken, timestamp);
                if (header != null) {
                    header = header.replace(tsToken, timestamp);
                }
                body = body.replace(tsToken, timestamp);
            }
            content = content.replace("${TITLE}", "<h1>" + title + "</h1>");
            content = content.replace("${HEADING}", "<h2>" + header + "</h2>");
            content = content.replace("${BODY}", body);
            br.close();
            Set<String> eventTokens = eventTokenMap.keySet();
            Iterator<String> eventIt = eventTokens.iterator();
            while (eventIt.hasNext()) {
                String et = eventIt.next();
                String fn = eventTokenMap.get(et);
                String val = currentEvent.getField(fn).toString();
                content = content.replace(et, val);
            }
            File dir = new File("assets/reports");
            if (!dir.exists()) {
                dir.mkdir();
            }
            String filename = "assets/reports/" + file;

            File outfile = new File(filename);

            FileOutputStream fos = new FileOutputStream(outfile);
            OutputStreamWriter osw = new OutputStreamWriter(fos);
            Writer w = new BufferedWriter(osw);
            w.write(content);
            w.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String ConstructSortedItemsByName(Map<String, List<String>> nameSortMap, ArrayList<String> nSortList) {
        String items = "";

        Boolean first = true;
        for (String n : nSortList) {
            List<String> l = nameSortMap.get(n);
            for (String item : l) {
                if (first) {
                    items += item;
                    first = false;
                } else {
                    items += "<br>" + item;
                }
            }
        }

        return items;
    }

    private String ConstructSortedItemsByDistance(Map<Double, List<String>> distSortMap,
            ArrayList<Double> dSortList) {
        String items = "";
        Boolean first = true;
        for (Double d : dSortList) {
            List<String> l = distSortMap.get(d);
            for (String item : l) {
                if (first) {
                    items += item;
                    first = false;
                } else {
                    items += "<br>" + item;
                }
            }
        }
        return items;
    }

}