Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | dec4257ad570 |
children |
comparison
equal
deleted
inserted
replaced
1027:fca4b5eb8d2f | 1119:7c4f81f74c47 |
---|---|
1 /* | |
2 * Copyright (c) 2010 by Intevation GmbH | |
3 * | |
4 * This program is free software under the LGPL (>=v2.1) | |
5 * Read the file LGPL.txt coming with the software for details | |
6 * or visit http://www.gnu.org/licenses/ if it does not exist. | |
7 */ | |
8 | |
9 package de.intevation.gnv.state.layer; | |
10 | |
11 import java.io.File; | |
12 import java.io.IOException; | |
13 import java.io.OutputStream; | |
14 import java.util.ArrayList; | |
15 import java.util.Collection; | |
16 import java.util.Iterator; | |
17 | |
18 import org.apache.log4j.Logger; | |
19 import org.w3c.dom.Document; | |
20 import org.w3c.dom.Node; | |
21 | |
22 import com.vividsolutions.jts.geom.Envelope; | |
23 import com.vividsolutions.jts.geom.Geometry; | |
24 import com.vividsolutions.jts.io.ParseException; | |
25 import com.vividsolutions.jts.io.WKTReader; | |
26 | |
27 import de.intevation.artifacts.common.utils.Config; | |
28 import de.intevation.artifacts.common.utils.XMLUtils; | |
29 import de.intevation.artifacts.ArtifactNamespaceContext; | |
30 import de.intevation.artifacts.CallContext; | |
31 import de.intevation.gnv.artifacts.context.GNVArtifactContext; | |
32 import de.intevation.gnv.geobackend.base.Result; | |
33 import de.intevation.gnv.geobackend.base.query.QueryExecutor; | |
34 import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; | |
35 import de.intevation.gnv.geobackend.base.query.exception.QueryException; | |
36 import de.intevation.gnv.state.InputData; | |
37 import de.intevation.gnv.state.OutputStateBase; | |
38 import de.intevation.gnv.state.exception.StateException; | |
39 import de.intevation.gnv.utils.ArtifactXMLUtilities; | |
40 import de.intevation.gnv.utils.ExclusiveExec; | |
41 import de.intevation.gnv.utils.FileUtils; | |
42 import de.intevation.gnv.utils.MapfileGenerator; | |
43 import de.intevation.gnv.utils.MetaWriter; | |
44 import de.intevation.gnv.utils.ShapeFileWriter; | |
45 | |
46 /** | |
47 * This <code>OutputState</code> is used for Layer-Products. | |
48 * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a> | |
49 * | |
50 */ | |
51 public class LayerOutputState extends OutputStateBase { | |
52 | |
53 /** | |
54 * the logger, used to log exceptions and additonaly information | |
55 */ | |
56 private static Logger log = Logger.getLogger(LayerOutputState.class); | |
57 | |
58 /** | |
59 * The UID of this Class. | |
60 */ | |
61 private static final long serialVersionUID = 9180957321704424049L; | |
62 | |
63 /** | |
64 * The Basename of the Templates for the WMS-Exports | |
65 */ | |
66 public static final String LAYER_MODEL = "layer"; | |
67 | |
68 /** | |
69 * The Name of the Shapefile which will be generated. | |
70 */ | |
71 public static final String SHAPEFILE_NAME = "data"; | |
72 | |
73 /** | |
74 * The ID for the Query fetching the Layer from the DB | |
75 */ | |
76 private String dataQueryID = null; | |
77 | |
78 /** | |
79 * The ID for the Query fetching the Geometry from the DB | |
80 * which should be used to Clip the Layerdata | |
81 */ | |
82 private String geometryQueryID = null; | |
83 | |
84 /** | |
85 * The ID of the Query for fetching the Columnnames of the Table which | |
86 * should put into the Shapefile. | |
87 */ | |
88 private String columnQueryID = null; | |
89 | |
90 /** | |
91 * The ID of the Query for fetching the Information which kind of Geometry | |
92 * should be put into the Shapefile. | |
93 */ | |
94 private String geometryTypeQueryID = null; | |
95 | |
96 /** | |
97 * The ID for the Value which will hold the Geometry-Value | |
98 */ | |
99 private String geometryID = null; | |
100 | |
101 /** | |
102 * Flag for synchronized Access of the Shapefile. | |
103 */ | |
104 private Boolean shapeFileLock = new Boolean(true); | |
105 | |
106 /** | |
107 * The Path where the Shapefile is stored. | |
108 */ | |
109 private String shapeFilePath; | |
110 | |
111 /** | |
112 * Constructor | |
113 */ | |
114 public LayerOutputState() { | |
115 super(); | |
116 } | |
117 | |
118 public void out(Document format, Collection<InputData> inputData, | |
119 OutputStream outputStream, String uuid, | |
120 CallContext callContext) throws StateException { | |
121 log.debug("LayerOutputState.out"); | |
122 String outputMode = XMLUtils.xpathString( | |
123 format, XPATH_OUTPUT_MODE, ArtifactNamespaceContext.INSTANCE); | |
124 if (outputMode.equalsIgnoreCase("wms")) { | |
125 | |
126 Collection<LayerMetaData> layerMetaData = | |
127 this.getRequestedLayerMetadata(); | |
128 if (layerMetaData != null && !layerMetaData.isEmpty()){ | |
129 XMLUtils.toStream(this.getWMS(uuid, callContext, | |
130 layerMetaData,inputData), | |
131 outputStream); | |
132 }else{ | |
133 this.writeExceptionReport2Stream(outputStream); | |
134 } | |
135 }else if (outputMode.equalsIgnoreCase("zip")){ | |
136 Collection<LayerMetaData> layerMetaData = | |
137 this.getRequestedLayerMetadata(); | |
138 | |
139 if (layerMetaData != null && !layerMetaData.isEmpty()){ | |
140 this.writeZip(uuid, callContext, | |
141 outputStream, layerMetaData); | |
142 }else{ | |
143 this.writeExceptionReport2Stream(outputStream); | |
144 } | |
145 | |
146 } | |
147 } | |
148 | |
149 /** | |
150 * Writes an exception to an output stream. | |
151 * | |
152 * @param outputStream The output stream used to write the exception to. | |
153 */ | |
154 private void writeExceptionReport2Stream(OutputStream outputStream) { | |
155 Document document = XMLUtils.newDocument(); | |
156 ArtifactXMLUtilities. | |
157 createExceptionReport("No Data to Export", document); | |
158 XMLUtils.toStream(document,outputStream); | |
159 } | |
160 | |
161 /** | |
162 * Returns the Metadata for the requested Layers for fetching the data | |
163 * of the Layer and generating the Layer and WMS. | |
164 * @return the Metadata for the requested Layers | |
165 */ | |
166 private Collection<LayerMetaData> getRequestedLayerMetadata(){ | |
167 log.debug("LayerOutputState.getRequestedLayerMetadata"); | |
168 Collection<Result> result = this.getData(this.queryID); | |
169 Collection<LayerMetaData> returnValue = null; | |
170 if (result != null){ | |
171 QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() | |
172 .getQueryExecutor(); | |
173 Iterator<Result> it = result.iterator(); | |
174 returnValue = new ArrayList<LayerMetaData>(result.size()); | |
175 while (it.hasNext()){ | |
176 Result resultValue = it.next(); | |
177 String table = resultValue.getString(0); | |
178 String geometryType = this.getGeometryType(table, queryExecutor); | |
179 String where = resultValue.getString(1); | |
180 String columns = this.fetchColumns(table); | |
181 String templateID = resultValue.getString(2); | |
182 String layername = resultValue.getString(3); | |
183 String[] queryValues = null; | |
184 String geometryWKT = null; | |
185 if (this.geometryID != null){ | |
186 InputData geometryInputData = | |
187 this.inputData.get(this.geometryID); | |
188 if (geometryInputData != null){ | |
189 try { | |
190 | |
191 Collection<Result> geometryData = queryExecutor | |
192 .executeQuery(this.geometryQueryID, | |
193 new String[]{geometryInputData.getValue()}); | |
194 Iterator<Result> git = geometryData.iterator(); | |
195 if (git.hasNext()){ | |
196 Result geometryValue = git.next(); | |
197 geometryWKT = geometryValue.getString(0); | |
198 } | |
199 } catch (QueryException e) { | |
200 log.error(e,e); | |
201 } | |
202 queryValues = new String[]{columns, | |
203 table, | |
204 where, | |
205 geometryWKT}; | |
206 }else{ | |
207 //Look into the presetting for an WKT | |
208 InputData geometryWKTData = this.preSettings != null ? | |
209 this.preSettings.get("geometry") : | |
210 null ; | |
211 if (geometryWKTData != null){ | |
212 queryValues = new String[]{columns, | |
213 table, | |
214 where, | |
215 geometryWKTData.getValue()}; | |
216 geometryWKT = geometryWKTData.getValue(); | |
217 }else{ | |
218 queryValues = new String[]{columns,table,where}; | |
219 } | |
220 } | |
221 }else{ | |
222 //Look into the presetting for an WKT | |
223 InputData geometryWKTData = this.preSettings != null ? | |
224 this.preSettings.get("geometry") : | |
225 null ; | |
226 if (geometryWKTData != null){ | |
227 queryValues = new String[]{columns, | |
228 table, | |
229 where, | |
230 geometryWKTData.getValue()}; | |
231 }else{ | |
232 queryValues = new String[]{columns,table,where}; | |
233 } | |
234 } | |
235 returnValue.add(new LayerMetaData( | |
236 table, geometryType, where, columns, | |
237 templateID, queryValues, geometryWKT, layername)); | |
238 } | |
239 } | |
240 return returnValue; | |
241 } | |
242 | |
243 /** | |
244 * Fetches the Data from the Databasebackend. | |
245 * | |
246 * @return the resultdata. | |
247 */ | |
248 protected Collection<Result> fetchData(LayerMetaData layerMetaData, Envelope mbr){ | |
249 log.debug("LayerOutputState.fetchData"); | |
250 Collection<Result> data = null; | |
251 QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() | |
252 .getQueryExecutor(); | |
253 try { | |
254 data = queryExecutor.executeQuery(dataQueryID, | |
255 layerMetaData.getQueryValues()); | |
256 if (data != null){ | |
257 WKTReader wktReader = new WKTReader(); | |
258 Geometry border = null; | |
259 if (layerMetaData.getGeometryWKT() != null){ | |
260 border = wktReader.read(layerMetaData.getGeometryWKT()); | |
261 } | |
262 Iterator<Result> dataIt = data.iterator(); | |
263 while (dataIt.hasNext()){ | |
264 // Trim the Geometries using the | |
265 // Geometry if one is available. | |
266 Result current = dataIt.next(); | |
267 String currentWKT = current.getString(0); | |
268 Geometry currentGeometry = null; | |
269 try { | |
270 currentGeometry = wktReader.read(currentWKT); | |
271 } catch (Exception e) { | |
272 log.error("Error parsing Geometry "+ currentWKT); | |
273 log.error(e,e); | |
274 } | |
275 if (currentGeometry != null){ | |
276 if (border != null){ | |
277 currentGeometry = currentGeometry.intersection(border); | |
278 current.addColumnValue(0, currentGeometry.toText()); | |
279 } | |
280 if (mbr.isNull()){ | |
281 mbr.init(currentGeometry.getEnvelopeInternal()); | |
282 }else{ | |
283 mbr.expandToInclude(currentGeometry.getEnvelopeInternal()); | |
284 } | |
285 } | |
286 } | |
287 } | |
288 } catch (QueryException e) { | |
289 log.error(e,e); | |
290 } catch (ParseException e){ | |
291 log.error(e,e); | |
292 } | |
293 return data; | |
294 } | |
295 | |
296 | |
297 /** | |
298 * This method determines the geometry type on basis of a table name. | |
299 * | |
300 * @param tableName Name of the table in the database. | |
301 * @param queryExecutor The QueryExecutor. | |
302 * @return the geometry type as string (e.g. MultiPolygon, Polygon, etc). | |
303 */ | |
304 private String getGeometryType(String tableName, | |
305 QueryExecutor queryExecutor){ | |
306 String returnValue = null; | |
307 String[] tables = tableName.toUpperCase().split(","); | |
308 String[] filter = tables[0].split("\\."); | |
309 try { | |
310 Collection<Result> result = | |
311 queryExecutor.executeQuery(this.geometryTypeQueryID, filter); | |
312 if (result != null && !result.isEmpty()) | |
313 { | |
314 int geometryCode = result.iterator().next().getInteger(0); | |
315 if (geometryCode == 11 || | |
316 geometryCode == 10){ | |
317 returnValue = "MultiPolygon"; | |
318 }else if (geometryCode == 9 || | |
319 geometryCode == 8){ | |
320 returnValue = "MultiLineString"; | |
321 }else if (geometryCode == 7){ | |
322 returnValue = "MultiPoint"; | |
323 }else if (geometryCode == 6){ | |
324 returnValue = "GeometryCollection"; | |
325 }else if (geometryCode == 5 || | |
326 geometryCode == 4){ | |
327 returnValue = "Polygon"; | |
328 }else if (geometryCode == 3 || | |
329 geometryCode == 2){ | |
330 returnValue = "LineString"; | |
331 }else if (geometryCode == 1){ | |
332 returnValue = "Point"; | |
333 }else if (geometryCode == 0){ | |
334 returnValue = "Geometry"; | |
335 } | |
336 } | |
337 } catch (QueryException e) { | |
338 log.error(e,e); | |
339 } | |
340 return returnValue; | |
341 } | |
342 | |
343 | |
344 /** | |
345 * Fetch the columns of a specific table. | |
346 * | |
347 * @param tableName The name of the table. | |
348 * @return the columns as string. | |
349 */ | |
350 private String fetchColumns(String tableName){ | |
351 String returnValue = null; | |
352 try { | |
353 String[] tables = tableName.toUpperCase().split(","); | |
354 String[] filter = tables[0].split("\\."); | |
355 // Only use the first Table the second one will be ignored. | |
356 QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() | |
357 .getQueryExecutor(); | |
358 Collection<Result> columnData = queryExecutor. | |
359 executeQuery(this.columnQueryID, | |
360 filter); | |
361 if (columnData != null && !columnData.isEmpty()){ | |
362 StringBuffer sb = new StringBuffer(); | |
363 synchronized (sb) { | |
364 Iterator<Result> it = columnData.iterator(); | |
365 while(it.hasNext()){ | |
366 Result current = it.next(); | |
367 sb.append(current.getString(0)); | |
368 if (it.hasNext()){ | |
369 sb.append(" , "); | |
370 } | |
371 } | |
372 } | |
373 returnValue = sb.toString(); | |
374 } | |
375 } catch (QueryException e) { | |
376 log.error(e,e); | |
377 } | |
378 return returnValue; | |
379 } | |
380 | |
381 | |
382 @Override | |
383 public void setup(Node configuration) { | |
384 log.debug("LayerOutputState.setup"); | |
385 super.setup(configuration); | |
386 this.dataQueryID = Config.getStringXPath(configuration, | |
387 "queryID-layerdata"); | |
388 this.geometryID = Config.getStringXPath(configuration, | |
389 "inputvalue-geometry"); | |
390 this.geometryQueryID = Config.getStringXPath(configuration, | |
391 "queryID-geometry"); | |
392 | |
393 this.columnQueryID = "layer_colums"; //Config.getStringXPath(configuration, | |
394 // "queryID-columns"); | |
395 this.geometryTypeQueryID = "geometry_type"; | |
396 } | |
397 | |
398 | |
399 /** | |
400 * Write the resultdata to shapefiles. | |
401 * | |
402 * @param uuid The UUID of the current artifact. | |
403 * @param data The finalized data used for shapefile creation. | |
404 * @param callContext The CallContext object. | |
405 * @param geometryType The geometry type. | |
406 * @return the shapefile path. | |
407 */ | |
408 protected String writeToShapeFile( | |
409 String uuid, | |
410 Collection<Result> data, | |
411 CallContext callContext, | |
412 String geometryType, | |
413 int layerNumber | |
414 ) { | |
415 boolean success = false; | |
416 if (data != null && !data.isEmpty()){ | |
417 File shapeDir = new File(shapeFilePath); | |
418 try { | |
419 File shapeFile = new File(shapeDir, createShapeFileName(layerNumber)); | |
420 if (!ShapeFileWriter.writeDataToFile(shapeFile, "data", data,geometryType)){ | |
421 log.error("writing data into shapefile failed"); | |
422 return null; | |
423 } | |
424 success = true; | |
425 callContext.afterCall(CallContext.STORE); | |
426 return shapeFilePath; | |
427 } | |
428 finally { | |
429 if (!success) { | |
430 FileUtils.deleteRecursive(shapeDir); | |
431 } | |
432 } | |
433 }else{ | |
434 return null; | |
435 } | |
436 } | |
437 | |
438 /** | |
439 * Check if the ShapeDir exists and if it exists delete all Contents | |
440 * in it. If it not exists the Director will be created. | |
441 * @param baseDir the BaseDirectory for all ShapeDirs | |
442 * @param uuid the UUID which is used to create the Directory | |
443 * @return true if the directory exists or could be created. | |
444 * false if the directory could not be created. | |
445 */ | |
446 private boolean createShapeDir(File baseDir, String uuid){ | |
447 File shapeDir = new File(baseDir, uuid); | |
448 boolean createdDir = false; | |
449 synchronized (shapeFileLock) { | |
450 if (shapeDir.exists()) { | |
451 FileUtils.deleteContent(shapeDir); // TODO Place on getZip and getWMS | |
452 } | |
453 else if (!shapeDir.mkdirs()) { | |
454 log.error("cannot create directory '" | |
455 + shapeDir.getAbsolutePath() + "'"); | |
456 return false; | |
457 } | |
458 createdDir = true; | |
459 } | |
460 shapeFilePath = shapeDir.getAbsolutePath(); | |
461 return createdDir; | |
462 } | |
463 | |
464 /** | |
465 * Create a zip archive with the shapefiles of the given shapefiles path and | |
466 * write it to <code>output</code>. | |
467 * | |
468 * @param uuid The UUID of the current artifact. | |
469 * @param callContext The CallContext object. | |
470 * @param output The output stream. | |
471 * @param data The data to be written to shapefile. | |
472 * @param geometryType The geometry type. | |
473 * @throws StateException if an error occured while zipfile creation. | |
474 */ | |
475 protected void writeZip( | |
476 String uuid, | |
477 CallContext callContext, | |
478 OutputStream output, | |
479 Collection<LayerMetaData> layerMetaData | |
480 ) | |
481 throws StateException | |
482 { | |
483 try { | |
484 String p = getShapeFilePath(); | |
485 if (p != null) { | |
486 File dir = new File(p); | |
487 if (dir.isDirectory()) { | |
488 FileUtils.createZipArchive(dir, output); | |
489 } | |
490 } | |
491 else { | |
492 File baseDir = shapefileDirectory(callContext); | |
493 if (!this.createShapeDir(baseDir, uuid)){ | |
494 return; | |
495 } | |
496 Iterator<LayerMetaData> it = layerMetaData.iterator(); | |
497 int i = 1; | |
498 Envelope mbr = new Envelope(); | |
499 while(it.hasNext()){ | |
500 LayerMetaData lmd = it.next(); | |
501 Collection<Result> data = this.fetchData(lmd, mbr); | |
502 p = writeToShapeFile(uuid, data, callContext,lmd.getGeometryType(),i++); | |
503 } | |
504 if (p != null) { | |
505 FileUtils.createZipArchive(new File(p), output); | |
506 } | |
507 } | |
508 } | |
509 catch (IOException ioe) { | |
510 log.error(ioe.getLocalizedMessage(), ioe); | |
511 } | |
512 } | |
513 | |
514 /** | |
515 * Returns the shapefile path. | |
516 * | |
517 * @return the shapefile path. | |
518 */ | |
519 public String getShapeFilePath() { | |
520 synchronized (shapeFileLock) { | |
521 return shapeFilePath; | |
522 } | |
523 } | |
524 | |
525 | |
526 /** | |
527 * Set the shapefile path. | |
528 */ | |
529 public void setShapeFilePath(String shapeFilePath) { | |
530 synchronized (shapeFileLock) { | |
531 this.shapeFilePath = shapeFilePath; | |
532 } | |
533 } | |
534 | |
535 /** | |
536 * Returns the basic-directory where the Shapefiles should be placed in. | |
537 * @param callContext the Context of this Call | |
538 * @return the Directory where the Shapefiles could be placed in. | |
539 * (Please create an own directory in this dir and not put the | |
540 * Files directly in it) | |
541 */ | |
542 private static File shapefileDirectory(CallContext callContext) { | |
543 // Code was taken from HorizontalCrossSectionMeshOutputState | |
544 GNVArtifactContext context = | |
545 (GNVArtifactContext)callContext.globalContext(); | |
546 File dir = (File)context.get( | |
547 GNVArtifactContext.HORIZONTAL_CROSS_SECTION_RESULT_SHAPEFILE_PATH_KEY); | |
548 return dir != null | |
549 ? dir | |
550 : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SHAPEFILE_PATH; | |
551 } | |
552 | |
553 | |
554 @Override | |
555 public void endOfLife(Object globalContext) { | |
556 super.endOfLife(globalContext); | |
557 // do it in background | |
558 new Thread() { | |
559 @Override | |
560 public void run() { | |
561 String path = resetShapeFilePath(); | |
562 if (path == null) { | |
563 return; | |
564 } | |
565 File dir = new File(path); | |
566 for (int i = 0; i < 10; ++i) { | |
567 if (!dir.exists() || FileUtils.deleteRecursive(dir)) { | |
568 MapfileGenerator.getInstance().update(); | |
569 return; | |
570 } | |
571 try { | |
572 Thread.sleep(10000L); | |
573 } | |
574 catch (InterruptedException ie) { | |
575 } | |
576 } | |
577 | |
578 log.error("failed to remove directory '" + path + "'"); | |
579 } // run | |
580 }.start(); | |
581 } | |
582 | |
583 /** | |
584 * Resets the Settings e.g shapeFilePath and templateID | |
585 * @return | |
586 */ | |
587 private String resetShapeFilePath() { | |
588 synchronized (shapeFileLock) { | |
589 String path = shapeFilePath; | |
590 shapeFilePath = null; | |
591 return path; | |
592 } | |
593 } | |
594 | |
595 | |
596 /** | |
597 * Write data to shapefiles and feed a map service with information about | |
598 * these shapefiles. The map service can be queried for displaying | |
599 * corresponding layers as WMS. | |
600 * | |
601 * @param uuid The UUID of the current artifact. | |
602 * @param callContext The CallContext object. | |
603 * @param layerMetaData The Metadata which is required to create the | |
604 * different Layers. | |
605 * @param inputData the Parameters which are send by the out-Call. | |
606 * @return a document with some meta information (shapefile path, geometry | |
607 * type, time to live of the current artifact, etc). | |
608 * @throws StateException if an error occured while shapefile writing. | |
609 */ | |
610 protected Document getWMS( | |
611 String uuid, | |
612 CallContext callContext, | |
613 Collection<LayerMetaData> layerMetaData, | |
614 Collection<InputData> inputData) | |
615 throws StateException | |
616 { | |
617 Document document = XMLUtils.newDocument(); | |
618 | |
619 File baseDir = shapefileDirectory(callContext); | |
620 File shapeDir = new File(baseDir, uuid); | |
621 | |
622 boolean success = false; | |
623 boolean createdDir = false; | |
624 | |
625 try { | |
626 // create shapefile directory or delete content if it already exists | |
627 synchronized (shapeFileLock) { | |
628 if (shapeDir.exists()) { | |
629 FileUtils.deleteContent(shapeDir); | |
630 } | |
631 else if (!shapeDir.mkdirs()) { | |
632 log.error("cannot create directory '" | |
633 + shapeDir.getAbsolutePath() + "'"); | |
634 return null; | |
635 } | |
636 setShapeFilePath(shapeDir.getAbsolutePath()); | |
637 createdDir = true; | |
638 } | |
639 | |
640 // process data | |
641 Iterator<LayerMetaData> it = layerMetaData.iterator(); | |
642 | |
643 // create meta file | |
644 Document meta = MetaWriter.initMeta(); | |
645 MetaWriter.insertAbstractMeta(callContext, meta); | |
646 | |
647 String path = getShapeFilePath(); | |
648 String prefix = getLayerPrefix(inputData); | |
649 | |
650 if (prefix == null) { | |
651 prefix = uuid; | |
652 } | |
653 | |
654 int layerNumber = 0; | |
655 Envelope mbr = new Envelope(); | |
656 while (it.hasNext()){ | |
657 LayerMetaData lmd = it.next(); | |
658 layerNumber ++; | |
659 | |
660 String geometryType = lmd.getGeometryType(); | |
661 String templateId = lmd.getTemplateID(); | |
662 | |
663 ExclusiveExec.UniqueKey key = ExclusiveExec.INSTANCE.acquire(uuid); | |
664 try{ | |
665 Collection<Result> results = this.fetchData(lmd,mbr); | |
666 if (results != null && writeToShapeFile(uuid, results, | |
667 callContext, | |
668 geometryType, | |
669 layerNumber) != null) { | |
670 String name = getLayerName(uuid, layerNumber); | |
671 String base = lmd.getLayertitle(); | |
672 String title = getLayerTitle(prefix, base); | |
673 String data = getLayerData( | |
674 uuid, createShapeFileName(layerNumber)); | |
675 String type = determineGeometryType(geometryType); | |
676 String status = "OFF"; | |
677 String model = findParameterTitle( | |
678 geometryType, templateId); | |
679 | |
680 MetaWriter.insertLayer( | |
681 callContext, meta, name, title, | |
682 data, model, type, status); | |
683 } | |
684 | |
685 success = true; | |
686 | |
687 if (meta != null && !it.hasNext()) { | |
688 MetaWriter.insertMbr(mbr, "EPSG:4326",meta); | |
689 MetaWriter.writeMetaFile(path, meta); | |
690 MapfileGenerator.getInstance().update(); | |
691 return meta; | |
692 } | |
693 }finally{ | |
694 ExclusiveExec.INSTANCE.release(key); | |
695 } | |
696 } | |
697 | |
698 return document; | |
699 } | |
700 finally { | |
701 if (!success && createdDir) { | |
702 FileUtils.deleteRecursive(shapeDir); | |
703 } | |
704 } | |
705 } | |
706 | |
707 /** | |
708 * Creates the name of the Shapefile | |
709 * @param layerNumber the Number of the Layer | |
710 * @return the create name of the Shapefile. | |
711 */ | |
712 private String createShapeFileName(int layerNumber) { | |
713 return SHAPEFILE_NAME+"_"+layerNumber+".shp"; | |
714 } | |
715 | |
716 | |
717 protected String getLayerName(String uuid, int idx) { | |
718 return "GNV_" + uuid + "_" + idx; | |
719 } | |
720 | |
721 | |
722 protected String getLayerTitle(String prefix, String base) { | |
723 return "GNV_" + prefix + "_" + base; | |
724 } | |
725 | |
726 | |
727 protected String getLayerData(String shapeDir, String filename) { | |
728 File path = new File(shapeDir, filename); | |
729 | |
730 return path.toString(); | |
731 } | |
732 | |
733 | |
734 /** | |
735 * Returns the parameterType for the Layer. | |
736 * @param geometryType | |
737 * @return | |
738 */ | |
739 private String findParameterTitle(String geometryType, String templateID) { | |
740 String paramType = LAYER_MODEL+"_"+templateID; | |
741 if (!MapfileGenerator.getInstance().templateExists(paramType)){ | |
742 // If the template doesn't exist the Defaulttemplates will be used. | |
743 paramType = LAYER_MODEL+"_"+ | |
744 this.determineDefaultTemplateName(geometryType); | |
745 } | |
746 return paramType; | |
747 } | |
748 | |
749 /** | |
750 * Find the title for a wms layer specified by the user. | |
751 * | |
752 * @param inputData A collection with InputData objects. | |
753 * @return the title. | |
754 */ | |
755 protected String getLayerPrefix(Collection<InputData> inputData) { | |
756 for (InputData data: inputData) { | |
757 String name = data.getName(); | |
758 if (name != null && name.equals("title")) { | |
759 return (String) data.getValue(); | |
760 } | |
761 } | |
762 return null; | |
763 } | |
764 | |
765 | |
766 /** | |
767 * Turns the geometry type into a form used for the templating mechanism | |
768 * while mapfile generation. | |
769 * | |
770 * @param geometryType The original geometry type. | |
771 * @return a valid geometry type fpr the template mechanism. | |
772 */ | |
773 private String determineGeometryType(String geometryType){ | |
774 String returnValue = geometryType.toLowerCase(); | |
775 if (returnValue.equalsIgnoreCase("linestring")){ | |
776 returnValue = "Line"; | |
777 }else if (returnValue.equalsIgnoreCase("multilinestring")){ | |
778 returnValue ="Line"; | |
779 }else if (returnValue.equalsIgnoreCase("multipolygon")){ | |
780 returnValue = "Polygon"; | |
781 } | |
782 return returnValue; | |
783 } | |
784 | |
785 | |
786 /** | |
787 * Determine the default template name if no special template is existing | |
788 * for this layer. | |
789 * | |
790 * @param geometryType The geometry type. | |
791 * @return a default geometry fitting to the original geometry type. | |
792 */ | |
793 private String determineDefaultTemplateName(String geometryType){ | |
794 String returnValue = geometryType.toLowerCase(); | |
795 if (returnValue.equalsIgnoreCase("multilinestring")){ | |
796 returnValue ="linestring"; | |
797 }else if (returnValue.equalsIgnoreCase("multipolygon")){ | |
798 returnValue = "polygon"; | |
799 }else if (returnValue.equalsIgnoreCase("multipoint")){ | |
800 returnValue = "point"; | |
801 } | |
802 return returnValue; | |
803 } | |
804 } | |
805 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |