comparison gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java @ 657:af3f56758f59

merged gnv-artifacts/0.5
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:13:53 +0200
parents 6eccb68a8b99
children 199982e8866e
comparison
equal deleted inserted replaced
590:5f5f273c8566 657:af3f56758f59
1 /**
2 *
3 */
4 package de.intevation.gnv.state.layer;
5
6 import java.io.File;
7 import java.io.IOException;
8 import java.io.OutputStream;
9 import java.util.Collection;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.Map;
13
14 import org.apache.log4j.Logger;
15 import org.w3c.dom.Document;
16 import org.w3c.dom.Element;
17 import org.w3c.dom.Node;
18
19 import com.vividsolutions.jts.geom.Geometry;
20 import com.vividsolutions.jts.io.ParseException;
21 import com.vividsolutions.jts.io.WKTReader;
22
23 import de.intevation.artifactdatabase.Config;
24 import de.intevation.artifactdatabase.XMLUtils;
25 import de.intevation.artifacts.ArtifactNamespaceContext;
26 import de.intevation.artifacts.CallContext;
27 import de.intevation.gnv.artifacts.context.GNVArtifactContext;
28 import de.intevation.gnv.geobackend.base.Result;
29 import de.intevation.gnv.geobackend.base.query.QueryExecutor;
30 import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
31 import de.intevation.gnv.geobackend.base.query.exception.QueryException;
32 import de.intevation.gnv.raster.PaletteManager;
33 import de.intevation.gnv.state.InputData;
34 import de.intevation.gnv.state.OutputStateBase;
35 import de.intevation.gnv.state.exception.StateException;
36 import de.intevation.gnv.utils.FileUtils;
37 import de.intevation.gnv.utils.MapfileGenerator;
38 import de.intevation.gnv.utils.MetaWriter;
39 import de.intevation.gnv.utils.ShapeFileWriter;
40
41 /**
42 * @author Tim Englich <tim.englich@intevation.de>
43 *
44 */
45 public class LayerOutputState extends OutputStateBase {
46
47 /**
48 * the logger, used to log exceptions and additonaly information
49 */
50 private static Logger log = Logger.getLogger(LayerOutputState.class);
51
52 /**
53 * The UID of this Class.
54 */
55 private static final long serialVersionUID = 9180957321704424049L;
56
57 // TODO: Replace
58 public static final String LAYER_MODEL = "layer";
59
60 /**
61 * The ID for the Query fetching the Layer from the DB
62 */
63 private String dataQueryID = null;
64
65 /**
66 * The ID for the Query fetching the Geometry from the DB
67 * which should be used to Clip the Layerdata
68 */
69 private String geometryQueryID = null;
70
71 /**
72 * The ID for the Value which will hold the Geometrie-Value
73 */
74 private String geometryID = null;
75
76 private Boolean shapeFileLock = new Boolean(true);
77
78 private String shapeFilePath;
79
80 private String geometryType = null;
81
82 public static final String SHAPEFILE_NAME = "data.shp";
83
84 /**
85 * Constructor
86 */
87 public LayerOutputState() {
88 super();
89 }
90
91 /**
92 * @see de.intevation.gnv.state.OutputState#out(org.w3c.dom.Document,
93 * java.util.Collection, java.io.OutputStream,
94 * java.lang.String, de.intevation.artifacts.CallContext)
95 */
96 public void out(Document format, Collection<InputData> inputData,
97 OutputStream outputStream, String uuid,
98 CallContext callContext) throws StateException {
99
100 log.debug("LayerOutputState.out");
101 String outputMode = XMLUtils.xpathString(
102 format, XPATH_OUTPUT_MODE, ArtifactNamespaceContext.INSTANCE);
103 if (outputMode.equalsIgnoreCase("wms")) {
104 Collection<Result> data = this.fetchData();
105 XMLUtils.toStream(this.getWMS(uuid, callContext, data),outputStream);
106 }else if (outputMode.equalsIgnoreCase("zip")){
107 Collection<Result> data = this.fetchData();
108 this.writeZip(uuid, callContext, outputStream, data);
109 }
110 }
111
112
113 /**
114 * Fetches the Data from the Databasebackend
115 * @return
116 */
117 protected Collection<Result> fetchData(){
118 log.debug("LayerOutputState.fetchData");
119 // TODO PUT ALL in CACHE
120 Collection<Result> result = this.getData(this.queryID);
121 Collection<Result> data = null;
122 String geometryWKT = null;
123 if (result != null){
124 QueryExecutor queryExecutor = QueryExecutorFactory.getInstance()
125 .getQueryExecutor();
126 Iterator<Result> it = result.iterator();
127 String[] queryValues = null;
128 if (it.hasNext()){
129 Result resultValue = it.next();
130 String table = resultValue.getString(0);
131 String where = resultValue.getString(1);
132 if (this.geometryID != null){
133 InputData geometryInputData =
134 this.inputData.get(this.geometryID);
135 if (geometryInputData != null){
136
137 try {
138 Collection<Result> geometryData = queryExecutor
139 .executeQuery(this.geometryQueryID,
140 new String[]{geometryInputData.getValue()});
141 Iterator<Result> git = geometryData.iterator();
142 if (git.hasNext()){
143 Result geometryValue = git.next();
144 geometryWKT = geometryValue.getString(0);
145 }
146 } catch (QueryException e) {
147 log.error(e,e);
148 // TODO: what should happen??
149 }
150 queryValues = new String[]{table,
151 where,
152 geometryWKT};
153 }else{
154 // TODO: Look into the presetting for an WKT
155 queryValues = new String[]{table,where};
156 }
157 }else{
158 // TODO: Look into the presetting for an WKT
159 queryValues = new String[]{table,where};
160
161 }
162 }
163
164 try {
165 data = queryExecutor.executeQuery(dataQueryID,
166 queryValues);
167 if (data != null && geometryWKT != null){
168 WKTReader wktReader = new WKTReader();
169 Geometry border = wktReader.read(geometryWKT);
170
171 Iterator<Result> dataIt = data.iterator();
172 while (dataIt.hasNext()){
173 // Trim the Geometries using the
174 // Geometry if on is available.
175 Result current = dataIt.next();
176 String currentWKT = current.getString(0);
177 Geometry currentGeometry = null;
178 try {
179 currentGeometry = wktReader.read(currentWKT);
180 } catch (Exception e) {
181 log.error("Error parsing Geometry "+ currentWKT);
182 log.error(e,e);
183 }
184
185 if (currentGeometry != null){
186 Geometry newGeometry = currentGeometry.intersection(border);
187 current.addColumnValue(0, newGeometry.toText());
188 }
189 }
190 }
191 } catch (QueryException e) {
192 log.error(e,e);
193 } catch (ParseException e){
194 log.error(e,e);
195 }
196 }
197 return data;
198 }
199
200 @Override
201 public void setup(Node configuration) {
202 log.debug("LayerOutputState.setup");
203 super.setup(configuration);
204 this.dataQueryID = Config.getStringXPath(configuration,
205 "queryID-layerdata");
206 this.geometryID = Config.getStringXPath(configuration,
207 "inputvalue-geometry");
208 this.geometryQueryID = Config.getStringXPath(configuration,
209 "queryID-geometry");
210 }
211
212 protected String writeToShapeFile(
213 String uuid,
214 Collection<Result> data,
215 CallContext callContext
216 ) {
217 File baseDir = shapefileDirectory(callContext);
218
219 File shapeDir = new File(baseDir, uuid);
220 boolean success = false;
221 boolean createdDir = false;
222
223 try {
224 synchronized (shapeFileLock) {
225 int count = 0;
226 while (shapeDir.exists()) {
227 shapeDir = new File(baseDir, uuid + "-" + count);
228 ++count;
229 }
230
231 if (!shapeDir.mkdirs()) {
232 log.error("cannot create directory '"
233 + shapeDir.getAbsolutePath() + "'");
234 return null;
235 }
236 createdDir = true;
237 }
238
239 File shapeFile = new File(shapeDir, SHAPEFILE_NAME);
240 if ((geometryType = ShapeFileWriter.writeDataToFile(shapeFile, "data", data)) == null){
241 log.error("writing data into shapefile failed");
242 return null;
243 }
244
245 shapeFilePath = shapeDir.getAbsolutePath();
246 success = true;
247
248 callContext.afterCall(CallContext.STORE);
249
250 return shapeFilePath;
251 }
252 finally {
253 if (!success && createdDir) {
254 FileUtils.deleteRecursive(shapeDir);
255 }
256 }
257 }
258
259 protected void writeZip(
260 String uuid,
261 CallContext callContext,
262 OutputStream output,
263 Collection<Result> data
264 )
265 throws StateException
266 {
267 try {
268 String p = getShapeFilePath();
269 if (p != null) {
270 File dir = new File(p);
271 if (dir.isDirectory()) {
272 FileUtils.createZipArchive(dir, output);
273 }
274 }
275 else {
276
277 if ((p = writeToShapeFile(uuid, data, callContext)) != null) {
278 FileUtils.createZipArchive(new File(p), output);
279 }
280 }
281 }
282 catch (IOException ioe) {
283 log.error(ioe.getLocalizedMessage(), ioe);
284 }
285 }
286
287 public String getShapeFilePath() {
288 synchronized (shapeFileLock) {
289 return shapeFilePath;
290 }
291 }
292
293 private static File shapefileDirectory(CallContext callContext) {
294 // TODO: Refactoring nessessary it should be used only one Shapefilepath
295 // for alle Modes. Code was taken from HorizontalCrossSectionMeshOutputState
296 GNVArtifactContext context =
297 (GNVArtifactContext)callContext.globalContext();
298 File dir = (File)context.get(
299 GNVArtifactContext.HORIZONTAL_CROSS_SECTION_RESULT_SHAPEFILE_PATH_KEY);
300 return dir != null
301 ? dir
302 : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SHAPEFILE_PATH;
303 }
304
305 /**
306 * @see de.intevation.gnv.state.StateBase#endOfLife(java.lang.Object)
307 */
308 @Override
309 public void endOfLife(Object globalContext) {
310 super.endOfLife(globalContext);
311
312 // do it in background
313 new Thread() {
314 public void run() {
315 // TODO: Do the un-publishing WMS stuff.
316 String path = resetShapeFilePath();
317
318 if (path == null) {
319 return;
320 }
321
322 File dir = new File(path);
323
324 for (int i = 0; i < 10; ++i) {
325 if (!dir.exists() || FileUtils.deleteRecursive(dir)) {
326 MapfileGenerator.getInstance().update();
327 return;
328 }
329
330 try {
331 Thread.sleep(10000L);
332 }
333 catch (InterruptedException ie) {
334 }
335 }
336
337 log.error("failed to remove directory '" + path + "'");
338 } // run
339 }.start();
340 }
341
342 public String resetShapeFilePath() {
343 synchronized (shapeFileLock) {
344 String path = shapeFilePath;
345 shapeFilePath = null;
346 geometryType = null;
347 return path;
348 }
349 }
350 protected Document getWMS(String uuid,
351 CallContext callContext,
352 Collection<Result> data)
353 throws StateException
354 {
355 // TODO: Do the real WMS publishing here!
356 Document document = XMLUtils.newDocument();
357
358 Element pathElement = document.createElement("path");
359 document.appendChild(pathElement);
360
361 String path = getShapeFilePath();
362
363 if (path != null && new File(path).isDirectory()) {
364 pathElement.setTextContent(path);
365 }
366 else {
367
368 if (data != null &&
369 (path = writeToShapeFile(uuid, data, callContext)) != null) {
370
371 String paramType = LAYER_MODEL+"_"+this.geometryType.toLowerCase();
372
373 Document meta = MetaWriter.writeLayerMeta(callContext, uuid,
374 path, paramType,
375 this.determineGeometryType());
376 if (meta != null) {
377 MapfileGenerator.getInstance().update();
378 return meta;
379 }
380
381 pathElement.setTextContent(path);
382 }
383 }
384
385 return document;
386 }
387
388 private String determineGeometryType(){
389
390 String returnValue = this.geometryType.toLowerCase();
391
392 if (returnValue.equalsIgnoreCase("linestring")){
393 returnValue = "Line";
394 }
395 return returnValue;
396 }
397
398 private static Map<Integer, PaletteManager> getPalettes(
399 CallContext callContext
400 ) {
401 //TODO: customize for product Layer
402 GNVArtifactContext context =
403 (GNVArtifactContext)callContext.globalContext();
404 Map<Integer, PaletteManager> palettes =
405 (Map<Integer, PaletteManager>)context.get(
406 GNVArtifactContext.PALETTES_KEY);
407 return palettes != null
408 ? palettes
409 : new HashMap<Integer, PaletteManager>();
410 }
411
412 }

http://dive4elements.wald.intevation.org