Package org.geoserver.geopkg.wps

Source Code of org.geoserver.geopkg.wps.GeoPackageProcess

package org.geoserver.geopkg.wps;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.namespace.QName;

import net.opengis.wfs20.GetFeatureType;
import net.opengis.wfs20.QueryType;
import net.opengis.wfs20.Wfs20Factory;

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.geopkg.GeoPackageGetMapOutputFormat;
import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.GetFeature;
import org.geoserver.wfs.WFSInfo;
import org.geoserver.wfs.request.FeatureCollectionResponse;
import org.geoserver.wfs.request.GetFeatureRequest;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wps.WPSStorageCleaner;
import org.geotools.data.DataUtilities;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.NameImpl;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.geopkg.Entry;
import org.geotools.geopkg.FeatureEntry;
import org.geotools.geopkg.GeoPackage;
import org.geotools.geopkg.TileEntry;
import org.geotools.geopkg.wps.GeoPackageProcessRequest;
import org.geotools.geopkg.wps.GeoPackageProcessRequest.FeaturesLayer;
import org.geotools.geopkg.wps.GeoPackageProcessRequest.Layer;
import org.geotools.geopkg.wps.GeoPackageProcessRequest.LayerType;
import org.geotools.geopkg.wps.GeoPackageProcessRequest.TilesLayer;
import org.geotools.process.factory.DescribeParameter;
import org.geotools.process.factory.DescribeProcess;
import org.geotools.process.factory.DescribeResult;
import org.geotools.process.gs.GSProcess;
import org.geotools.referencing.CRS;
import org.geotools.styling.Style;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;

import com.vividsolutions.jts.geom.Envelope;

@DescribeProcess(title="GeoPackage", description="Geopackage Process")
public class GeoPackageProcess implements GSProcess {
   
   private Catalog catalog;
   
   private WPSStorageCleaner storage;
  
   private GetFeature getFeatureDelegate;
     
   private GeoPackageGetMapOutputFormat mapOutput;
  
   private FilterFactory2 filterFactory;
  
   public GeoPackageProcess(GeoServer geoServer, GeoPackageGetMapOutputFormat mapOutput, WPSStorageCleaner storage, FilterFactory2 filterFactory) {
       this.storage = storage;
       this.mapOutput = mapOutput;
       this.filterFactory = filterFactory;
       catalog = geoServer.getCatalog();
       getFeatureDelegate = new GetFeature(geoServer.getService(WFSInfo.class), catalog);
       getFeatureDelegate.setFilterFactory(filterFactory);
   }
  
   private static final int TEMP_DIR_ATTEMPTS = 10000;
  
   public static File createTempDir(File baseDir) {       
        String baseName = System.currentTimeMillis() + "-";

        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
            File tempDir = new File(baseDir, baseName + counter);
            if (tempDir.mkdir()) {
                return tempDir;
            }
        }
        throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS
                + " attempts (tried " + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1)
                + ')');
    }

   @DescribeResult(name="geopackage", description="Link to Compiled Geopackage File")
   public URL execute(@DescribeParameter(name="contents", description="xml scheme describing geopackage contents") GeoPackageProcessRequest contents) throws IOException {
      
       final File file;
      
       URL path = contents.getPath();
       boolean remove = contents.getRemove() != null ? contents.getRemove() : true;
      
       if(!remove && path != null){
           File urlToFile = DataUtilities.urlToFile(path);
           urlToFile.mkdirs();
           file =new File(urlToFile, contents.getName()+ ".gpkg");
       }else{
           file = new File( createTempDir(storage.getStorage()), contents.getName()+ ".gpkg");
       }
      
       GeoPackage gpkg = new GeoPackage(file);
       // Initialize the GeoPackage file in order to avoid exceptions when accessing the geoPackage file
       gpkg.init();
             
       for (int i=0; i < contents.getLayerCount() ; i++) {
           Layer layer = contents.getLayer(i);
          
           if (layer.getType() == LayerType.FEATURES){
               FeaturesLayer features = (FeaturesLayer) layer;
               QName ftName = features.getFeatureType();

               QueryType query = Wfs20Factory.eINSTANCE.createQueryType();
               query.getTypeNames().add(ftName);

               if (features.getSrs() == null) {
                   String ns = ftName.getNamespaceURI() != null
                       ? ftName.getNamespaceURI() : ftName.getPrefix();
                   FeatureTypeInfo ft =
                       catalog.getFeatureTypeByName(ns, ftName.getLocalPart());
                   if (ft != null) {
                       try {
                           query.setSrsName(new URI(ft.getSRS()));
                       } catch (URISyntaxException e) {
                           throw new RuntimeException(e);
                       }
                   }
               }
               else {
                   query.setSrsName(features.getSrs());
               }

               if (features.getPropertyNames() != null) {
                   query.getPropertyNames().addAll(features.getPropertyNames());
               }
               Filter filter = features.getFilter();

               //add bbox to filter if there is one
               if (features.getBbox() != null){
                   String defaultGeometry = catalog.getFeatureTypeByName(features.getFeatureType().getLocalPart())
                           .getFeatureType().getGeometryDescriptor().getLocalName();

                   Envelope e = features.getBbox();
                   // HACK: because we are going through wfs 2.0, flip the coordinates (specified in xy)
                   // which will then be later flipped back to xy
                   if (query.getSrsName() != null) {
                       try {
                           CoordinateReferenceSystem crs = CRS.decode(query.getSrsName().toString());
                           if (crs instanceof GeographicCRS) {
                               // flip the bbox
                               e = new Envelope(e.getMinY(), e.getMaxY(), e.getMinX(), e.getMaxX());
                           }
                       }
                       catch(Exception ex) {
                           throw new RuntimeException(ex);
                       }
                   }

                   Filter bboxFilter = filterFactory.bbox(filterFactory.property(defaultGeometry),
                       ReferencedEnvelope.reference(e));
                   if (filter == null) {
                       filter = bboxFilter;
                   } else {
                       filter = filterFactory.and(filter, bboxFilter);
                   }
               }
               query.setFilter(filter);
              
               GetFeatureType getFeature = Wfs20Factory.eINSTANCE.createGetFeatureType();
               getFeature.getAbstractQueryExpression().add(query);

               FeatureCollectionResponse fc = getFeatureDelegate.run(GetFeatureRequest.adapt(getFeature));
              
               for (FeatureCollection collection: fc.getFeatures()) {                  
                   if (! (collection instanceof SimpleFeatureCollection)) {
                       throw new ServiceException("GeoPackage OutputFormat does not support Complex Features.");
                   }
                  
                   FeatureEntry e = new FeatureEntry();
                   e.setTableName(layer.getName());                  
                   addLayerMetadata(e, features);
                   ReferencedEnvelope bounds = collection.getBounds();
                   if (features.getBbox() != null){
                       bounds = ReferencedEnvelope.reference(bounds.intersection(features.getBbox()));
                   }
                  
                   e.setBounds(bounds);
                 
                   gpkg.add(e, (SimpleFeatureCollectioncollection);
               }
              
           } else if (layer.getType() == LayerType.TILES) {
               TilesLayer tiles = (TilesLayer) layer;              
               GetMapRequest request = new GetMapRequest();
              
               request.setLayers(new ArrayList<MapLayerInfo>());
               for (QName layerQName : tiles.getLayers()) {
                   LayerInfo layerInfo = null;
                   if ("".equals(layerQName.getNamespaceURI())) {
                       layerInfo = catalog.getLayerByName(layerQName.getLocalPart());
                   } else {
                       layerInfo = catalog.getLayerByName(new NameImpl(layerQName.getNamespaceURI(), layerQName.getLocalPart()));
                   }
                   if (layerInfo == null) {
                       throw new ServiceException("Layer not found: " + layerQName);
                   }
                   request.getLayers().add(new MapLayerInfo(layerInfo));
               }

               if (tiles.getBbox() == null) {
                   try {
                       // generate one from requests layers
                       CoordinateReferenceSystem crs =
                           tiles.getSrs() != null ? CRS.decode(tiles.getSrs().toString()) : null;
   
                       ReferencedEnvelope bbox = null;
                       for (MapLayerInfo l : request.getLayers()) {
                           ResourceInfo r = l.getResource();
                           ReferencedEnvelope b = null;
                           if (crs != null) {
                               // transform from lat lon bbox
                               b = r.getLatLonBoundingBox().transform(crs, true);
                           }
                           else {
                               // use native bbox
                               b = r.getNativeBoundingBox();
                               if (bbox != null) {
                                   // transform
                                   b = b.transform(bbox.getCoordinateReferenceSystem(), true);
                               }
                           }
   
                           if (bbox != null) {
                               bbox.include(b);
                           }
                           else {
                               bbox = b;
                           }
                       }

                       request.setBbox(bbox);
                   }
                   catch(Exception e) {
                       String msg = "Must specify bbox, unable to derive from requested layers";
                       throw new RuntimeException(msg ,e);
                   }
               }
               else {
                   request.setBbox(tiles.getBbox());
               }

               if (tiles.getSrs() == null) {
                   // use srs of first layer
                   ResourceInfo r = request.getLayers().iterator().next().getResource();
                   request.setSRS(r.getSRS());
               }
               else {
                   request.setSRS(tiles.getSrs().toString());
               }

               // Get the request SRS defined and set is as the request CRS
               String srs = request.getSRS();
               if(srs != null && !srs.isEmpty()){
                   try {
                       request.setCrs(CRS.decode(srs));
                   } catch (FactoryException e) {
                       throw new RuntimeException(e);
                   }
               }

               request.setBgColor(tiles.getBgColor());
               request.setTransparent(tiles.isTransparent());
               request.setStyleBody(tiles.getSldBody());
               if (tiles.getSld() != null) {
                   request.setStyleUrl(tiles.getSld().toURL());
               }
               else if (tiles.getSldBody() != null) {
                   request.setStyleBody(tiles.getSldBody());
               }
               else {
                   request.setStyles(new ArrayList<Style>());
                   if (tiles.getStyles() != null) {
                       for (String styleName : tiles.getStyles()) {
                           StyleInfo info = catalog.getStyleByName(styleName);
                           if (info != null){
                               request.getStyles().add(info.getStyle());
                           }                      
                       }
                   }
                   if (request.getStyles().isEmpty()) {
                       for (MapLayerInfo layerInfo : request.getLayers()) {
                           request.getStyles().add(layerInfo.getDefaultStyle());
                       }
                   }
               }
               request.setFormat("none");
               Map formatOptions = new HashMap();
               formatOptions.put("format",tiles.getFormat());
               if (tiles.getCoverage() != null) {
                   if (tiles.getCoverage().getMinZoom() != null) {
                       formatOptions.put("min_zoom", tiles.getCoverage().getMinZoom());
                   }
                   if (tiles.getCoverage().getMaxZoom() != null) {
                       formatOptions.put("max_zoom", tiles.getCoverage().getMaxZoom());
                   }
                   if (tiles.getCoverage().getMinColumn() != null) {                      
                       formatOptions.put("min_column", tiles.getCoverage().getMinColumn());
                   }
                   if (tiles.getCoverage().getMaxColumn() != null) {
                       formatOptions.put("max_column", tiles.getCoverage().getMaxColumn());
                   }
                   if (tiles.getCoverage().getMinRow() != null) {
                       formatOptions.put("min_row", tiles.getCoverage().getMinRow());
                   }
                   if (tiles.getCoverage().getMaxRow() != null) {
                       formatOptions.put("max_row", tiles.getCoverage().getMaxRow());
                   }
               }
               if (tiles.getGridSetName() != null) {
                   formatOptions.put("gridset", tiles.getGridSetName());
               }
               request.setFormatOptions(formatOptions);
                             
               TileEntry e = new TileEntry();                
               addLayerMetadata(e, tiles);
              
               if (tiles.getGrids() != null) {
                   mapOutput.addTiles(gpkg, e, request, tiles.getGrids(), layer.getName());
               } else {
                   mapOutput.addTiles(gpkg, e, request, layer.getName());
               }
           }
       }
      
       gpkg.close();
       // Add to storage only if it is a temporary file
       if(path != null && !remove){
           return path;
       }else{
           return storage.getURL(file);
       }
   }

    private void addLayerMetadata(Entry e, Layer layer) {
        e.setDescription(layer.getDescription());
        e.setIdentifier(layer.getIdentifier());
    }

}
TOP

Related Classes of org.geoserver.geopkg.wps.GeoPackageProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.