com.esri.geoevent.processor.reversegeocoder.ReverseGeocoderProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.esri.geoevent.processor.reversegeocoder.ReverseGeocoderProcessor.java

Source

/*
  Copyright 1995-2015 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.
    
  For additional information, contact:
  Environmental Systems Research Institute, Inc.
  Attn: Contracts Dept
  380 New York Street
  Redlands, California, USA 92373
    
  email: contracts@esri.com
 */

package com.esri.geoevent.processor.reversegeocoder;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;

import com.esri.core.geometry.Geometry;
import com.esri.core.geometry.Point;
import com.esri.ges.core.ConfigurationException;
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.FieldException;
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.property.Property;
import com.esri.ges.framework.i18n.BundleLogger;
import com.esri.ges.framework.i18n.BundleLoggerFactory;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManager;
import com.esri.ges.manager.geoeventdefinition.GeoEventDefinitionManagerException;
import com.esri.ges.messaging.GeoEventCreator;
import com.esri.ges.messaging.Messaging;
import com.esri.ges.messaging.MessagingException;
import com.esri.ges.processor.GeoEventProcessorBase;
import com.esri.ges.processor.GeoEventProcessorDefinition;

public class ReverseGeocoderProcessor extends GeoEventProcessorBase {
    /**
     * Initialize the i18n Bundle Logger
     * 
     * See {@link BundleLogger} for more info.
     */

    private static final Log LOG = LogFactory.getLog(ReverseGeocoderProcessor.class);
    private static final BundleLogger LOGGER = BundleLoggerFactory.getLogger(ReverseGeocoderProcessor.class);

    private Object propertyLock = new Object();
    private int agolSearchDistance;
    private String agolSearchFormat;
    private GeoEventCreator geoEventCreator;
    private String newGeoEventDefinitionName;

    protected ReverseGeocoderProcessor(GeoEventProcessorDefinition definition) throws ComponentException {
        super(definition);
    }

    @Override
    public void afterPropertiesSet() {
        synchronized (propertyLock) {
            agolSearchDistance = 100;
            if (hasProperty(ReverseGeocoderProcessorDefinition.AGOL_SEARCHDISTANCE_PROPERTY)) {
                agolSearchDistance = (int) getProperty(
                        ReverseGeocoderProcessorDefinition.AGOL_SEARCHDISTANCE_PROPERTY).getValue();
            }

            newGeoEventDefinitionName = "NewGeoEventDefinition";
            if (hasProperty(ReverseGeocoderProcessorDefinition.NEWGEOEVENTDEFINITION_PROPERTY)) {
                newGeoEventDefinitionName = (String) getProperty(
                        ReverseGeocoderProcessorDefinition.NEWGEOEVENTDEFINITION_PROPERTY).getValue();
            }
        }
    }

    @Override
    public GeoEvent process(GeoEvent geoEvent) throws Exception {
        GeoEvent agolStreetAddress = processGeoEvent(geoEvent);

        return agolStreetAddress;
    }

    private GeoEvent processGeoEvent(GeoEvent geoEvent) throws MalformedURLException, JSONException,
            ConfigurationException, GeoEventDefinitionManagerException, FieldException {
        if (geoEvent.getTrackId() == null || geoEvent.getGeometry() == null) {
            LOGGER.warn("NULL_ERROR: TrackID and/or Geometry is NULL.");
            return null;
        }

        Geometry geom = geoEvent.getGeometry().getGeometry();
        if (geom.isEmpty())
            return geoEvent;

        if (!Geometry.isPoint(geom.getType().value()))
            return geoEvent;

        if (Geometry.isMultiVertex(geom.getType().value()))
            return geoEvent;

        Point point = (Point) geom;

        double lon = point.getX();
        double lat = point.getY();
        int wkid = geoEvent.getGeometry().getSpatialReference().getID();

        // fetch nearest street address (reverse geocode) via ArcGIS Online World GeoCode service
        // The response format. Values: html | json | kmz 
        // The default response format is html.
        agolSearchFormat = "json";
        URL agolURL = new URL(
                "http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location="
                        + Double.toString(lon) + "," + Double.toString(lat) + "&distance="
                        + Integer.toString(agolSearchDistance) + "&outSR=" + Integer.toString(wkid) + "&f="
                        + agolSearchFormat);
        String addressJson = getReverseGeocode(agolURL);
        GeoEvent agolStreetAddress = augmentGeoEventWithAddress(geoEvent, addressJson);
        return agolStreetAddress;
    }

