V1_0.java [src/java/m/example/gis_geotools] Revision: 6a43cae54bfb109df7bc9a3f6e07e8fe92dc33de  Date: Fri Apr 08 12:55:26 MDT 2016
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package m.example.gis_geotools;

//import com.vividsolutions.jts.geom.Geometry;
import csip.ModelDataService;
import static csip.ModelDataService.EXEC_OK;
import csip.ServiceException;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.Path;
import oms3.annotations.Description;
import oms3.annotations.Name;
import org.apache.commons.io.IOUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
//import org.geotools.feature.FeatureCollection;
//import org.geotools.feature.FeatureIterator;
//import org.geotools.geojson.feature.FeatureJSON;
//import org.geotools.geojson.geom.GeometryJSON;
//import org.opengis.feature.Feature;
//import org.opengis.feature.simple.SimpleFeature;

/**
 *  Basic usage of the GeoTools Geometry and Feature objects.
 *  NOTE:  This example also delves into:
 *         -- Extended use of the process() return value features....Will soon be deprecated though, so this may not be useful.
 *         -- SQL statements for MsSQL -vs- PostGIS
 *         -- Demonstration, in the JSON example input files, of the _proper_ usage of "Geometry", "Feature" and "FeatureCollection" types.
 *              Notice in the basic_geometry JSON file there is no keyword "Geometry"...This is correct usage.  "Geometry" is only specified in
 *              "Feature" or GeometryCollection, and has been misused, to date, in our service JSON examples .
 *              The FeatureCollection and Feature types in GeoJSON should be used to their utmost ability, if possible.
 *              Features that have properties should set those properties in their associated Feature properties section
 *              not specify them as separate JSONObjects in the input params.  Using tools like ArcMap or ArcGIS can, subsequently
 *              produce the inputs for our services without outside intervention, if we utilize these GeoJSON features correctly.
 *              Please See:  http://geojson.org/geojson-spec.html for further details...
 *              NOTE:  Thus far, to date, our usage of "Feature" and "FeatureCollection" have been invalid GeoJSON in many cases, and this needs to be repaired,
 *                     for instance, every "Feature" MUST have a "properties" section, but most of ours do not...and most of the time, we really mean 
 *                     to use "Geometry" not "Feature"....
 * 
 * 
 * @author Shaun Case
 */
