package mil.nga.giat.geowave.adapter.vector.render; import org.geoserver.wms.GetMapCallbackAdapter; import org.geoserver.wms.WMS; import org.geoserver.wms.WMSMapContent; import org.geotools.factory.CommonFactoryFinder; import org.geotools.map.FeatureLayer; import org.geotools.map.Layer; import org.geotools.process.Processors; import org.geotools.process.function.DistributedRenderProcessUtils; import org.geotools.process.function.ProcessFunction; import org.geotools.styling.FeatureTypeStyle; import org.geotools.styling.RasterSymbolizer; import org.geotools.styling.Rule; import org.geotools.styling.Style; import org.geotools.styling.StyleFactory; import org.geotools.styling.visitor.DuplicatingStyleVisitor; import org.opengis.filter.expression.Expression; import mil.nga.giat.geowave.adapter.vector.plugin.DistributedRenderProcess; import mil.nga.giat.geowave.adapter.vector.plugin.InternalProcessFactory; /** * The purpose of this callback is completely to get the layer Style accessible * from the query, in particular making the style available to either the * FeatureReader or to a RenderingTransformation * */ public class DistributedRenderCallback extends GetMapCallbackAdapter { private final WMS wms; public DistributedRenderCallback( final WMS wms ) { this.wms = wms; } @Override public Layer beforeLayer( final WMSMapContent mapContent, final Layer layer ) { // sanity check the style if ((layer instanceof FeatureLayer) && (layer.getStyle() != null) && (layer.getStyle().featureTypeStyles() != null) && !layer.getStyle().featureTypeStyles().isEmpty()) { final Style layerStyle = layer.getStyle(); final FeatureTypeStyle style = layerStyle.featureTypeStyles().get( 0); // check if their is a DistributedRender rendering // transformation if (style instanceof ProcessFunction && style.getTransformation() != null && (((ProcessFunction) style.getTransformation()).getName() != null) && ((ProcessFunction) style.getTransformation()).getName().equals( DistributedRenderProcess.PROCESS_NAME)) { // if their is a DistributedRender transformation, we need // to provide more information that can only be found final DuplicatingStyleVisitor cloner = new DuplicatingStyleVisitor(); layerStyle.accept(cloner); layer.getQuery().getHints().put( DistributedRenderProcess.OPTIONS, new DistributedRenderOptions( wms, mapContent, layerStyle)); // now that the options with the distributed render style // have been set the original style will be used with // distributed rendering // now, replace the style with a direct raster symbolizer, // so the GridCoverage result of the distributed rendering // process is directly rendered to the map in place of the // original style final Style directRasterStyle = (Style) cloner.getCopy(); directRasterStyle.featureTypeStyles().clear(); Processors.addProcessFactory(new InternalProcessFactory()); directRasterStyle.featureTypeStyles().add( getDirectRasterStyle( layer.getFeatureSource().getSchema().getGeometryDescriptor().getLocalName(), DistributedRenderProcessUtils.getRenderingProcess())); ((FeatureLayer) layer).setStyle(directRasterStyle); } } return layer; } private static FeatureTypeStyle getDirectRasterStyle( final String geometryPropertyName, final Expression transformation ) { final StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(); final FeatureTypeStyle style = styleFactory.createFeatureTypeStyle(); final Rule rule = styleFactory.createRule(); rule.setName("distributed render - direct raster"); rule.setTitle("Distributed Render - Direct Raster"); final RasterSymbolizer symbolizer = styleFactory.createRasterSymbolizer(); symbolizer.setGeometryPropertyName(geometryPropertyName); rule.symbolizers().add( symbolizer); style.rules().add( rule); style.setTransformation(transformation); return style; } }