    private String getReverseGeocode(URL url) {
        String output = "";

        try {

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");

            if (conn.getResponseCode() != 200) {
                String errorString = "Failed : HTTP error code : " + conn.getResponseCode();
                throw new RuntimeException(errorString);
            }

            BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

            String line;
            while ((line = br.readLine()) != null) {
                output += line;
            }

            conn.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return output;
    }

    private GeoEvent augmentGeoEventWithAddress(GeoEvent geoEvent, String addressJson)
            throws ConfigurationException, GeoEventDefinitionManagerException, FieldException, JSONException {
        JSONObject jsonObj = new JSONObject(addressJson);
        JSONObject addressJSONObject = jsonObj.getJSONObject("address");
        GeoEvent newGeoEvent = null;
        if (geoEventCreator != null) {
            try {
                GeoEventDefinition edIn = geoEvent.getGeoEventDefinition();

                List<FieldDefinition> fds = new ArrayList<FieldDefinition>();
                fds.add(new DefaultFieldDefinition("Address", FieldType.String));
                fds.add(new DefaultFieldDefinition("Neighborhood", FieldType.String));
                fds.add(new DefaultFieldDefinition("City", FieldType.String));
                fds.add(new DefaultFieldDefinition("Subregion", FieldType.String));
                fds.add(new DefaultFieldDefinition("Region", FieldType.String));
                fds.add(new DefaultFieldDefinition("Postal", FieldType.String));
                fds.add(new DefaultFieldDefinition("PostalExt", FieldType.String));
                fds.add(new DefaultFieldDefinition("CountryCode", FieldType.String));
                fds.add(new DefaultFieldDefinition("Match_addr", FieldType.String));
                fds.add(new DefaultFieldDefinition("Loc_name", FieldType.String));

                GeoEventDefinition edOut = edIn.augment(fds);

                edOut.setName(newGeoEventDefinitionName);
                edOut.setOwner(getId());
                GeoEventDefinitionManager geoEventDefinitionManager = geoEventCreator
                        .getGeoEventDefinitionManager();

                // if (geoEventDefinitionManager.getGeoEventDefinition(newGeoEventDefinitionName) == null)
                //   geoEventDefinitionManager.addGeoEventDefinition(edOut);

                // LOGGER.info("Checking for GED: " + edOut.getName());
                String gedGuid = "";
                try {
                    Collection<GeoEventDefinition> geoEventDefinitions = geoEventDefinitionManager
                            .searchInRepositoryGeoEventDefinitionByName(newGeoEventDefinitionName);

                    // LOGGER.info("Found " + geoEventDefinitions.size() + " GEDs named " + edOut.getName());
                    if (geoEventDefinitions == null || geoEventDefinitions.size() == 0) {
                        // LOGGER.info("Didn't find it. Adding GED: " + edOut.getName());
                        geoEventDefinitionManager.addGeoEventDefinition(edOut);
                    } else
                        gedGuid = geoEventDefinitions.iterator().next().getGuid();
                } catch (Exception ex) {
                    LOGGER.info("Encountered an error checking for this GED: " + edOut.getName()
                            + ". Adding it anyway.");
                    geoEventDefinitionManager.addGeoEventDefinition(edOut);
                    gedGuid = edOut.getGuid();
                }

                List<Object> fieldValues = new ArrayList<Object>();
                Object value;
                for (int i = 0; i < edIn.getFieldDefinitions().size(); i++) {
                    value = geoEvent.getField(i);
                    fieldValues.add(value);
                }

                try {
                    fieldValues.add(addressJSONObject.get("Address"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Neighborhood"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("City"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Subregion"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Region"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Postal"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("PostalExt"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("CountryCode"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Match_addr"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }
                try {
                    fieldValues.add(addressJSONObject.get("Loc_name"));
                } catch (Exception ex) {
                    fieldValues.add("");
                }

                // LOGGER.info("Creating a Geoevent from GED: " + edOut.getName());
                newGeoEvent = geoEventCreator.create(gedGuid);
                // LOGGER.info("Create a Geoevent from GED: " + edOut.getName());

                // newGeoEvent = geoEventCreator.create(newGeoEventDefinitionName, definition.getUri().toString());
                for (int i = 0; i < edOut.getFieldDefinitions().size(); i++) {
                    try {
                        newGeoEvent.setField(i, fieldValues.get(i));
                    } catch (Exception ex) {
                    }
                }

                newGeoEvent.setProperty(GeoEventPropertyName.TYPE, "event");
                newGeoEvent.setProperty(GeoEventPropertyName.OWNER_ID, getId());
                newGeoEvent.setProperty(GeoEventPropertyName.OWNER_URI, definition.getUri());

            } catch (MessagingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return newGeoEvent;
    }

    public void setMessaging(Messaging messaging) {
        geoEventCreator = messaging.createGeoEventCreator();
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(definition.getName());
        sb.append("/");
        sb.append(definition.getVersion());
        sb.append("[");
        for (Property p : getProperties()) {
            sb.append(p.getDefinition().getPropertyName());
            sb.append(":");
            sb.append(p.getValue());
            sb.append(" ");
        }
        sb.append("]");
        return sb.toString();
    }
}