3131import org .geotools .filter .text .ecql .ECQL ;
3232import org .geotools .geometry .jts .ReferencedEnvelope ;
3333import org .geotools .util .factory .GeoTools ;
34- import org .hortonmachine .gears .utils .features .CoordinateSwappingFeatureCollection ;
3534import org .hortonmachine .gears .utils .geometry .GeometryHelper ;
3635import org .hortonmachine .gears .utils .geometry .GeometryUtilities ;
3736import org .integratedmodelling .kim .api .IKimConcept .Type ;
7877 * The Class RasterEncoder.
7978 */
8079public class VectorEncoder implements IResourceEncoder {
81- protected boolean intersect ;
82- protected boolean presence ;
83- protected String idRequested ;
84- protected String defaultTypeName ;
85-
86- private Map <String , Class <?>> attributes = new HashMap <>();
87- private Map <String , String > attributeNames = new HashMap <>();
88- protected Projection originalProjection ;
8980
9081 @ Override
9182 public void getEncodedData (IResource resource , Map <String , String > urnParameters , IGeometry geometry , Builder builder ,
@@ -153,15 +144,49 @@ public void encodeFromFeatures(FeatureSource<SimpleFeatureType, SimpleFeature> s
153144 * merge urn params with resource params: if attr=x, use filter, if just value=x and we have
154145 * a nameAttribute filter, else add to parameters
155146 */
156- this . idRequested = urnParameters .containsKey (Urn .SINGLE_PARAMETER_KEY ) && urnParameters .size () == 1
147+ String idRequested = urnParameters .containsKey (Urn .SINGLE_PARAMETER_KEY ) && urnParameters .size () == 1
157148 ? urnParameters .get (Urn .SINGLE_PARAMETER_KEY )
158149 : null ;
159-
150+
160151 String geomName = source .getSchema ().getGeometryDescriptor ().getName ().toString ();
161- this .intersect = urnParameters .containsKey ("intersect" ) ? Boolean .parseBoolean (urnParameters .get ("intersect" )) : true ;
162- this .presence = urnParameters .containsKey ("presence" ) ? Boolean .parseBoolean (urnParameters .get ("presence" )) : false ;
152+ boolean intersect = urnParameters .containsKey ("intersect" ) ? Boolean .parseBoolean (urnParameters .get ("intersect" )) : true ;
153+ boolean presence = urnParameters .containsKey ("presence" ) ? Boolean .parseBoolean (urnParameters .get ("presence" )) : false ;
154+
155+ Map <String , Class <?>> attributes = new HashMap <>();
156+ Map <String , String > attributeNames = new HashMap <>();
157+
158+ for (AttributeDescriptor ad : source .getSchema ().getAttributeDescriptors ()) {
159+ if (!ad .getLocalName ().equals (geomName )) {
160+ attributes .put (ad .getLocalName (), ad .getType ().getBinding ());
161+ attributeNames .put (ad .getLocalName ().toLowerCase (), ad .getLocalName ());
162+ if (idRequested == null && (urnParameters .containsKey (ad .getLocalName ().toLowerCase ())
163+ || urnParameters .containsKey (ad .getLocalName ().toUpperCase ()))) {
164+ try {
165+ // use syntax dependent on attribute type
166+ if (ad .getType ().getBinding () == String .class ) {
167+ filter = ECQL .toFilter (
168+ ad .getLocalName () + " = '" + Utils .getIgnoreCase (urnParameters , ad .getLocalName ()) + "'" );
169+ } else {
170+ filter = ECQL
171+ .toFilter (ad .getLocalName () + " = " + Utils .getIgnoreCase (urnParameters , ad .getLocalName ()));
172+ }
173+ } catch (CQLException e ) {
174+ // shouldn't happen as filter was validated previously
175+ throw new KlabValidationException (e );
176+ }
177+ }
178+ }
179+ }
163180
164- filter = readAttributeData (source , urnParameters , filter , geomName );
181+ /*
182+ * TODO would be nicer to check the request geometry for the data - which may not be the
183+ * scale of the result! If it's IRREGULAR MULTIPLE we want objects, otherwise we want a
184+ * state. I don't think there is a way to check that at the moment - the scale will be that
185+ * of contextualization, not the geometry for the actuator, which may depend on context.
186+ */
187+ boolean rasterize = (idRequested != null || (scope .getTargetSemantics () != null
188+ && (scope .getTargetSemantics ().is (Type .QUALITY ) || scope .getTargetSemantics ().is (Type .TRAIT ))))
189+ && requestScale .getSpace () instanceof Space && ((Space ) requestScale .getSpace ()).getGrid () != null ;
165190
166191 /*
167192 * situations like urn#filter=xxxx" - can't contain an equal sign
@@ -175,7 +200,7 @@ public void encodeFromFeatures(FeatureSource<SimpleFeatureType, SimpleFeature> s
175200 throw new KlabValidationException (e );
176201 }
177202 }
178-
203+
179204 /*
180205 * filters set into the resource parameters
181206 */
@@ -195,66 +220,20 @@ public void encodeFromFeatures(FeatureSource<SimpleFeatureType, SimpleFeature> s
195220 } catch (IOException e ) {
196221 throw new KlabIOException (e );
197222 }
198- this .defaultTypeName = fc .getSchema ().getTypeName () + "_" ;
199223
200224 CoordinateReferenceSystem crs = fc .getSchema ().getCoordinateReferenceSystem ();
201225 crs = GeotoolsUtils .INSTANCE .checkCrs (crs );
202- this . originalProjection = Projection .create (crs );
226+ Projection originalProjection = Projection .create (crs );
203227 IEnvelope envelopeInOriginalProjection = requestScale .getSpace ().getEnvelope ().transform (originalProjection , true );
204228
205229 ReferencedEnvelope bboxRefEnv = ((Envelope ) envelopeInOriginalProjection ).getJTSEnvelope ();
206230 Filter bbfilter = ff .bbox (ff .property (geomName ), bboxRefEnv );
207231 if (filter != null ) {
208232 bbfilter = ff .and (bbfilter , filter );
209233 }
210- FeatureIterator <SimpleFeature > it = fc .subCollection (bbfilter ).features ();
211-
212- parseFeatures (it , resource , urnParameters , geometry , builder , scope , bboxRefEnv );
213- }
214234
215- private Filter readAttributeData (FeatureSource <SimpleFeatureType , SimpleFeature > source , Map <String , String > urnParameters ,
216- Filter filter , String geomName ) {
217- for (AttributeDescriptor ad : source .getSchema ().getAttributeDescriptors ()) {
218- if (!ad .getLocalName ().equals (geomName )) {
219- attributes .put (ad .getLocalName (), ad .getType ().getBinding ());
220- attributeNames .put (ad .getLocalName ().toLowerCase (), ad .getLocalName ());
221- if (idRequested == null && (urnParameters .containsKey (ad .getLocalName ().toLowerCase ())
222- || urnParameters .containsKey (ad .getLocalName ().toUpperCase ()))) {
223- try {
224- // use syntax dependent on attribute type
225- if (ad .getType ().getBinding () == String .class ) {
226- filter = ECQL .toFilter (
227- ad .getLocalName () + " = '" + Utils .getIgnoreCase (urnParameters , ad .getLocalName ()) + "'" );
228- } else {
229- filter = ECQL
230- .toFilter (ad .getLocalName () + " = " + Utils .getIgnoreCase (urnParameters , ad .getLocalName ()));
231- }
232- } catch (CQLException e ) {
233- // shouldn't happen as filter was validated previously
234- throw new KlabValidationException (e );
235- }
236- }
237- }
238- }
239- return filter ;
240- }
241-
242- protected void parseFeatures (FeatureIterator <SimpleFeature > it , IResource resource , Map <String , String > urnParameters ,
243- IGeometry geometry , Builder builder , IContextualizationScope scope , ReferencedEnvelope bboxRefEnv ) {
244- Scale requestScale = geometry instanceof Scale ? (Scale ) geometry : Scale .create (geometry );
245235 Rasterizer <Object > rasterizer = null ;
246236 double cellWidth = -1.0 ;
247-
248- /*
249- * TODO would be nicer to check the request geometry for the data - which may not be the
250- * scale of the result! If it's IRREGULAR MULTIPLE we want objects, otherwise we want a
251- * state. I don't think there is a way to check that at the moment - the scale will be that
252- * of contextualization, not the geometry for the actuator, which may depend on context.
253- */
254- boolean rasterize = (idRequested != null || (scope .getTargetSemantics () != null
255- && (scope .getTargetSemantics ().is (Type .QUALITY ) || scope .getTargetSemantics ().is (Type .TRAIT ))))
256- && requestScale .getSpace () instanceof Space && ((Space ) requestScale .getSpace ()).getGrid () != null ;
257-
258237 Polygon polygonEnv = null ;
259238 if (rasterize ) {
260239 IGrid grid = ((Space ) requestScale .getSpace ()).getGrid ();
@@ -272,7 +251,10 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
272251 nameAttribute = "NAME" ;
273252 }
274253
254+ // SpatialDisplay display = new SpatialDisplay(requestScale);
255+
275256 int n = 1 ;
257+ FeatureIterator <SimpleFeature > it = fc .subCollection (bbfilter ).features ();
276258 while (it .hasNext ()) {
277259
278260 if (presence ) {
@@ -283,6 +265,7 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
283265
284266 SimpleFeature feature = it .next ();
285267 Geometry shape = (Geometry ) feature .getDefaultGeometry ();
268+
286269 if (shape .isEmpty ()) {
287270 continue ;
288271 }
@@ -293,30 +276,36 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
293276 shape = shape .buffer (0 );
294277 }
295278 }
279+
296280
297281 IShape objectShape = null ;
298- if (rasterize ) {
282+ if (rasterize ) {
299283 // do always intersect
300284 try {
301285 Geometry intersection = GeometryHelper .multiPolygonIntersection (polygonEnv , shape , cellWidth );
302- objectShape = Shape .create (intersection , originalProjection ).transform (requestScale .getSpace ().getProjection ());
286+ objectShape = Shape .create (intersection , originalProjection )
287+ .transform (requestScale .getSpace ().getProjection ());
303288 } catch (Exception e ) {
304289 throw new KlabIOException (e );
305290 }
306-
307- } else {
308- objectShape = Shape .create (shape , originalProjection ).transform (requestScale .getSpace ().getProjection ());
309-
310- if (this .intersect ) {
291+
292+ }else {
293+ objectShape = Shape .create (shape , originalProjection )
294+ .transform (requestScale .getSpace ().getProjection ());
295+
296+ if (intersect ) {
311297 objectShape = objectShape .intersection (requestScale .getSpace ().getShape ());
312298 }
313299 }
314300
301+ // display.add(objectShape);
302+
315303 if (objectShape .isEmpty ()) {
316304 continue ;
317305 }
318306
319307 if (rasterize ) {
308+
320309 Object value = Boolean .TRUE ;
321310
322311 if (idRequested != null ) {
@@ -331,7 +320,7 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
331320 final Object vval = value ;
332321 rasterizer .add (objectShape , (s ) -> vval );
333322
334- } else if (!this . presence ) {
323+ } else if (!presence ) {
335324
336325 IScale objectScale = Scale .createLike (scope .getScale (), objectShape );
337326 String objectName = null ;
@@ -348,11 +337,11 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
348337 }
349338 }
350339 if (objectName /* still */ == null ) {
351- objectName = defaultTypeName + (n ++);
340+ objectName = fc . getSchema (). getTypeName () + "_" + (n ++);
352341 }
353342
354343 builder = builder .startObject (scope .getTargetName (), objectName , objectScale );
355- for (String key : attributes .keySet ()) {
344+ for (String key : attributes .keySet ()) {
356345 Object nattr = feature .getAttribute (key );
357346 if (nattr == null ) {
358347 nattr = feature .getAttribute (key .toUpperCase ());
@@ -373,17 +362,20 @@ protected void parseFeatures(FeatureIterator<SimpleFeature> it, IResource resour
373362
374363 it .close ();
375364
376- if (this .presence ) {
365+ // display.show();
366+
367+ if (presence ) {
377368 builder = builder .withMetadata ("presence" , Boolean .FALSE );
378369 }
379-
370+
380371 if (rasterize ) {
381372 final Builder stateBuilder = builder ;
382373 rasterizer .finish ((b , xy ) -> {
383374 stateBuilder .set (b , requestScale .at (ISpace .class , xy ));
384375 });
385376// builder = builder.finishState();
386377 }
378+
387379 }
388380
389381 @ Override
0 commit comments