1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package nl.b3p.viewer.stripes;
18
19 import static nl.b3p.viewer.ibis.util.DateUtils.addMonth;
20 import static nl.b3p.viewer.ibis.util.DateUtils.differenceInMonths;
21
22 import java.io.StringReader;
23 import java.math.BigDecimal;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.Comparator;
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 import java.util.TimeZone;
36 import java.util.TreeMap;
37 import java.util.TreeSet;
38 import javax.persistence.EntityManager;
39 import net.sourceforge.stripes.action.ActionBean;
40 import net.sourceforge.stripes.action.ActionBeanContext;
41 import net.sourceforge.stripes.action.After;
42 import net.sourceforge.stripes.action.Before;
43 import net.sourceforge.stripes.action.DefaultHandler;
44 import net.sourceforge.stripes.action.Resolution;
45 import net.sourceforge.stripes.action.StreamingResolution;
46 import net.sourceforge.stripes.action.StrictBinding;
47 import net.sourceforge.stripes.action.UrlBinding;
48 import net.sourceforge.stripes.controller.LifecycleStage;
49 import net.sourceforge.stripes.validation.DateTypeConverter;
50 import net.sourceforge.stripes.validation.EnumeratedTypeConverter;
51 import net.sourceforge.stripes.validation.Validate;
52 import nl.b3p.viewer.config.app.Application;
53 import nl.b3p.viewer.config.app.ApplicationLayer;
54 import nl.b3p.viewer.config.security.Authorizations;
55 import nl.b3p.viewer.config.services.AttributeDescriptor;
56 import nl.b3p.viewer.config.services.FeatureTypeRelation;
57 import nl.b3p.viewer.config.services.Layer;
58 import nl.b3p.viewer.config.services.SimpleFeatureType;
59 import nl.b3p.viewer.ibis.util.IbisConstants;
60 import nl.b3p.viewer.util.FeatureToJson;
61 import org.apache.commons.logging.Log;
62 import org.apache.commons.logging.LogFactory;
63 import org.geotools.data.DataUtilities;
64 import org.geotools.data.Query;
65 import org.geotools.data.simple.SimpleFeatureCollection;
66 import org.geotools.data.simple.SimpleFeatureIterator;
67 import org.geotools.feature.simple.SimpleFeatureBuilder;
68 import org.geotools.data.simple.SimpleFeatureSource;
69 import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
70 import org.geotools.filter.text.ecql.ECQL;
71 import org.json.JSONArray;
72 import org.json.JSONException;
73 import org.json.JSONObject;
74 import org.opengis.feature.Property;
75 import org.opengis.feature.simple.SimpleFeature;
76 import org.opengis.filter.Filter;
77 import org.stripesstuff.stripersist.Stripersist;
78
79
80
81
82
83
84 @UrlBinding("/action/ibisattributes")
85 @StrictBinding
86 public class IbisAttributeListActionBean implements ActionBean, IbisConstants {
87
88 private static final Log log = LogFactory.getLog(IbisAttributeListActionBean.class);
89 private static final String JSON_METADATA = "metaData";
90 private ActionBeanContext context;
91
92
93
94
95 @Validate
96 private String data;
97
98
99
100 @Validate
101 private String filename;
102
103
104
105 @Validate
106 private String mimetype;
107
108 @Validate
109 private Application application;
110
111 @Validate
112 private ApplicationLayer appLayer;
113
114 @Validate(converter = DateTypeConverter.class)
115 private Date fromDate;
116 @Validate(converter = DateTypeConverter.class)
117 private Date toDate;
118 @Validate
119 private String regio;
120 @Validate
121 private String gemeente;
122 @Validate
123 private String terrein;
124 @Validate
125 private List<String> attrNames;
126
127
128
129 @Validate(converter = EnumeratedTypeConverter.class)
130 private ReportType reportType;
131
132
133
134 @Validate(converter = EnumeratedTypeConverter.class)
135 private QueryArea aggregationLevel;
136 @Validate(converter = EnumeratedTypeConverter.class)
137 private AggregationLevelDate aggregationLevelDate;
138
139 private Layer layer = null;
140 private boolean unauthorized;
141 private String gebiedsNaamQuery;
142 private QueryArea areaType;
143
144 enum QueryArea {
145
146 REGIO, GEMEENTE, TERREIN
147 }
148
149 enum ReportType {
150
151 INDIVIDUAL, AGGREGATED, ISSUE;
152 }
153
154 enum AggregationLevelDate {
155
156 NONE, MONTH
157 }
158
159
160
161
162 private static final String TERREINID_FIELDNAME = "id";
163
164
165
166 private static final String GEMEENTE_FIELDNAME = "naam";
167
168
169
170 private static final String REGIO_FIELDNAME = "vvr_naam";
171
172
173
174 private static final String TERREIN_FIELDNAME = "a_plannaam";
175
176
177
178 private static final String STATUS_FIELDNAME = "status";
179
180
181
182 private static final String KAVELID_RELATED_FIELDNAME = "kavelid";
183
184
185
186 private static final String GEMEENTE_RELATED_FIELDNAME = "gemeentenaam";
187
188
189
190 private static final String REGIO_RELATED_FIELDNAME = "regionaam";
191
192
193
194 private static final String TERREIN_RELATED_FIELDNAME = "terreinnaam";
195
196
197
198
199 private static final String TERREINID_RELATED_FIELDNAME = "terreinid";
200
201
202
203
204 private static final String UITGIFTEDATUM_RELATED_FIELDNAME = "datumuitgifte";
205
206
207
208 private static final String OPPERVLAKTE_GEOM_RELATED_FIELDNAME = "opp_geometrie";
209
210
211
212
213 private static final String GEBIED_FIELDNAME = "gebied";
214
215
216
217
218
219
220 private static final String RELATED_FT_NAME = null;
221
222 @After(stages = LifecycleStage.BindingAndValidation)
223 public void loadLayer() {
224 this.layer = appLayer.getService().getSingleLayer(appLayer.getLayerName(), Stripersist.getEntityManager());
225 }
226
227 @Before(stages = LifecycleStage.EventHandling)
228 public void checkAuthorization() {
229 EntityManager em = Stripersist.getEntityManager();
230 if (application == null
231 || appLayer == null
232 || !Authorizations.isAppLayerReadAuthorized(application, appLayer, context.getRequest(), em)) {
233 unauthorized = true;
234 }
235 }
236
237
238
239
240
241
242
243
244
245 public Resolution download() throws Exception {
246 if (data == null) {
247 throw new IllegalArgumentException("Data cannot be null.");
248 } else if (unauthorized) {
249 throw new IllegalStateException("Not authorized.");
250 }
251 if (mimetype == null) {
252 mimetype = "application/vnd.ms-excel";
253 }
254 if (filename == null) {
255 filename = "ibisrapportage.xls";
256 }
257 log.debug("returning excel:" + data);
258 return new StreamingResolution(mimetype, new StringReader(data)).setFilename(filename).setAttachment(false);
259 }
260
261 @DefaultHandler
262 public Resolution query() throws Exception {
263 JSONObject json = new JSONObject();
264 json.put("success", Boolean.FALSE);
265
266 JSONObject metadata = new JSONObject()
267 .put("root", "data").put("totalProperty", "total")
268 .put("successProperty", "success")
269 .put("messageProperty", "message")
270 .put("idProperty", "rownum");
271 json.put(JSON_METADATA, metadata);
272
273 String error = null;
274 if (appLayer == null) {
275 error = "Invalid parameters.";
276 } else if (unauthorized) {
277 error = "Not authorized.";
278 } else if (reportType == null) {
279 error = "Report type is required.";
280 } else {
281 try {
282
283 if (terrein != null) {
284 areaType = QueryArea.TERREIN;
285 gebiedsNaamQuery = TERREIN_FIELDNAME + "='" + terrein + "'";;
286 } else if (gemeente != null) {
287 areaType = QueryArea.GEMEENTE;
288 gebiedsNaamQuery = GEMEENTE_FIELDNAME + "='" + gemeente + "'";
289 } else if (regio != null) {
290 areaType = QueryArea.REGIO;
291 gebiedsNaamQuery = REGIO_FIELDNAME + "='" + regio + "'";
292 } else {
293 throw new IllegalArgumentException("Geen gebied opgegeven voor rapport.");
294 }
295
296 switch (reportType) {
297 case ISSUE:
298 reportIssued(json);
299 break;
300 case INDIVIDUAL:
301 reportIndividualData(json);
302 break;
303 case AGGREGATED:
304 reportAggregateData(json);
305 break;
306 }
307
308 json.put("message", "OK");
309 json.put("success", Boolean.TRUE);
310
311 } catch (Exception e) {
312 log.error("Error generating report data.", e);
313 error = e.getLocalizedMessage();
314 }
315 }
316
317 if (error != null) {
318 json.put("success", Boolean.FALSE);
319 json.put("message", error);
320 }
321
322 log.debug("returning json:" + json);
323 return new StreamingResolution("application/json", new StringReader(json.toString()));
324 }
325
326
327
328
329
330
331
332 private void reportIssued(JSONObject json) throws Exception {
333 if (fromDate == null || toDate == null) {
334 throw new IllegalArgumentException("Datum vanaf en datum tot zijn verplicht voor uitgifte.");
335 }
336 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
337 sdf.setTimeZone(TimeZone.getDefault());
338
339 SimpleFeatureType ft = layer.getFeatureType();
340 SimpleFeatureType relFt = this.getRelatedSFT(ft, RELATED_FT_NAME);
341 SimpleFeatureSource fs = (SimpleFeatureSource) ft.openGeoToolsFeatureSource();
342 SimpleFeatureSource foreignFs = (SimpleFeatureSource) relFt.openGeoToolsFeatureSource();
343
344 Filter filter = ECQL.toFilter(this.gebiedsNaamQuery);
345 List<String> tPropnames = Arrays.asList(
346 TERREINID_FIELDNAME,
347 TERREIN_FIELDNAME,
348 GEMEENTE_FIELDNAME,
349 REGIO_FIELDNAME);
350 Query q = new Query(fs.getName().toString());
351 q.setPropertyNames(tPropnames);
352 q.setFilter(filter);
353 q.setHandle("uitgifte-rapport");
354 q.setMaxFeatures(FeatureToJson.MAX_FEATURES);
355
356 try {
357
358 SimpleFeatureCollection inMem = DataUtilities.collection(fs.getFeatures(q).features());
359 StringBuilder in = new StringBuilder();
360 SimpleFeatureIterator inMemFeats = inMem.features();
361 Set<String> terreinNames = new TreeSet<>(
362 new Comparator<String>() {
363 @Override
364 public int compare(String a, String b) {
365 return a.compareTo(b);
366 }
367 }
368 );
369 Set<String> regioNames = new TreeSet<>(new Comparator<String>() {
370 @Override
371 public int compare(String a, String b) {
372 return a.compareTo(b);
373 }
374 });
375 Set<String> gemeenteNames = new TreeSet<>(new Comparator<String>() {
376 @Override
377 public int compare(String a, String b) {
378 return a.compareTo(b);
379 }
380 });
381
382 while (inMemFeats.hasNext()) {
383 SimpleFeature f = inMemFeats.next();
384 in.append(f.getAttribute(TERREINID_FIELDNAME)).append(",");
385 terreinNames.add((String) f.getAttribute(TERREIN_FIELDNAME));
386 regioNames.add((String) f.getAttribute(REGIO_FIELDNAME));
387 gemeenteNames.add((String) f.getAttribute(GEMEENTE_FIELDNAME));
388 }
389 inMemFeats.close();
390
391
392 Query foreignQ = new Query(foreignFs.getName().toString());
393 foreignQ.setHandle("uitgifte-rapport-related");
394 List<String> propnames = Arrays.asList(
395 KAVELID_RELATED_FIELDNAME,
396 OPPERVLAKTE_GEOM_RELATED_FIELDNAME,
397 UITGIFTEDATUM_RELATED_FIELDNAME,
398 TERREIN_RELATED_FIELDNAME,
399 REGIO_RELATED_FIELDNAME,
400 GEMEENTE_RELATED_FIELDNAME);
401 foreignQ.setPropertyNames(propnames);
402 String query = STATUS_FIELDNAME + "= 'uitgegeven' AND "
403 + TERREINID_RELATED_FIELDNAME + " IN (" + in.substring(0, in.length() - 1) + ") AND "
404 + UITGIFTEDATUM_RELATED_FIELDNAME + " DURING " + sdf.format(fromDate) + "/" + sdf.format(toDate);
405 log.debug("uitgifte query: " + query);
406 foreignQ.setFilter(ECQL.toFilter(query));
407
408
409 SimpleFeatureCollection sfc = DataUtilities.collection(foreignFs.getFeatures(foreignQ).features());
410
411
412 org.opengis.feature.simple.SimpleFeatureType type = DataUtilities.createType(
413 "AGGREGATE",
414 "id:String,*geom:MultiPolygon:28992,maand:String,oppervlakte:Double,gebied:String");
415
416
417 List<AttributeDescriptor> relFeatureTypeAttributes = new ArrayList<>();
418 AttributeDescriptor maand = new AttributeDescriptor();
419 maand.setName("maand");
420 maand.setAlias("maand");
421 maand.setType(AttributeDescriptor.TYPE_DATE);
422 maand.setId(1L);
423 relFeatureTypeAttributes.add(maand);
424
425 AttributeDescriptor opp = new AttributeDescriptor();
426 opp.setName("oppervlakte");
427 opp.setAlias("oppervlakte");
428 opp.setType(AttributeDescriptor.TYPE_DOUBLE);
429 opp.setId(2L);
430 relFeatureTypeAttributes.add(opp);
431
432 AttributeDescriptor plan = new AttributeDescriptor();
433 plan.setName(GEBIED_FIELDNAME);
434 plan.setAlias("gebiedsnaam");
435 plan.setType(AttributeDescriptor.TYPE_STRING);
436 plan.setId(3L);
437 relFeatureTypeAttributes.add(plan);
438
439 switch (aggregationLevel) {
440 case REGIO:
441 switch (aggregationLevelDate) {
442 case MONTH:
443 sfc = aggregateUitgifteByMonthAndArea(sfc, type, "oppervlakte",
444 regioNames, REGIO_RELATED_FIELDNAME);
445 break;
446 case NONE:
447 sfc = aggregateUitgifteByArea(sfc, type, "oppervlakte",
448 regioNames, REGIO_RELATED_FIELDNAME);
449 break;
450 }
451 break;
452 case GEMEENTE:
453 switch (aggregationLevelDate) {
454 case MONTH:
455 sfc = aggregateUitgifteByMonthAndArea(sfc, type, "oppervlakte",
456 gemeenteNames, GEMEENTE_RELATED_FIELDNAME);
457 break;
458 case NONE:
459 sfc = aggregateUitgifteByArea(sfc, type, "oppervlakte",
460 gemeenteNames, GEMEENTE_RELATED_FIELDNAME);
461 break;
462 }
463 break;
464 case TERREIN:
465 switch (aggregationLevelDate) {
466 case MONTH:
467 sfc = aggregateUitgifteByMonthAndArea(sfc, type, "oppervlakte",
468 terreinNames, TERREIN_RELATED_FIELDNAME);
469 break;
470 case NONE:
471 sfc = aggregateUitgifteByArea(sfc, type, "oppervlakte",
472 terreinNames, TERREIN_RELATED_FIELDNAME);
473 break;
474 }
475 break;
476 }
477 switch (aggregationLevelDate) {
478 case MONTH:
479 propnames = Arrays.asList("maand", "oppervlakte", GEBIED_FIELDNAME);
480 break;
481 case NONE:
482 propnames = Arrays.asList("oppervlakte", GEBIED_FIELDNAME);
483 }
484 featuresToJson(sfc, json, relFeatureTypeAttributes, propnames);
485 } finally {
486 foreignFs.getDataStore().dispose();
487 fs.getDataStore().dispose();
488 }
489 }
490
491
492
493
494
495
496
497
498
499
500
501
502 private SimpleFeatureCollection aggregateUitgifteByMonthAndArea(SimpleFeatureCollection sfc,
503 org.opengis.feature.simple.SimpleFeatureType type, final String sfTypeAreaName,
504 Set<String> featNames, final String gebiedFieldName) {
505
506 final int months = differenceInMonths(fromDate, toDate);
507 final SimpleDateFormat YYYYMM = new SimpleDateFormat("YYYY.MM");
508 Map<String, SimpleFeature> newfeats = new TreeMap<>();
509
510
511 for (String fName : featNames) {
512 Date newDate = fromDate;
513 for (int m = 0; m < months; m++) {
514 String key = fName + YYYYMM.format(newDate);
515 SimpleFeature month = DataUtilities.
516 createFeature(type, key + "|null|" + YYYYMM.format(newDate) + "|0d|" + fName);
517 newfeats.put(key, month);
518 newDate = addMonth(newDate);
519 }
520 }
521
522
523 SimpleFeatureIterator items = sfc.features();
524 while (items.hasNext()) {
525 SimpleFeature f = items.next();
526 Date d = (Date) f.getAttribute(UITGIFTEDATUM_RELATED_FIELDNAME);
527 SimpleFeature newFeat = newfeats.get(f.getAttribute(gebiedFieldName) + YYYYMM.format(d));
528 newFeat.setAttribute(sfTypeAreaName,
529 ((Double) newFeat.getAttribute(sfTypeAreaName))
530 + ((BigDecimal) f.getAttribute(OPPERVLAKTE_GEOM_RELATED_FIELDNAME)).doubleValue());
531
532 }
533 items.close();
534
535 ArrayList<SimpleFeature> feats = new ArrayList<>(newfeats.values());
536 return DataUtilities.collection(feats);
537 }
538
539
540
541
542
543
544
545
546
547
548
549 private SimpleFeatureCollection aggregateUitgifteByArea(SimpleFeatureCollection sfc,
550 org.opengis.feature.simple.SimpleFeatureType type, String sfTypeAreaName,
551 Set<String> featNames, final String gebiedFieldName) {
552
553
554 Map<String, SimpleFeature> newfeats = new TreeMap<>();
555 for (String fName : featNames) {
556 SimpleFeature newfeat = DataUtilities.
557 createFeature(type, fName + "|null|null|0d|" + fName);
558 newfeats.put(fName, newfeat);
559 }
560
561
562 SimpleFeatureIterator items = sfc.features();
563 while (items.hasNext()) {
564 SimpleFeature f = items.next();
565 SimpleFeature newFeat = newfeats.get((String) f.getAttribute(gebiedFieldName));
566 newFeat.setAttribute(sfTypeAreaName,
567 ((Double) newFeat.getAttribute(sfTypeAreaName))
568 + ((BigDecimal) f.getAttribute(OPPERVLAKTE_GEOM_RELATED_FIELDNAME)).doubleValue());
569
570 }
571 items.close();
572 ArrayList<SimpleFeature> feats = new ArrayList<SimpleFeature>(newfeats.values());
573 Collections.reverse(feats);
574 return DataUtilities.collection(feats);
575 }
576
577
578
579
580
581
582
583
584
585
586
587 private void featuresToJson(SimpleFeatureCollection sfc, JSONObject json,
588 List<AttributeDescriptor> featureTypeAttributes, List<String> outputPropNames) throws JSONException {
589
590
591 JSONArray fields = new JSONArray();
592
593 JSONArray columns = new JSONArray();
594
595 JSONArray datas = new JSONArray();
596
597 SimpleFeatureIterator sfIter = sfc.features();
598
599 boolean getMetadataFromFirstFeature = true;
600 while (sfIter.hasNext()) {
601 SimpleFeature feature = sfIter.next();
602 JSONObject fData = new JSONObject();
603
604 for (AttributeDescriptor attr : featureTypeAttributes) {
605 String name = attr.getName();
606 if (getMetadataFromFirstFeature) {
607 if (outputPropNames.contains(name)) {
608
609 JSONObject field = new JSONObject().put("name", name).put("type", attr.getExtJSType());
610 if (reportType == ReportType.ISSUE && attr.getType().equals(AttributeDescriptor.TYPE_DATE)) {
611 field.put("dateFormat", "Y-m");
612 }
613 fields.put(field);
614 columns.put(new JSONObject().put("text", (attr.getAlias() != null ? attr.getAlias() : name)).put("dataIndex", name));
615 }
616 }
617 fData.put(attr.getName(), feature.getAttribute(attr.getName()));
618 }
619 datas.put(fData);
620 getMetadataFromFirstFeature = false;
621 }
622
623 json.getJSONObject(JSON_METADATA).put("fields", fields);
624 json.getJSONObject(JSON_METADATA).put("columns", columns);
625 json.put("data", datas);
626 json.put("total", datas.length());
627
628 sfIter.close();
629 }
630
631
632
633
634
635
636
637
638
639
640
641 private SimpleFeatureType getRelatedSFT(SimpleFeatureType ft, String typeNameToGet) {
642 SimpleFeatureType relFt = null;
643
644 for (FeatureTypeRelation rel : ft.getRelations()) {
645 if (rel.getType().equals(FeatureTypeRelation.RELATE)) {
646 relFt = rel.getForeignFeatureType();
647 if (relFt.getTypeName().equals(typeNameToGet) || typeNameToGet == null) {
648 break;
649 }
650 }
651 }
652 return relFt;
653 }
654
655 private void reportIndividualData(JSONObject json) throws Exception {
656 List<String> tPropnames = new ArrayList(attrNames);
657
658 SimpleFeatureType ft = layer.getFeatureType();
659 List<AttributeDescriptor> featureTypeAttributes = ft.getAttributes();
660 SimpleFeatureSource fs = (SimpleFeatureSource) ft.openGeoToolsFeatureSource();
661
662 List<String> foreignAttrNames = new ArrayList<String>();
663
664 for (String a : attrNames) {
665 if (fs.getSchema().getDescriptor(a) == null) {
666
667 foreignAttrNames.add(a);
668 tPropnames.remove(a);
669 }
670 }
671 foreignAttrNames.add(TERREINID_RELATED_FIELDNAME);
672 tPropnames.add(TERREINID_FIELDNAME);
673 Filter filter = ECQL.toFilter(this.gebiedsNaamQuery);
674 Query q = new Query(fs.getName().toString());
675 q.setPropertyNames(tPropnames);
676 q.setFilter(filter);
677 q.setHandle("individueel-rapport");
678 q.setMaxFeatures(FeatureToJson.MAX_FEATURES);
679
680 SimpleFeatureCollection mainFSinMem;
681 try {
682 mainFSinMem = DataUtilities.collection(fs.getFeatures(q).features());
683 } finally {
684 fs.getDataStore().dispose();
685 }
686 if (!foreignAttrNames.isEmpty()) {
687 SimpleFeatureType relFt = this.getRelatedSFT(ft, RELATED_FT_NAME);
688 SimpleFeatureSource foreignFs = (SimpleFeatureSource) relFt.openGeoToolsFeatureSource();
689
690 StringBuilder in = new StringBuilder();
691 HashMap<Integer, SimpleFeature> parentFeatures = new HashMap<>();
692 SimpleFeatureIterator inMemFeats = mainFSinMem.features();
693 while (inMemFeats.hasNext()) {
694 SimpleFeature f = inMemFeats.next();
695 in.append(f.getAttribute(TERREINID_FIELDNAME)).append(",");
696 parentFeatures.put((Integer) f.getAttribute(TERREINID_FIELDNAME), f);
697 }
698 inMemFeats.close();
699
700
701 Query foreignQ = new Query(foreignFs.getName().toString());
702 foreignQ.setHandle("individueel-rapport-related");
703 foreignQ.setPropertyNames(foreignAttrNames);
704 String query = TERREINID_RELATED_FIELDNAME + " IN (" + in.substring(0, in.length() - 1) + ")";
705 log.debug("individueel-rapport-related: " + query);
706 foreignQ.setFilter(ECQL.toFilter(query));
707 try {
708
709 SimpleFeatureCollection relatedFC = foreignFs.getFeatures(foreignQ);
710
711 SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
712 tb.setName("COMPOSITE");
713 for (String prop : attrNames) {
714 org.opengis.feature.type.AttributeDescriptor attrDescName = fs.getSchema().getDescriptor(prop);
715 if (attrDescName == null) {
716
717 attrDescName = foreignFs.getSchema().getDescriptor(prop);
718 }
719 tb.add(attrDescName);
720 }
721 tb.add(TERREINID_RELATED_FIELDNAME, Integer.class);
722 org.opengis.feature.simple.SimpleFeatureType type = tb.buildFeatureType();
723
724 featureTypeAttributes.addAll(relFt.getAttributes());
725
726 SimpleFeatureBuilder sfBuilder = new SimpleFeatureBuilder(type);
727 SimpleFeatureIterator sfcIter = relatedFC.features();
728 ArrayList<SimpleFeature> newfeats = new ArrayList<>();
729 while (sfcIter.hasNext()) {
730
731 SimpleFeature f = sfcIter.next();
732 SimpleFeature n = SimpleFeatureBuilder.retype(f, sfBuilder);
733
734 SimpleFeature p = parentFeatures.get((Integer) f.getAttribute(TERREINID_RELATED_FIELDNAME));
735 for (Property a : p.getProperties()) {
736 if (attrNames.contains(a.getName().toString())) {
737 n.setAttribute(a.getName(), a.getValue());
738 }
739 }
740 newfeats.add(n);
741 }
742 sfcIter.close();
743 mainFSinMem = DataUtilities.collection(newfeats);
744 } finally {
745 foreignFs.getDataStore().dispose();
746 }
747 }
748 featuresToJson(mainFSinMem, json, featureTypeAttributes, attrNames);
749 }
750
751 private void reportAggregateData(JSONObject json) throws Exception {
752 SimpleFeatureType ft = layer.getFeatureType();
753 List<AttributeDescriptor> featureTypeAttributes = ft.getAttributes();
754 SimpleFeatureSource fs = (SimpleFeatureSource) ft.openGeoToolsFeatureSource();
755
756 List<String> tPropnames = new ArrayList(attrNames);
757 List<String> foreignAttrNames = new ArrayList<>();
758
759 for (String a : attrNames) {
760 if (fs.getSchema().getDescriptor(a) == null) {
761
762 foreignAttrNames.add(a);
763 tPropnames.remove(a);
764 }
765 }
766 foreignAttrNames.add(TERREINID_RELATED_FIELDNAME);
767 tPropnames.add(TERREINID_FIELDNAME);
768 tPropnames.add(GEMEENTE_FIELDNAME);
769 tPropnames.add(REGIO_FIELDNAME);
770 tPropnames.add(TERREIN_FIELDNAME);
771
772 Filter filter = ECQL.toFilter(this.gebiedsNaamQuery);
773 Query q = new Query(fs.getName().toString());
774 q.setPropertyNames(tPropnames);
775 q.setFilter(filter);
776 q.setHandle("aggregatie-rapport");
777 q.setMaxFeatures(FeatureToJson.MAX_FEATURES);
778 log.debug("aggregatie query:" + q);
779
780 try {
781
782 org.opengis.feature.simple.SimpleFeatureType type;
783 SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
784 tb.setName("AGGREGATE");
785 for (String prop : tPropnames) {
786 org.opengis.feature.type.AttributeDescriptor attrDescName = fs.getSchema().getDescriptor(prop);
787 if (attrDescName != null) {
788 tb.add(attrDescName);
789 }
790 }
791 tb.add(GEBIED_FIELDNAME, String.class);
792
793 AttributeDescriptor g = new AttributeDescriptor();
794 g.setName(GEBIED_FIELDNAME);
795 g.setAlias("gebiedsnaam");
796 g.setType(AttributeDescriptor.TYPE_STRING);
797 featureTypeAttributes.add(0, g);
798
799 SimpleFeatureCollection sfc = DataUtilities.collection(fs.getFeatures(q).features());
800
801 if (!foreignAttrNames.isEmpty()) {
802 SimpleFeatureType relFt = this.getRelatedSFT(ft, RELATED_FT_NAME);
803 SimpleFeatureSource foreignFs = (SimpleFeatureSource) relFt.openGeoToolsFeatureSource();
804
805
806 for (String prop : foreignAttrNames) {
807 org.opengis.feature.type.AttributeDescriptor attrDescName = foreignFs.getSchema().getDescriptor(prop);
808 if (attrDescName != null) {
809 tb.add(attrDescName);
810 }
811 }
812 tb.add(TERREINID_RELATED_FIELDNAME, Integer.class);
813 type = tb.buildFeatureType();
814
815
816 featureTypeAttributes.addAll(relFt.getAttributes());
817
818
819 StringBuilder in = new StringBuilder();
820 HashMap<Integer, SimpleFeature> parentFeatures = new HashMap<>();
821 SimpleFeatureIterator inMemFeats = sfc.features();
822 while (inMemFeats.hasNext()) {
823 SimpleFeature f = inMemFeats.next();
824 in.append(f.getAttribute(TERREINID_FIELDNAME)).append(",");
825 parentFeatures.put((Integer) f.getAttribute(TERREINID_FIELDNAME), f);
826 }
827 inMemFeats.close();
828
829
830 Query foreignQ = new Query(foreignFs.getName().toString());
831 foreignQ.setHandle("aggregatie-rapport-related");
832 foreignQ.setPropertyNames(foreignAttrNames);
833 String query = TERREINID_RELATED_FIELDNAME + " IN (" + in.substring(0, in.length() - 1) + ")";
834 log.debug("aggregatie-rapport-related: " + query);
835 foreignQ.setFilter(ECQL.toFilter(query));
836
837 try {
838
839 SimpleFeatureCollection relatedFC = foreignFs.getFeatures(foreignQ);
840 SimpleFeatureBuilder sfBuilder = new SimpleFeatureBuilder(type);
841 SimpleFeatureIterator sfcIter = relatedFC.features();
842 ArrayList<SimpleFeature> newfeats = new ArrayList<>();
843
844 boolean firsttimeForP = true;
845 Set<SimpleFeature> firsttimeForPSet = new HashSet<>();
846 while (sfcIter.hasNext()) {
847
848 SimpleFeature f = sfcIter.next();
849 SimpleFeature n = SimpleFeatureBuilder.retype(f, sfBuilder);
850
851
852
853 SimpleFeature p = parentFeatures.get((Integer) f.getAttribute(TERREINID_RELATED_FIELDNAME));
854 for (Property a : p.getProperties()) {
855 if (firsttimeForPSet.contains(p)) {
856 if (!attrNames.contains(a.getName().toString())) {
857 n.setAttribute(a.getName(), a.getValue());
858 }
859 } else {
860 if (tPropnames.contains(a.getName().toString())) {
861 n.setAttribute(a.getName(), a.getValue());
862 }
863 }
864 }
865 newfeats.add(n);
866 firsttimeForPSet.add(p);
867 }
868 sfcIter.close();
869 sfc = DataUtilities.collection(newfeats);
870 } finally {
871 foreignFs.getDataStore().dispose();
872 }
873 } else {
874 type = tb.buildFeatureType();
875 }
876
877
878 Set<String> regions = new HashSet<>();
879 switch (aggregationLevel) {
880 case REGIO:
881
882 regions.add(regio);
883 sfc = aggregateFields(sfc, type, regions, attrNames, REGIO_FIELDNAME);
884 break;
885 case GEMEENTE:
886 if (this.areaType == QueryArea.TERREIN) {
887 regions.add(gemeente);
888 } else {
889
890 SimpleFeatureIterator iter = sfc.features();
891 try {
892 while (iter.hasNext()) {
893 SimpleFeature f = iter.next();
894 regions.add((String) f.getAttribute(GEMEENTE_FIELDNAME));
895 }
896 } finally {
897 iter.close();
898 }
899 }
900 sfc = aggregateFields(sfc, type, regions, attrNames, GEMEENTE_FIELDNAME);
901 break;
902 case TERREIN:
903 if (this.areaType == QueryArea.TERREIN) {
904 regions.add(terrein);
905 } else {
906
907 SimpleFeatureIterator iter = sfc.features();
908 try {
909 while (iter.hasNext()) {
910 SimpleFeature f = iter.next();
911 regions.add((String) f.getAttribute(TERREIN_FIELDNAME));
912 }
913 } finally {
914 iter.close();
915 }
916 }
917 sfc = aggregateFields(sfc, type, regions, attrNames, TERREIN_FIELDNAME);
918 break;
919 }
920
921 attrNames.add(GEBIED_FIELDNAME);
922 featuresToJson(sfc, json, featureTypeAttributes, attrNames);
923 } finally {
924 fs.getDataStore().dispose();
925 }
926
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943 private SimpleFeatureCollection aggregateFields(
944 SimpleFeatureCollection sfc,
945 org.opengis.feature.simple.SimpleFeatureType type,
946 Set<String> featNames,
947 List<String> aggregateFieldNames,
948 String gebiedFieldName) {
949
950
951 Map<String, SimpleFeature> newfeats = new TreeMap<>();
952 for (String fName : featNames) {
953 SimpleFeature newfeat = DataUtilities.template(type);
954 for (String aggrName : aggregateFieldNames) {
955 newfeat.setAttribute(aggrName, 0);
956 }
957 newfeat.setAttribute(GEBIED_FIELDNAME, fName);
958 newfeats.put(fName, newfeat);
959 }
960
961
962
963 SimpleFeatureIterator items = sfc.features();
964 while (items.hasNext()) {
965 SimpleFeature f = items.next();
966 SimpleFeature newFeat = newfeats.get((String) f.getAttribute(gebiedFieldName));
967
968 for (String aggrFieldName : aggregateFieldNames) {
969 if (f.getAttribute(aggrFieldName) != null) {
970
971 newFeat.setAttribute(aggrFieldName,
972 ((Number) newFeat.getAttribute(aggrFieldName)).doubleValue()
973 + ((Number) f.getAttribute(aggrFieldName)).doubleValue()
974 );
975 }
976 }
977 }
978 items.close();
979 ArrayList<SimpleFeature> feats = new ArrayList<>(newfeats.values());
980 return DataUtilities.collection(feats);
981 }
982
983
984 public String getData() {
985 return data;
986 }
987
988 public void setData(String data) {
989 this.data = data;
990 }
991
992 public String getFilename() {
993 return filename;
994 }
995
996 public void setFilename(String filename) {
997 this.filename = filename;
998 }
999
1000 public String getMimetype() {
1001 return mimetype;
1002 }
1003
1004 public void setMimetype(String mimetype) {
1005 this.mimetype = mimetype;
1006 }
1007
1008 @Override
1009 public void setContext(ActionBeanContext context) {
1010 this.context = context;
1011 }
1012
1013 @Override
1014 public ActionBeanContext getContext() {
1015 return context;
1016 }
1017
1018 public Application getApplication() {
1019 return application;
1020 }
1021
1022 public void setApplication(Application application) {
1023 this.application = application;
1024 }
1025
1026 public ApplicationLayer getAppLayer() {
1027 return appLayer;
1028 }
1029
1030 public void setAppLayer(ApplicationLayer appLayer) {
1031 this.appLayer = appLayer;
1032 }
1033
1034 public String getRegio() {
1035 return regio;
1036 }
1037
1038 public void setRegio(String regio) {
1039 this.regio = regio;
1040 }
1041
1042 public String getGemeente() {
1043 return gemeente;
1044 }
1045
1046 public void setGemeente(String gemeente) {
1047 this.gemeente = gemeente;
1048 }
1049
1050 public String getTerrein() {
1051 return terrein;
1052 }
1053
1054 public void setTerrein(String terrein) {
1055 this.terrein = terrein;
1056 }
1057
1058 public ReportType getReportType() {
1059 return reportType;
1060 }
1061
1062 public void setReportType(ReportType reportType) {
1063 this.reportType = reportType;
1064 }
1065
1066 public QueryArea getAggregationLevel() {
1067 return aggregationLevel;
1068 }
1069
1070 public void setAggregationLevel(QueryArea aggregationLevel) {
1071 this.aggregationLevel = aggregationLevel;
1072 }
1073
1074 public AggregationLevelDate getAggregationLevelDate() {
1075 return aggregationLevelDate;
1076 }
1077
1078 public void setAggregationLevelDate(AggregationLevelDate aggregationLevelDate) {
1079 this.aggregationLevelDate = aggregationLevelDate;
1080 }
1081
1082 public Date getFromDate() {
1083 return fromDate;
1084 }
1085
1086 public void setFromDate(Date fromDate) {
1087 this.fromDate = fromDate;
1088 }
1089
1090 public Date getToDate() {
1091 return toDate;
1092 }
1093
1094 public void setToDate(Date toDate) {
1095 this.toDate = toDate;
1096 }
1097
1098 public List<String> getAttrNames() {
1099 return attrNames;
1100 }
1101
1102 public void setAttrNames(List<String> attrNames) {
1103 this.attrNames = attrNames;
1104 }
1105
1106
1107 }