1
2
3
4
5
6
7 package nl.mineleni.cbsviewer.servlet.wms;
8
9 import java.io.BufferedReader;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.InputStreamReader;
13 import java.io.Reader;
14 import java.io.StringWriter;
15 import java.io.Writer;
16 import java.util.Iterator;
17
18 import javax.xml.parsers.ParserConfigurationException;
19
20 import nl.mineleni.cbsviewer.util.LabelsBundle;
21 import nl.mineleni.cbsviewer.util.xml.LayerDescriptor;
22
23 import org.geotools.GML;
24 import org.geotools.GML.Version;
25 import org.geotools.data.simple.SimpleFeatureCollection;
26 import org.geotools.data.simple.SimpleFeatureIterator;
27 import org.geotools.feature.DefaultFeatureCollection;
28 import org.geotools.feature.simple.SimpleFeatureBuilder;
29 import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
30 import org.jsoup.Jsoup;
31 import org.jsoup.nodes.Element;
32 import org.opengis.feature.simple.SimpleFeature;
33 import org.opengis.feature.simple.SimpleFeatureType;
34 import org.opengis.geometry.primitive.Point;
35 import org.opengis.referencing.crs.CoordinateReferenceSystem;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38 import org.xml.sax.SAXException;
39
40
41
42
43
44
45
46
47
48
49
50 public final class FeatureInfoResponseConverter {
51
52
53
54
55 public enum CONVERTER_TYPE {
56
57
58 GMLTYPE("application/vnd.ogc.gml"),
59
60 HTMLTYPE("text/html"),
61
62 XMLTYPE("application/vnd.ogc.wms_xml");
63
64
65 private final String type;
66
67
68
69
70
71
72
73 CONVERTER_TYPE(final String type) {
74 this.type = type;
75 }
76
77
78
79
80
81
82
83
84 @Override
85 public String toString() {
86 return this.type;
87 }
88 }
89
90
91 private static final int BUFFERSIZE = 1024;
92
93
94 private static final Logger LOGGER = LoggerFactory
95 .getLogger(FeatureInfoResponseConverter.class);
96
97
98 private static final AttributesNamesFilter NAMESFILTER = new AttributesNamesFilter();
99
100
101 private static final LabelsBundle RESOURCES = new LabelsBundle();
102
103
104 private static final AttributeValuesFilter VALUESFILTER = new AttributeValuesFilter();
105
106
107
108
109 private FeatureInfoResponseConverter() {
110
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125 private static String cleanupHTML(final InputStream htmlStream,
126 final LayerDescriptor layer) throws IOException {
127 final Element table = Jsoup.parse(convertStreamToString(htmlStream))
128 .select("table").first();
129 if (table == null) {
130 LOGGER.debug("Geen attribuut info voor deze locatie/zoomnivo.");
131 return RESOURCES.getString("KEY_INFO_GEEN_FEATURES");
132 }
133
134 final DefaultFeatureCollection featureCollection = new DefaultFeatureCollection(
135 "internal");
136 final SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
137
138
139
140 final Element headers = table.select("tr:first-child").first();
141 if (headers != null) {
142 final Iterator<Element> iterTHs = headers.select("th").iterator();
143 while (iterTHs.hasNext()) {
144 b.add(iterTHs.next().text(), String.class);
145 }
146 }
147 b.setDefaultGeometry("point");
148 b.setCRS(null);
149 b.nillable(true).add("point", Point.class,
150 (CoordinateReferenceSystem) null);
151 b.setName("tablerow");
152 final SimpleFeatureType type = b.buildFeatureType();
153 final SimpleFeatureBuilder builder = new SimpleFeatureBuilder(type);
154 final Iterator<Element> rows = table.select("tr:not(:first-child)")
155 .iterator();
156 while (rows.hasNext()) {
157 final Iterator<Element> iterTH = headers.select("th").iterator();
158 final Iterator<Element> iterTDs = rows.next().select("td")
159 .iterator();
160 final SimpleFeature f = builder.buildFeature(null);
161 while (iterTDs.hasNext()) {
162 f.setAttribute(iterTH.next().text(), iterTDs.next().text());
163 }
164 f.setDefaultGeometry(null);
165 featureCollection.add(f);
166 }
167
168 return featureCollectionConverter(featureCollection, layer);
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182 private static String convertGML(final InputStream gmlStream,
183 final LayerDescriptor layer) throws IOException {
184 try {
185 final GML gml = new GML(Version.WFS1_0);
186 return featureCollectionConverter(
187 gml.decodeFeatureCollection(gmlStream), layer);
188 } catch (ParserConfigurationException | SAXException e) {
189 LOGGER.error("Fout tijdens parsen van GML. ", e);
190 return "";
191 } finally {
192 gmlStream.close();
193 }
194
195 }
196
197
198
199
200
201
202
203
204
205
206 private static String convertStreamToString(final InputStream is)
207 throws IOException {
208 final Writer writer = new StringWriter();
209 if (is != null) {
210
211 final char[] buffer = new char[BUFFERSIZE];
212 try {
213 final Reader reader = new BufferedReader(new InputStreamReader(
214 is, "UTF-8"));
215 int n;
216 while ((n = reader.read(buffer)) != -1) {
217 writer.write(buffer, 0, n);
218 }
219 } finally {
220 is.close();
221 }
222 }
223 return writer.toString();
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 public static String convertToHTMLTable(final InputStream input,
241 final CONVERTER_TYPE type, final LayerDescriptor layer)
242 throws IOException {
243 switch (type) {
244 case GMLTYPE:
245 return convertGML(input, layer);
246 case HTMLTYPE:
247 return cleanupHTML(input, layer);
248 case XMLTYPE:
249 throw new IOException(CONVERTER_TYPE.XMLTYPE
250 + " (XMLTYPE) wordt niet ondersteund.");
251 default:
252 return convertStreamToString(input);
253 }
254 }
255
256
257
258
259
260
261
262
263
264
265 private static String featureCollectionConverter(
266 final SimpleFeatureCollection features, final LayerDescriptor layer) {
267
268 final StringBuilder sb = new StringBuilder();
269 final String[] fieldNames = layer.getAttributes().split(",\\s*");
270
271 if ((features != null) && (features.size() > 0)) {
272
273 sb.append("<table id=\"attribuutTabel\" class=\"attribuutTabel\">");
274 sb.append("<caption>");
275 sb.append(RESOURCES.getString("KEY_INFO_TABEL_CAPTION"));
276 sb.append("</caption><thead><tr>");
277 for (final String n : fieldNames) {
278 sb.append("<th scope=\"col\">");
279 sb.append(NAMESFILTER.filterValue(n, layer.getId()));
280 sb.append("</th>");
281 }
282 sb.append("</tr></thead><tbody>");
283 int i = 0;
284 SimpleFeatureIterator iter = features.features();
285 while (iter.hasNext()) {
286 sb.append("<tr class=\"")
287 .append(((i++ % 2) == 0) ? "odd" : "even")
288 .append("\">");
289 final SimpleFeature f = iter.next();
290 for (final String n : fieldNames) {
291 if (VALUESFILTER.hasFilters()) {
292 sb.append("<td>")
293 .append(VALUESFILTER.filterValue(f
294 .getAttribute(n))).append("</td>");
295 } else {
296 sb.append("<td>").append(f.getAttribute(n))
297 .append("</td>");
298 }
299 }
300 sb.append("</tr>");
301 }
302 sb.append("</tbody></table>");
303 iter.close();
304 iter = null;
305 LOGGER.debug("Gemaakte HTML tabel: " + sb);
306 return sb.toString();
307 } else {
308 LOGGER.debug("Geen attribuut info voor deze locatie/zoomnivo.");
309 return RESOURCES.getString("KEY_INFO_GEEN_FEATURES");
310 }
311 }
312 }