comparison gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java @ 649:4fc97074eb90

Added Support for writing Shapefiles and Export them as an Zipfile for the Product Layer. gnv-artifacts/trunk@738 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Fri, 05 Mar 2010 12:35:24 +0000
parents 93978859fa9e
children 6eccb68a8b99
comparison
equal deleted inserted replaced
648:7c67ff162e87 649:4fc97074eb90
1 /** 1 /**
2 * 2 *
3 */ 3 */
4 package de.intevation.gnv.state.layer; 4 package de.intevation.gnv.state.layer;
5 5
6 import java.io.File;
7 import java.io.IOException;
6 import java.io.OutputStream; 8 import java.io.OutputStream;
7 import java.util.Collection; 9 import java.util.Collection;
8 import java.util.Iterator; 10 import java.util.Iterator;
9 11
10 import org.apache.log4j.Logger; 12 import org.apache.log4j.Logger;
11 import org.w3c.dom.Document; 13 import org.w3c.dom.Document;
12 import org.w3c.dom.Node; 14 import org.w3c.dom.Node;
15
16 import com.vividsolutions.jts.geom.Geometry;
17 import com.vividsolutions.jts.io.ParseException;
18 import com.vividsolutions.jts.io.WKTReader;
13 19
14 import de.intevation.artifactdatabase.Config; 20 import de.intevation.artifactdatabase.Config;
15 import de.intevation.artifactdatabase.XMLUtils; 21 import de.intevation.artifactdatabase.XMLUtils;
16 import de.intevation.artifacts.ArtifactNamespaceContext; 22 import de.intevation.artifacts.ArtifactNamespaceContext;
17 import de.intevation.artifacts.CallContext; 23 import de.intevation.artifacts.CallContext;
24 import de.intevation.gnv.artifacts.context.GNVArtifactContext;
18 import de.intevation.gnv.geobackend.base.Result; 25 import de.intevation.gnv.geobackend.base.Result;
26 import de.intevation.gnv.geobackend.base.query.QueryExecutor;
27 import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
28 import de.intevation.gnv.geobackend.base.query.exception.QueryException;
19 import de.intevation.gnv.state.InputData; 29 import de.intevation.gnv.state.InputData;
20 import de.intevation.gnv.state.OutputStateBase; 30 import de.intevation.gnv.state.OutputStateBase;
21 import de.intevation.gnv.state.exception.StateException; 31 import de.intevation.gnv.state.exception.StateException;
32 import de.intevation.gnv.utils.FileUtils;
33 import de.intevation.gnv.utils.MapfileGenerator;
34 import de.intevation.gnv.utils.ShapeFileWriter;
22 35
23 /** 36 /**
24 * @author Tim Englich <tim.englich@intevation.de> 37 * @author Tim Englich <tim.englich@intevation.de>
25 * 38 *
26 */ 39 */
38 51
39 /** 52 /**
40 * The ID for the Query fetching the Layer from the DB 53 * The ID for the Query fetching the Layer from the DB
41 */ 54 */
42 private String dataQueryID = null; 55 private String dataQueryID = null;
56
57 /**
58 * The ID for the Query fetching the Geometry from the DB
59 * which should be used to Clip the Layerdata
60 */
61 private String geometryQueryID = null;
62
63 /**
64 * The ID for the Value which will hold the Geometrie-Value
65 */
66 private String geometryID = null;
67
68 private Boolean shapeFileLock = new Boolean(true);
69
70 private String shapeFilePath;
71
72 public static final String SHAPEFILE_NAME = "data.shp";
73
43 /** 74 /**
44 * Constructor 75 * Constructor
45 */ 76 */
46 public LayerOutputState() { 77 public LayerOutputState() {
47 super(); 78 super();
62 if (outputMode.equalsIgnoreCase("wms")) { 93 if (outputMode.equalsIgnoreCase("wms")) {
63 Collection<Result> data = this.fetchData(); 94 Collection<Result> data = this.fetchData();
64 // TODO USE ME 95 // TODO USE ME
65 }else if (outputMode.equalsIgnoreCase("zip")){ 96 }else if (outputMode.equalsIgnoreCase("zip")){
66 Collection<Result> data = this.fetchData(); 97 Collection<Result> data = this.fetchData();
67 // TODO USE ME 98 this.writeZip(uuid, callContext, outputStream, data);
68 } 99 }
69 } 100 }
70 101
71 102
103 /**
104 * Fetches the Data from the Databasebackend
105 * @return
106 */
72 protected Collection<Result> fetchData(){ 107 protected Collection<Result> fetchData(){
73 log.debug("LayerOutputState.fetchData"); 108 log.debug("LayerOutputState.fetchData");
74 // TODO PUT ALL in CACHE 109 // TODO PUT ALL in CACHE
75 Collection<Result> result = this.getData(this.queryID); 110 Collection<Result> result = this.getData(this.queryID);
76 Collection<Result> data = null; 111 Collection<Result> data = null;
112 String geometryWKT = null;
77 if (result != null){ 113 if (result != null){
114 QueryExecutor queryExecutor = QueryExecutorFactory.getInstance()
115 .getQueryExecutor();
78 Iterator<Result> it = result.iterator(); 116 Iterator<Result> it = result.iterator();
79 String table = null; 117 String[] queryValues = null;
80 String where = null;
81 if (it.hasNext()){ 118 if (it.hasNext()){
82 Result resultValue = it.next(); 119 Result resultValue = it.next();
83 table = resultValue.getString(0); 120 String table = resultValue.getString(0);
84 where = resultValue.getString(1); 121 String where = resultValue.getString(1);
85 // TODO ADD SpatialFilter if Geometry is available 122 if (this.geometryID != null){
123 InputData geometryInputData =
124 this.inputData.get(this.geometryID);
125 if (geometryInputData != null){
126
127 try {
128 Collection<Result> geometryData = queryExecutor
129 .executeQuery(this.geometryQueryID,
130 new String[]{geometryInputData.getValue()});
131 Iterator<Result> git = geometryData.iterator();
132 if (git.hasNext()){
133 Result geometryValue = git.next();
134 geometryWKT = geometryValue.getString(0);
135 }
136 } catch (QueryException e) {
137 log.error(e,e);
138 // TODO: what should happen??
139 }
140 queryValues = new String[]{table,
141 where,
142 geometryWKT};
143 }else{
144 // TODO: Look into the presetting for an WKT
145 queryValues = new String[]{table,where};
146 }
147 }else{
148 // TODO: Look into the presetting for an WKT
149 queryValues = new String[]{table,where};
150
151 }
86 } 152 }
87 153
88 data = null; // TODO Fetch the Data for the Layer and Trim the Geometries 154 try {
89 // using the Geometry if on is available. 155 data = queryExecutor.executeQuery(dataQueryID,
156 queryValues);
157 if (data != null && geometryWKT != null){
158 WKTReader wktReader = new WKTReader();
159 Geometry border = wktReader.read(geometryWKT);
160
161 Iterator<Result> dataIt = data.iterator();
162 while (dataIt.hasNext()){
163 // Trim the Geometries using the
164 // Geometry if on is available.
165 Result current = dataIt.next();
166 String currentWKT = current.getString(0);
167 Geometry currentGeometry = null;
168 try {
169 currentGeometry = wktReader.read(currentWKT);
170 } catch (Exception e) {
171 log.error("Error parsing Geometry "+ currentWKT);
172 log.error(e,e);
173 }
174
175 if (currentGeometry != null){
176 Geometry newGeometry = currentGeometry.intersection(border);
177 current.addColumnValue(0, newGeometry.toText());
178 }
179 }
180 }
181 } catch (QueryException e) {
182 log.error(e,e);
183 } catch (ParseException e){
184 log.error(e,e);
185 }
90 } 186 }
91 return data; 187 return data;
92 } 188 }
93 189
94 @Override 190 @Override
95 public void setup(Node configuration) { 191 public void setup(Node configuration) {
96 log.debug("LayerOutputState.setup"); 192 log.debug("LayerOutputState.setup");
97 super.setup(configuration); 193 super.setup(configuration);
98 this.dataQueryID = Config.getStringXPath(configuration,"queryID-layerdata"); 194 this.dataQueryID = Config.getStringXPath(configuration,
99 } 195 "queryID-layerdata");
196 this.geometryID = Config.getStringXPath(configuration,
197 "inputvalue-geometry");
198 this.geometryQueryID = Config.getStringXPath(configuration,
199 "queryID-geometry");
200 }
201
202 protected String writeToShapeFile(
203 String uuid,
204 Collection<Result> data,
205 CallContext callContext
206 ) {
207 File baseDir = shapefileDirectory(callContext);
208
209 File shapeDir = new File(baseDir, uuid);
210 boolean success = false;
211 boolean createdDir = false;
212
213 try {
214 synchronized (shapeFileLock) {
215 int count = 0;
216 while (shapeDir.exists()) {
217 shapeDir = new File(baseDir, uuid + "-" + count);
218 ++count;
219 }
220
221 if (!shapeDir.mkdirs()) {
222 log.error("cannot create directory '"
223 + shapeDir.getAbsolutePath() + "'");
224 return null;
225 }
226 createdDir = true;
227 }
228
229 File shapeFile = new File(shapeDir, SHAPEFILE_NAME);
230 if (!ShapeFileWriter.writeDataToFile(shapeFile, "data", data)){
231 log.error("writing data into shapefile failed");
232 return null;
233 }
234
235 shapeFilePath = shapeDir.getAbsolutePath();
236 success = true;
237
238 callContext.afterCall(CallContext.STORE);
239
240 return shapeFilePath;
241 }
242 finally {
243 if (!success && createdDir) {
244 FileUtils.deleteRecursive(shapeDir);
245 }
246 }
247 }
248
249 protected void writeZip(
250 String uuid,
251 CallContext callContext,
252 OutputStream output,
253 Collection<Result> data
254 )
255 throws StateException
256 {
257 try {
258 String p = getShapeFilePath();
259 if (p != null) {
260 File dir = new File(p);
261 if (dir.isDirectory()) {
262 FileUtils.createZipArchive(dir, output);
263 }
264 }
265 else {
266
267 if ((p = writeToShapeFile(uuid, data, callContext)) != null) {
268 FileUtils.createZipArchive(new File(p), output);
269 }
270 }
271 }
272 catch (IOException ioe) {
273 log.error(ioe.getLocalizedMessage(), ioe);
274 }
275 }
276
277 public String getShapeFilePath() {
278 synchronized (shapeFileLock) {
279 return shapeFilePath;
280 }
281 }
282
283 private static File shapefileDirectory(CallContext callContext) {
284 // TODO: Refactoring nessessary it should be used only one Shapefilepath
285 // for alle Modes. Code was taken from HorizontalCrossSectionMeshOutputState
286 GNVArtifactContext context =
287 (GNVArtifactContext)callContext.globalContext();
288 File dir = (File)context.get(
289 GNVArtifactContext.HORIZONTAL_CROSS_SECTION_RESULT_SHAPEFILE_PATH_KEY);
290 return dir != null
291 ? dir
292 : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SHAPEFILE_PATH;
293 }
294
295 /**
296 * @see de.intevation.gnv.state.StateBase#endOfLife(java.lang.Object)
297 */
298 @Override
299 public void endOfLife(Object globalContext) {
300 super.endOfLife(globalContext);
301
302 // do it in background
303 new Thread() {
304 public void run() {
305 // TODO: Do the un-publishing WMS stuff.
306 String path = resetShapeFilePath();
307
308 if (path == null) {
309 return;
310 }
311
312 File dir = new File(path);
313
314 for (int i = 0; i < 10; ++i) {
315 if (!dir.exists() || FileUtils.deleteRecursive(dir)) {
316 MapfileGenerator.getInstance().update();
317 return;
318 }
319
320 try {
321 Thread.sleep(10000L);
322 }
323 catch (InterruptedException ie) {
324 }
325 }
326
327 log.error("failed to remove directory '" + path + "'");
328 } // run
329 }.start();
330 }
331
332 public String resetShapeFilePath() {
333 synchronized (shapeFileLock) {
334 String path = shapeFilePath;
335 shapeFilePath = null;
336 return path;
337 }
338 }
339
100 340
101 } 341 }

http://dive4elements.wald.intevation.org