Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java @ 859:3fbabd4803d7
ISSUE252 Make it possible to export more than one Layer
gnv-artifacts/trunk@983 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Tim Englich <tim.englich@intevation.de> |
---|---|
date | Mon, 26 Apr 2010 09:09:20 +0000 |
parents | 164d102b0af5 |
children | dfd02f8d3602 |
line wrap: on
line diff
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java Fri Apr 23 13:26:21 2010 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/layer/LayerOutputState.java Mon Apr 26 09:09:20 2010 +0000 @@ -3,12 +3,12 @@ import java.io.File; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.apache.log4j.Logger; import org.w3c.dom.Document; -import org.w3c.dom.Element; import org.w3c.dom.Node; import com.vividsolutions.jts.geom.Geometry; @@ -59,7 +59,7 @@ /** * The Name of the Shapefile which will be generated. */ - public static final String SHAPEFILE_NAME = "data.shp"; + public static final String SHAPEFILE_NAME = "data"; /** * The ID for the Query fetching the Layer from the DB @@ -100,17 +100,6 @@ private String shapeFilePath; /** - * The ID of the Template which should be used to generate the Layerentry - * in the Mapfile. - */ - private String templateID = null; - - /** - * The Kind of Geometry which should be used to generate the Shapefile. - */ - private String geometryType = null; - - /** * Constructor */ public LayerOutputState() { @@ -120,25 +109,27 @@ public void out(Document format, Collection<InputData> inputData, OutputStream outputStream, String uuid, CallContext callContext) throws StateException { - log.debug("LayerOutputState.out"); String outputMode = XMLUtils.xpathString( format, XPATH_OUTPUT_MODE, ArtifactNamespaceContext.INSTANCE); if (outputMode.equalsIgnoreCase("wms")) { - Collection<Result> data = this.fetchData(); - if (data != null && !data.isEmpty()){ + + Collection<LayerMetaData> layerMetaData = + this.getRequestedLayerMetadata(); + if (layerMetaData != null && !layerMetaData.isEmpty()){ XMLUtils.toStream(this.getWMS(uuid, callContext, - data, geometryType, - inputData), + layerMetaData,inputData), outputStream); }else{ this.writeExceptionReport2Stream(outputStream); } }else if (outputMode.equalsIgnoreCase("zip")){ - Collection<Result> data = this.fetchData(); - if (data != null && !data.isEmpty()){ - this.writeZip(uuid, callContext, outputStream, - data,geometryType); + Collection<LayerMetaData> layerMetaData = + this.getRequestedLayerMetadata(); + + if (layerMetaData != null && !layerMetaData.isEmpty()){ + this.writeZip(uuid, callContext, + outputStream, layerMetaData); }else{ this.writeExceptionReport2Stream(outputStream); } @@ -158,38 +149,35 @@ XMLUtils.toStream(document,outputStream); } - /** - * Fetches the Data from the Databasebackend. - * - * @return the resultdata. + * Returns the Metadata for the requested Layers for fetching the data + * of the Layer and generating the Layer and WMS. + * @return the Metadata for the requested Layers */ - protected Collection<Result> fetchData(){ - log.debug("LayerOutputState.fetchData"); + private Collection<LayerMetaData> getRequestedLayerMetadata(){ + log.debug("LayerOutputState.getRequestedLayerMetadata"); Collection<Result> result = this.getData(this.queryID); - Collection<Result> data = null; - String geometryWKT = null; + Collection<LayerMetaData> returnValue = null; if (result != null){ QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() .getQueryExecutor(); Iterator<Result> it = result.iterator(); - String[] queryValues = null; - if (it.hasNext()){ + returnValue = new ArrayList<LayerMetaData>(result.size()); + while (it.hasNext()){ Result resultValue = it.next(); String table = resultValue.getString(0); - - this.geometryType = this.getGeometryType(table, queryExecutor); - + String geometryType = this.getGeometryType(table, queryExecutor); String where = resultValue.getString(1); String columns = this.fetchColumns(table); - - templateID = resultValue.getString(2); + String templateID = resultValue.getString(2); + String[] queryValues = null; + String geometryWKT = null; if (this.geometryID != null){ InputData geometryInputData = this.inputData.get(this.geometryID); if (geometryInputData != null){ - try { + Collection<Result> geometryData = queryExecutor .executeQuery(this.geometryQueryID, new String[]{geometryInputData.getValue()}); @@ -233,40 +221,54 @@ queryValues = new String[]{columns,table,where}; } } + returnValue.add(new LayerMetaData(table, geometryType, + where, columns, + templateID, queryValues, + geometryWKT)); } - - try { - data = queryExecutor.executeQuery(dataQueryID, - queryValues); - if (data != null && geometryWKT != null){ - WKTReader wktReader = new WKTReader(); - Geometry border = wktReader.read(geometryWKT); + } + return returnValue; + } - Iterator<Result> dataIt = data.iterator(); - while (dataIt.hasNext()){ - // Trim the Geometries using the - // Geometry if on is available. - Result current = dataIt.next(); - String currentWKT = current.getString(0); - Geometry currentGeometry = null; - try { - currentGeometry = wktReader.read(currentWKT); - } catch (Exception e) { - log.error("Error parsing Geometry "+ currentWKT); - log.error(e,e); - } - - if (currentGeometry != null){ - Geometry newGeometry = currentGeometry.intersection(border); - current.addColumnValue(0, newGeometry.toText()); - } + /** + * Fetches the Data from the Databasebackend. + * + * @return the resultdata. + */ + protected Collection<Result> fetchData(LayerMetaData layerMetaData){ + log.debug("LayerOutputState.fetchData"); + Collection<Result> data = null; + QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() + .getQueryExecutor(); + try { + data = queryExecutor.executeQuery(dataQueryID, + layerMetaData.getQueryValues()); + if (data != null && layerMetaData.getGeometryWKT() != null){ + WKTReader wktReader = new WKTReader(); + Geometry border = wktReader.read(layerMetaData.getGeometryWKT()); + Iterator<Result> dataIt = data.iterator(); + while (dataIt.hasNext()){ + // Trim the Geometries using the + // Geometry if one is available. + Result current = dataIt.next(); + String currentWKT = current.getString(0); + Geometry currentGeometry = null; + try { + currentGeometry = wktReader.read(currentWKT); + } catch (Exception e) { + log.error("Error parsing Geometry "+ currentWKT); + log.error(e,e); + } + if (currentGeometry != null){ + Geometry newGeometry = currentGeometry.intersection(border); + current.addColumnValue(0, newGeometry.toText()); } } - } catch (QueryException e) { - log.error(e,e); - } catch (ParseException e){ - log.error(e,e); } + } catch (QueryException e) { + log.error(e,e); + } catch (ParseException e){ + log.error(e,e); } return data; } @@ -284,7 +286,6 @@ String returnValue = null; String[] tables = tableName.toUpperCase().split(","); String[] filter = tables[0].split("\\."); - try { Collection<Result> result = queryExecutor.executeQuery(this.geometryTypeQueryID, filter); @@ -316,7 +317,6 @@ } catch (QueryException e) { log.error(e,e); } - return returnValue; } @@ -334,8 +334,7 @@ String[] filter = tables[0].split("\\."); // Only use the first Table the second one will be ignored. QueryExecutor queryExecutor = QueryExecutorFactory.getInstance() - .getQueryExecutor(); - + .getQueryExecutor(); Collection<Result> columnData = queryExecutor. executeQuery(this.columnQueryID, filter); @@ -353,7 +352,6 @@ } returnValue = sb.toString(); } - } catch (QueryException e) { log.error(e,e); } @@ -391,47 +389,57 @@ String uuid, Collection<Result> data, CallContext callContext, - String geometryType + String geometryType, + int layerNumber ) { - File baseDir = shapefileDirectory(callContext); - - File shapeDir = new File(baseDir, uuid); boolean success = false; - boolean createdDir = false; - - try { - synchronized (shapeFileLock) { - if (shapeDir.exists()) { - FileUtils.deleteContent(shapeDir); - } - else if (!shapeDir.mkdirs()) { - log.error("cannot create directory '" - + shapeDir.getAbsolutePath() + "'"); + if (data != null && !data.isEmpty()){ + File shapeDir = new File(shapeFilePath); + try { + File shapeFile = new File(shapeDir, createShapeFileName(layerNumber)); + if (!ShapeFileWriter.writeDataToFile(shapeFile, "data", data,geometryType)){ + log.error("writing data into shapefile failed"); return null; } - createdDir = true; - } - - File shapeFile = new File(shapeDir, SHAPEFILE_NAME); - if (!ShapeFileWriter.writeDataToFile(shapeFile, "data", data,geometryType)){ - log.error("writing data into shapefile failed"); - return null; + success = true; + callContext.afterCall(CallContext.STORE); + return shapeFilePath; } - - shapeFilePath = shapeDir.getAbsolutePath(); - success = true; - - callContext.afterCall(CallContext.STORE); - - return shapeFilePath; - } - finally { - if (!success && createdDir) { - FileUtils.deleteRecursive(shapeDir); + finally { + if (!success) { + FileUtils.deleteRecursive(shapeDir); + } } + }else{ + return null; } } + /** + * Check if the ShapeDir exists and if it exists delete all Contents + * in it. If it not exists the Director will be created. + * @param baseDir the BaseDirectory for all ShapeDirs + * @param uuid the UUID which is used to create the Directory + * @return true if the directory exists or could be created. + * false if the directory could not be created. + */ + private boolean createShapeDir(File baseDir, String uuid){ + File shapeDir = new File(baseDir, uuid); + boolean createdDir = false; + synchronized (shapeFileLock) { + if (shapeDir.exists()) { + FileUtils.deleteContent(shapeDir); // TODO Place on getZip and getWMS + } + else if (!shapeDir.mkdirs()) { + log.error("cannot create directory '" + + shapeDir.getAbsolutePath() + "'"); + return false; + } + createdDir = true; + } + shapeFilePath = shapeDir.getAbsolutePath(); + return createdDir; + } /** * Create a zip archive with the shapefiles of the given shapefiles path and @@ -448,8 +456,7 @@ String uuid, CallContext callContext, OutputStream output, - Collection<Result> data, - String geometryType + Collection<LayerMetaData> layerMetaData ) throws StateException { @@ -462,8 +469,18 @@ } } else { - - if ((p = writeToShapeFile(uuid, data, callContext,geometryType)) != null) { + File baseDir = shapefileDirectory(callContext); + if (!this.createShapeDir(baseDir, uuid)){ + return; + } + Iterator<LayerMetaData> it = layerMetaData.iterator(); + int i = 1; + while(it.hasNext()){ + LayerMetaData lmd = it.next(); + Collection<Result> data = this.fetchData(lmd); + p = writeToShapeFile(uuid, data, callContext,lmd.getGeometryType(),i++); + } + if (p != null) { FileUtils.createZipArchive(new File(p), output); } } @@ -484,10 +501,15 @@ } } - + /** + * Returns the basic-directory where the Shapefiles should be placed in. + * @param callContext the Context of this Call + * @return the Directory where the Shapefiles could be placed in. + * (Please create an own directory in this dir and not put the + * Files directly in it) + */ private static File shapefileDirectory(CallContext callContext) { - // TODO: Refactoring nessessary it should be used only one Shapefilepath - // for alle Modes. Code was taken from HorizontalCrossSectionMeshOutputState + // Code was taken from HorizontalCrossSectionMeshOutputState GNVArtifactContext context = (GNVArtifactContext)callContext.globalContext(); File dir = (File)context.get( @@ -501,25 +523,20 @@ @Override public void endOfLife(Object globalContext) { super.endOfLife(globalContext); - // do it in background new Thread() { @Override public void run() { String path = resetShapeFilePath(); - if (path == null) { return; } - File dir = new File(path); - for (int i = 0; i < 10; ++i) { if (!dir.exists() || FileUtils.deleteRecursive(dir)) { MapfileGenerator.getInstance().update(); return; } - try { Thread.sleep(10000L); } @@ -540,7 +557,6 @@ synchronized (shapeFileLock) { String path = shapeFilePath; shapeFilePath = null; - templateID = null; return path; } } @@ -553,8 +569,8 @@ * * @param uuid The UUID of the current artifact. * @param callContext The CallContext object. - * @param data A collection with some input data. - * @param geometryType The geometry type. + * @param layerMetaData The Metadata which is required to create the + * different Layers. * @param inputData the Parameters which are send by the out-Call. * @return a document with some meta information (shapefile path, geometry * type, time to live of the current artifact, etc). @@ -562,72 +578,125 @@ */ protected Document getWMS(String uuid, CallContext callContext, - Collection<Result> data, - String geometryType, + Collection<LayerMetaData> layerMetaData, Collection<InputData> inputData) throws StateException { - Document document = XMLUtils.newDocument(); + String path = getShapeFilePath(); + if (path != null && new File(path).isDirectory()){ + return this.refreshMetaFile(layerMetaData, inputData, + uuid, callContext); + }else{ + Document document = XMLUtils.newDocument(); + if (this.shapeFilePath == null){ + File baseDir = shapefileDirectory(callContext); + if (!this.createShapeDir(baseDir, uuid)){ + // TODO Insert Error Report + return document; + } + } + path = getShapeFilePath(); + Iterator<LayerMetaData> it = layerMetaData.iterator(); + Node meta = null; + int layerNumber = 0; + while (it.hasNext()){ + LayerMetaData lmd = it.next(); + layerNumber ++; + String geometryType = lmd.getGeometryType(); + String templateId = lmd.getTemplateID(); + ExclusiveExec.UniqueKey key = ExclusiveExec.INSTANCE.acquire(uuid); + try{ + Collection<Result> data = this.fetchData(lmd); + if (data != null && + (this.writeToShapeFile(uuid, data, callContext, + geometryType,layerNumber)) != null) { + String paramType = findParameterTitle(geometryType,templateId); + String title = getLayerTitle(inputData); + if (title == null) { + title = uuid+"_"+layerNumber; + }else{ + title = title+"_"+layerNumber; + } + if (meta == null){ + meta = MetaWriter.writeLayerMeta(callContext,document); + } + MetaWriter.writeLayerMeta(callContext, document, + meta, uuid, paramType, + this.determineGeometryType(geometryType), + createShapeFileName(layerNumber), + title); + } + if (meta != null && !it.hasNext()) { + MetaWriter.writeMetaFile(path,document); + MapfileGenerator.getInstance().update(); + return document; + } + }finally{ + ExclusiveExec.INSTANCE.release(key); + } + } + return document; + } + } - Element pathElement = document.createElement("path"); - document.appendChild(pathElement); + /** + * Creates the name of the Shapefile + * @param layerNumber the Number of the Layer + * @return the create name of the Shapefile. + */ + private String createShapeFileName(int layerNumber) { + return SHAPEFILE_NAME+"_"+layerNumber+".shp"; + } - String path = getShapeFilePath(); - - if (path != null && new File(path).isDirectory()) { + /** + * Method that refreshes the Metadatafile for publishing the WMS + * Without generating the Data ones again. + * @param layerMetaData the Metadata which is required to create the Layers + * @param inputData the Inputdata which was sent by the Client + * @param uuid the uuid of the Artifact + * @param callContext the context of this Call + * @return a refreshed Metadata-Document + */ + private Document refreshMetaFile(Collection<LayerMetaData> layerMetaData, + Collection<InputData> inputData, + String uuid, + CallContext callContext){ + Document document = XMLUtils.newDocument(); + Node meta = null; + int layerNumber = 0; + Iterator<LayerMetaData> it = layerMetaData.iterator(); + while (it.hasNext()){ + LayerMetaData lmd = it.next(); + layerNumber ++; + String geometryType = lmd.getGeometryType(); + String templateId = lmd.getTemplateID(); String title = getLayerTitle(inputData); if (title == null) { - title = uuid; + title = uuid+"_"+layerNumber; + }else{ + title = title+"_"+layerNumber; } - callContext.putContextValue( MetaWriter.CONTEXT_LAYER_TITLE, title); - - String paramType = findParameterTitle(geometryType); - + String paramType = findParameterTitle(geometryType,templateId); if (log.isDebugEnabled()) { log.debug("Layer title: " + title); log.debug("Layer type: " + paramType); } - - Document meta = MetaWriter.writeLayerMeta(callContext, uuid, - path, paramType, - this.determineGeometryType(geometryType), - SHAPEFILE_NAME, - title); - if (meta != null) { - MapfileGenerator.getInstance().update(); - return meta; + if (meta == null){ + meta = MetaWriter.writeLayerMeta(callContext,document); } - - pathElement.setTextContent(path); - } - else { - ExclusiveExec.UniqueKey key = ExclusiveExec.INSTANCE.acquire(uuid); - try{ - if (data != null && - (path = writeToShapeFile(uuid, data, callContext,geometryType)) != null) { - String paramType = findParameterTitle(geometryType); - String title = getLayerTitle(inputData); - if (title == null) { - title = uuid; - } - Document meta = MetaWriter.writeLayerMeta(callContext, uuid, - path, paramType, - this.determineGeometryType(geometryType), - SHAPEFILE_NAME, - title); - if (meta != null) { - MapfileGenerator.getInstance().update(); - return meta; - } - pathElement.setTextContent(path); - } - }finally{ - ExclusiveExec.INSTANCE.release(key); + MetaWriter.writeLayerMeta(callContext, document, + meta, uuid, paramType, + this.determineGeometryType(geometryType), + createShapeFileName(layerNumber), + title); + if (meta != null && !it.hasNext()) { + MetaWriter.writeMetaFile(getShapeFilePath(),document); + MapfileGenerator.getInstance().update(); + return document; } } - return document; } @@ -636,9 +705,8 @@ * @param geometryType * @return */ - private String findParameterTitle(String geometryType) { + private String findParameterTitle(String geometryType, String templateID) { String paramType = LAYER_MODEL+"_"+templateID; - if (!MapfileGenerator.getInstance().templateExists(paramType)){ // If the template doesn't exist the Defaulttemplates will be used. paramType = LAYER_MODEL+"_"+ @@ -672,9 +740,7 @@ * @return a valid geometry type fpr the template mechanism. */ private String determineGeometryType(String geometryType){ - String returnValue = geometryType.toLowerCase(); - if (returnValue.equalsIgnoreCase("linestring")){ returnValue = "Line"; }else if (returnValue.equalsIgnoreCase("multilinestring")){ @@ -694,9 +760,7 @@ * @return a default geometry fitting to the original geometry type. */ private String determineDefaultTemplateName(String geometryType){ - String returnValue = geometryType.toLowerCase(); - if (returnValue.equalsIgnoreCase("multilinestring")){ returnValue ="linestring"; }else if (returnValue.equalsIgnoreCase("multipolygon")){