@Name("GIS_GeoTools")
@Description("An example of how to read in geometries or featurecollections using the geotools libraries.  Also demonstrates proper GeoJSON, error passing with ModelDataServices and SQL differences between PostGIS and MsSQL")
//@Path("m/gis_geotools/1.0")
public class V1_0 extends ModelDataService {

//    Geometry aoa_geometry;
//    JSONObject aoa_input_geometry;
//
//    @Override
//    //  NOTE:  Changed "Exception" to csip.ServiceException.  (It's considered bad form to throw a generic exception in Java)
//    //         We will check the validity of the param array, if it is present, and return a distinct message identifying what is
//    //         missing, if necessary, when we throw a csip.ServiceException. This is much better than just throwing the exception
//    //         with no message at all.
//    protected void preProcess() throws csip.ServiceException {
//        Map<String, JSONObject> inputParams = getParamMap();
//        if (null != inputParams) {
//            this.aoa_input_geometry = inputParams.get("aoa_geometry");
//            if (null == this.aoa_input_geometry) {
//                throw new csip.ServiceException("No 'aoa_geometry' item was found in the JSON input.  Please specify an 'aoa_geometry' .");
//            }
//        } else {
//            throw new csip.ServiceException(" No JSON input parameters were found.  Please specify some input.");
//        }
//    }
//
//    @Override
//    //  NOTE:  Notice the usage of the ability to return an error message string via the process() routine here, instead of throwing a generic exeption.  
//    //         This feature gives the programmer the ability to return very helpful messages to the client of this service.  This makes debugging much
//    //         simpler when such features are used to their full extent.
//    //
//    //  Also NOTE:  This feature will soon be deprecated and using the csip.ServiceException only will be the prefered pathway once the output of the 
//    //              stack traces associated with an exception are moved to a different section of the Metadata of the result rather than the body of the 
//    //              result.
//    
//    protected String process() throws ServiceException {
//        String ret_val = EXEC_OK;
//
//        GeometryJSON geoJSON = new GeometryJSON();
//        try {
//            if (this.aoa_input_geometry.has("features")) {
//                FeatureJSON featureJSON = new FeatureJSON();
//
//                FeatureCollection inputFeatures = featureJSON.readFeatureCollection(this.aoa_input_geometry.toString());
//                FeatureIterator tFeatures = inputFeatures.features();
//                int count = 1;
//                while (tFeatures.hasNext()) {
//                    Feature tFeature = tFeatures.next(); 
//                    this.aoa_geometry = (Geometry) ((SimpleFeature) tFeature).getAttribute("geometry");
//                    Logger.getLogger(V1_0.class.getName()).log(Level.INFO, "Feature geometry " + count + " recieved was: {0}", this.aoa_geometry.toText());                    
//                    count++;
//                    //  Do something with this particular feature here...OR just grab the first one if only one was specified.
//                    //  This particular code assumes only one was specified, but can easily be altered to send more than one
//                    //  and do something with each....
//                                
//                }
//            } else {
//                if ( this.aoa_input_geometry.has("type")){  //Try to uncover if this is a "Feature" or a geometry object                    
//                    if ( this.aoa_input_geometry.getString("type").equalsIgnoreCase("feature")){
//                        FeatureJSON featureJSON = new FeatureJSON();
//                        Feature tFeature = featureJSON.readFeature(this.aoa_input_geometry.toString());
//                        this.aoa_geometry = (Geometry) ((SimpleFeature) tFeature).getAttribute("geometry");
//                        //  Here we could pull out the Feature's properies as well...
//                        Logger.getLogger(V1_0.class.getName()).log(Level.INFO, "This Feature''s Id is: {0}", ((SimpleFeature) tFeature).getID());
//                        Logger.getLogger(V1_0.class.getName()).log(Level.INFO, "This Feature''s name is: {0}", ((SimpleFeature) tFeature).getAttribute("name"));
//                        
//                        //NOTE:  For some reason, property values that are arrays (as in the example JSON), don't get read, so watch out for this!
//                        Logger.getLogger(V1_0.class.getName()).log(Level.INFO, "This Feature''s adjustment factor is: {0}", ((SimpleFeature) tFeature).getAttribute("AdjustmentFactor"));
//                                                
//                    }
//                    else{  //Try to read the GeoJSON geometry object
//                        this.aoa_geometry = geoJSON.read(IOUtils.toInputStream(this.aoa_input_geometry.toString()));
//                    }
//                }
//                else{
//                    
//                }
//            }
//
//            //  TODO:  Add your code here to do something with the geometry(ies) you read in.
//            //         For instance:  See code lines below:  (NOTE:  The .toText() funciton of "Geometry" returns WKT..)
//            //  Log the WKT of the input.
//            Logger.getLogger(V1_0.class.getName()).log(Level.INFO, "Last aoa_geometry value recieved was: {0}", this.aoa_geometry.toText());
//
//            String Query;
//            //     PostGIS specific SQL statement below to calculate area in acres.
//            Query = "SELECT st_area(st_transform(ST_PolygonFromText('" + this.aoa_geometry.toText() + "', 4326),3541))/43560 as areaInAcres; ";
//
//            //     MsSQL specific SQL statement below to calculate area in acres.  (NOTE:  Assumes point rotation is openGIS compliant, i.e. non-ESRI Shapefile)
//            Query = "SELECT  geography::STGeomFromText('" + this.aoa_geometry.toText() + "', 4326).MakeValid().STArea() / 4046.86 as areaInAcres; ";
//
//            //     MsSQL specific SQL statement below to calculate area in acres.  (NOTE:  Assumes point rotation is non-openGIS compliant, i.e. ESRI Shapefile)
//            Query = "SELECT  geography::STGeomFromText('" + this.aoa_geometry.toText() + "', 4326).ReorientObject().MakeValid().STArea() / 4046.86 as areaInAcres; ";
//
//        } catch (IOException ex) {
//            Logger.getLogger(V1_0.class.getName()).log(Level.SEVERE, "Cannot parse the input GeoJSON into valid GIS entities: ", ex);
//            //  This will return a useable error message to the user via the process() return value, rather than a exception stacktrace, with no explanations.
//            ret_val = "Cannot parse the input GeoJSON into valid GIS entities: " + ex.getMessage();
//            //  Or 
//            //throw new csip.ServiceException( ex );
//        } catch (JSONException ex) {
//            Logger.getLogger(V1_0.class.getName()).log(Level.SEVERE, "Cannot parse the aoa_geometry geometry type.  Please check your syntax. ", ex);
//            ret_val = "Cannot parse the aoa_geometry geometry type.  Please check your syntax. " + ex.getMessage();
//            //  Or 
//            //throw new csip.ServiceException( ex );
//        }
//
//        return ret_val;
//    }

}