ingo@1115: /*
ingo@1115: * Copyright (c) 2010 by Intevation GmbH
ingo@1115: *
ingo@1115: * This program is free software under the LGPL (>=v2.1)
ingo@1115: * Read the file LGPL.txt coming with the software for details
ingo@1115: * or visit http://www.gnu.org/licenses/ if it does not exist.
ingo@1115: */
ingo@1115:
tim@616: package de.intevation.gnv.state.layer;
tim@616:
tim@799: import java.io.File;
tim@799: import java.io.IOException;
tim@799: import java.io.OutputStream;
tim@859: import java.util.ArrayList;
tim@799: import java.util.Collection;
tim@799: import java.util.Iterator;
tim@799:
tim@799: import org.apache.log4j.Logger;
tim@799: import org.w3c.dom.Document;
tim@799: import org.w3c.dom.Node;
tim@799:
tim@1070: import com.vividsolutions.jts.geom.Envelope;
sascha@779: import com.vividsolutions.jts.geom.Geometry;
tim@649: import com.vividsolutions.jts.io.ParseException;
tim@649: import com.vividsolutions.jts.io.WKTReader;
tim@649:
sascha@1117: import de.intevation.artifacts.common.utils.Config;
sascha@1117: import de.intevation.artifacts.common.utils.XMLUtils;
tim@616: import de.intevation.artifacts.ArtifactNamespaceContext;
tim@616: import de.intevation.artifacts.CallContext;
tim@649: import de.intevation.gnv.artifacts.context.GNVArtifactContext;
tim@616: import de.intevation.gnv.geobackend.base.Result;
tim@649: import de.intevation.gnv.geobackend.base.query.QueryExecutor;
tim@649: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory;
tim@649: import de.intevation.gnv.geobackend.base.query.exception.QueryException;
tim@616: import de.intevation.gnv.state.InputData;
tim@616: import de.intevation.gnv.state.OutputStateBase;
tim@616: import de.intevation.gnv.state.exception.StateException;
tim@723: import de.intevation.gnv.utils.ArtifactXMLUtilities;
tim@828: import de.intevation.gnv.utils.ExclusiveExec;
tim@649: import de.intevation.gnv.utils.FileUtils;
tim@649: import de.intevation.gnv.utils.MapfileGenerator;
tim@655: import de.intevation.gnv.utils.MetaWriter;
tim@649: import de.intevation.gnv.utils.ShapeFileWriter;
tim@616:
tim@616: /**
tim@822: * This OutputState
is used for Layer-Products.
sascha@780: * @author Tim Englich
tim@616: *
tim@616: */
tim@616: public class LayerOutputState extends OutputStateBase {
tim@616:
tim@616: /**
tim@616: * the logger, used to log exceptions and additonaly information
tim@616: */
tim@616: private static Logger log = Logger.getLogger(LayerOutputState.class);
sascha@778:
tim@616: /**
tim@616: * The UID of this Class.
tim@616: */
tim@616: private static final long serialVersionUID = 9180957321704424049L;
sascha@778:
tim@822: /**
tim@822: * The Basename of the Templates for the WMS-Exports
tim@822: */
tim@655: public static final String LAYER_MODEL = "layer";
sascha@835:
tim@822: /**
tim@822: * The Name of the Shapefile which will be generated.
tim@822: */
tim@859: public static final String SHAPEFILE_NAME = "data";
tim@616:
tim@616: /**
tim@616: * The ID for the Query fetching the Layer from the DB
tim@616: */
sascha@778: private String dataQueryID = null;
sascha@778:
tim@649: /**
tim@649: * The ID for the Query fetching the Geometry from the DB
tim@649: * which should be used to Clip the Layerdata
tim@649: */
tim@649: private String geometryQueryID = null;
sascha@778:
tim@822: /**
sascha@835: * The ID of the Query for fetching the Columnnames of the Table which
tim@822: * should put into the Shapefile.
tim@822: */
tim@728: private String columnQueryID = null;
sascha@778:
tim@822: /**
sascha@835: * The ID of the Query for fetching the Information which kind of Geometry
tim@822: * should be put into the Shapefile.
tim@822: */
tim@799: private String geometryTypeQueryID = null;
tim@799:
tim@649: /**
tim@822: * The ID for the Value which will hold the Geometry-Value
tim@649: */
tim@649: private String geometryID = null;
sascha@778:
tim@822: /**
tim@822: * Flag for synchronized Access of the Shapefile.
tim@822: */
tim@649: private Boolean shapeFileLock = new Boolean(true);
sascha@778:
tim@822: /**
tim@822: * The Path where the Shapefile is stored.
tim@822: */
tim@649: private String shapeFilePath;
sascha@778:
tim@822: /**
tim@616: * Constructor
tim@616: */
tim@616: public LayerOutputState() {
tim@616: super();
tim@616: }
tim@616:
tim@616: public void out(Document format, Collection inputData,
tim@616: OutputStream outputStream, String uuid,
tim@616: CallContext callContext) throws StateException {
tim@616: log.debug("LayerOutputState.out");
tim@616: String outputMode = XMLUtils.xpathString(
tim@616: format, XPATH_OUTPUT_MODE, ArtifactNamespaceContext.INSTANCE);
tim@616: if (outputMode.equalsIgnoreCase("wms")) {
ingo@870:
ingo@870: Collection layerMetaData =
tim@859: this.getRequestedLayerMetadata();
tim@859: if (layerMetaData != null && !layerMetaData.isEmpty()){
tim@799: XMLUtils.toStream(this.getWMS(uuid, callContext,
tim@859: layerMetaData,inputData),
tim@723: outputStream);
tim@723: }else{
tim@723: this.writeExceptionReport2Stream(outputStream);
tim@723: }
tim@616: }else if (outputMode.equalsIgnoreCase("zip")){
ingo@870: Collection layerMetaData =
tim@859: this.getRequestedLayerMetadata();
tim@859:
tim@859: if (layerMetaData != null && !layerMetaData.isEmpty()){
ingo@870: this.writeZip(uuid, callContext,
tim@859: outputStream, layerMetaData);
tim@723: }else{
tim@723: this.writeExceptionReport2Stream(outputStream);
tim@723: }
sascha@778:
tim@616: }
tim@616: }
tim@723:
tim@723: /**
ingo@813: * Writes an exception to an output stream.
ingo@813: *
ingo@813: * @param outputStream The output stream used to write the exception to.
tim@723: */
tim@723: private void writeExceptionReport2Stream(OutputStream outputStream) {
tim@723: Document document = XMLUtils.newDocument();
ingo@813: ArtifactXMLUtilities.
tim@723: createExceptionReport("No Data to Export", document);
tim@723: XMLUtils.toStream(document,outputStream);
tim@723: }
sascha@778:
tim@649: /**
ingo@870: * Returns the Metadata for the requested Layers for fetching the data
tim@859: * of the Layer and generating the Layer and WMS.
tim@859: * @return the Metadata for the requested Layers
tim@649: */
tim@859: private Collection getRequestedLayerMetadata(){
tim@859: log.debug("LayerOutputState.getRequestedLayerMetadata");
tim@616: Collection result = this.getData(this.queryID);
tim@859: Collection returnValue = null;
tim@616: if (result != null){
tim@649: QueryExecutor queryExecutor = QueryExecutorFactory.getInstance()
tim@649: .getQueryExecutor();
tim@616: Iterator it = result.iterator();
tim@859: returnValue = new ArrayList(result.size());
tim@859: while (it.hasNext()){
tim@616: Result resultValue = it.next();
tim@649: String table = resultValue.getString(0);
tim@859: String geometryType = this.getGeometryType(table, queryExecutor);
tim@649: String where = resultValue.getString(1);
tim@728: String columns = this.fetchColumns(table);
tim@859: String templateID = resultValue.getString(2);
ingo@1057: String layername = resultValue.getString(3);
tim@859: String[] queryValues = null;
tim@859: String geometryWKT = null;
tim@649: if (this.geometryID != null){
sascha@778: InputData geometryInputData =
tim@649: this.inputData.get(this.geometryID);
tim@649: if (geometryInputData != null){
tim@649: try {
ingo@870:
tim@649: Collection geometryData = queryExecutor
tim@649: .executeQuery(this.geometryQueryID,
tim@649: new String[]{geometryInputData.getValue()});
tim@649: Iterator git = geometryData.iterator();
tim@649: if (git.hasNext()){
tim@649: Result geometryValue = git.next();
tim@649: geometryWKT = geometryValue.getString(0);
tim@649: }
tim@649: } catch (QueryException e) {
tim@649: log.error(e,e);
tim@649: }
tim@728: queryValues = new String[]{columns,
tim@728: table,
tim@649: where,
tim@649: geometryWKT};
tim@649: }else{
tim@729: //Look into the presetting for an WKT
sascha@778: InputData geometryWKTData = this.preSettings != null ?
tim@742: this.preSettings.get("geometry") :
tim@742: null ;
tim@729: if (geometryWKTData != null){
tim@729: queryValues = new String[]{columns,
tim@729: table,
tim@729: where,
tim@729: geometryWKTData.getValue()};
tim@1103: geometryWKT = geometryWKTData.getValue();
tim@729: }else{
tim@729: queryValues = new String[]{columns,table,where};
tim@729: }
tim@729: }
tim@729: }else{
tim@729: //Look into the presetting for an WKT
sascha@778: InputData geometryWKTData = this.preSettings != null ?
tim@742: this.preSettings.get("geometry") :
tim@742: null ;
tim@729: if (geometryWKTData != null){
tim@729: queryValues = new String[]{columns,
tim@729: table,
tim@729: where,
tim@729: geometryWKTData.getValue()};
tim@729: }else{
tim@728: queryValues = new String[]{columns,table,where};
tim@649: }
tim@649: }
ingo@1057: returnValue.add(new LayerMetaData(
ingo@1057: table, geometryType, where, columns,
ingo@1057: templateID, queryValues, geometryWKT, layername));
tim@616: }
tim@859: }
tim@859: return returnValue;
tim@859: }
sascha@778:
tim@859: /**
tim@859: * Fetches the Data from the Databasebackend.
tim@859: *
tim@859: * @return the resultdata.
tim@859: */
tim@1070: protected Collection fetchData(LayerMetaData layerMetaData, Envelope mbr){
tim@859: log.debug("LayerOutputState.fetchData");
tim@859: Collection data = null;
tim@859: QueryExecutor queryExecutor = QueryExecutorFactory.getInstance()
tim@859: .getQueryExecutor();
tim@859: try {
tim@859: data = queryExecutor.executeQuery(dataQueryID,
tim@859: layerMetaData.getQueryValues());
tim@1070: if (data != null){
tim@859: WKTReader wktReader = new WKTReader();
tim@1070: Geometry border = null;
tim@1070: if (layerMetaData.getGeometryWKT() != null){
tim@1070: border = wktReader.read(layerMetaData.getGeometryWKT());
tim@1070: }
tim@859: Iterator dataIt = data.iterator();
tim@859: while (dataIt.hasNext()){
tim@859: // Trim the Geometries using the
tim@859: // Geometry if one is available.
tim@859: Result current = dataIt.next();
tim@859: String currentWKT = current.getString(0);
tim@859: Geometry currentGeometry = null;
tim@859: try {
tim@859: currentGeometry = wktReader.read(currentWKT);
tim@859: } catch (Exception e) {
tim@859: log.error("Error parsing Geometry "+ currentWKT);
tim@859: log.error(e,e);
tim@859: }
tim@859: if (currentGeometry != null){
tim@1070: if (border != null){
tim@1070: currentGeometry = currentGeometry.intersection(border);
tim@1070: current.addColumnValue(0, currentGeometry.toText());
tim@1070: }
tim@1070: if (mbr.isNull()){
tim@1070: mbr.init(currentGeometry.getEnvelopeInternal());
tim@1070: }else{
tim@1070: mbr.expandToInclude(currentGeometry.getEnvelopeInternal());
tim@1070: }
tim@649: }
tim@649: }
tim@649: }
tim@859: } catch (QueryException e) {
tim@859: log.error(e,e);
tim@859: } catch (ParseException e){
tim@859: log.error(e,e);
tim@616: }
tim@616: return data;
tim@616: }
tim@616:
ingo@813:
ingo@813: /**
ingo@813: * This method determines the geometry type on basis of a table name.
ingo@813: *
ingo@813: * @param tableName Name of the table in the database.
ingo@813: * @param queryExecutor The QueryExecutor.
ingo@813: * @return the geometry type as string (e.g. MultiPolygon, Polygon, etc).
ingo@813: */
tim@799: private String getGeometryType(String tableName,
tim@799: QueryExecutor queryExecutor){
tim@799: String returnValue = null;
tim@799: String[] tables = tableName.toUpperCase().split(",");
tim@799: String[] filter = tables[0].split("\\.");
tim@799: try {
sascha@803: Collection result =
tim@799: queryExecutor.executeQuery(this.geometryTypeQueryID, filter);
tim@799: if (result != null && !result.isEmpty())
tim@799: {
tim@799: int geometryCode = result.iterator().next().getInteger(0);
sascha@803: if (geometryCode == 11 ||
tim@799: geometryCode == 10){
tim@799: returnValue = "MultiPolygon";
sascha@803: }else if (geometryCode == 9 ||
tim@799: geometryCode == 8){
tim@799: returnValue = "MultiLineString";
tim@799: }else if (geometryCode == 7){
tim@799: returnValue = "MultiPoint";
tim@799: }else if (geometryCode == 6){
tim@799: returnValue = "GeometryCollection";
sascha@803: }else if (geometryCode == 5 ||
tim@799: geometryCode == 4){
tim@799: returnValue = "Polygon";
sascha@803: }else if (geometryCode == 3 ||
tim@799: geometryCode == 2){
tim@799: returnValue = "LineString";
tim@799: }else if (geometryCode == 1){
tim@799: returnValue = "Point";
tim@799: }else if (geometryCode == 0){
tim@799: returnValue = "Geometry";
tim@799: }
tim@799: }
tim@799: } catch (QueryException e) {
tim@799: log.error(e,e);
tim@799: }
tim@799: return returnValue;
tim@799: }
ingo@813:
ingo@813:
ingo@813: /**
ingo@813: * Fetch the columns of a specific table.
ingo@813: *
ingo@813: * @param tableName The name of the table.
ingo@813: * @return the columns as string.
ingo@813: */
tim@728: private String fetchColumns(String tableName){
tim@728: String returnValue = null;
tim@728: try {
tim@756: String[] tables = tableName.toUpperCase().split(",");
tim@756: String[] filter = tables[0].split("\\.");
tim@756: // Only use the first Table the second one will be ignored.
tim@728: QueryExecutor queryExecutor = QueryExecutorFactory.getInstance()
tim@859: .getQueryExecutor();
tim@728: Collection columnData = queryExecutor.
sascha@778: executeQuery(this.columnQueryID,
tim@728: filter);
tim@728: if (columnData != null && !columnData.isEmpty()){
tim@728: StringBuffer sb = new StringBuffer();
tim@728: synchronized (sb) {
tim@728: Iterator it = columnData.iterator();
tim@728: while(it.hasNext()){
tim@728: Result current = it.next();
tim@728: sb.append(current.getString(0));
tim@728: if (it.hasNext()){
tim@728: sb.append(" , ");
tim@728: }
tim@728: }
tim@728: }
tim@728: returnValue = sb.toString();
tim@728: }
tim@728: } catch (QueryException e) {
tim@728: log.error(e,e);
tim@728: }
tim@728: return returnValue;
tim@728: }
ingo@813:
ingo@813:
tim@616: @Override
tim@616: public void setup(Node configuration) {
tim@616: log.debug("LayerOutputState.setup");
tim@616: super.setup(configuration);
tim@649: this.dataQueryID = Config.getStringXPath(configuration,
tim@649: "queryID-layerdata");
tim@649: this.geometryID = Config.getStringXPath(configuration,
tim@649: "inputvalue-geometry");
tim@649: this.geometryQueryID = Config.getStringXPath(configuration,
tim@649: "queryID-geometry");
sascha@778:
tim@728: this.columnQueryID = "layer_colums"; //Config.getStringXPath(configuration,
tim@728: // "queryID-columns");
tim@799: this.geometryTypeQueryID = "geometry_type";
tim@616: }
sascha@778:
ingo@813:
ingo@813: /**
tim@822: * Write the resultdata to shapefiles.
ingo@813: *
ingo@813: * @param uuid The UUID of the current artifact.
ingo@813: * @param data The finalized data used for shapefile creation.
ingo@813: * @param callContext The CallContext object.
ingo@813: * @param geometryType The geometry type.
ingo@813: * @return the shapefile path.
ingo@813: */
tim@649: protected String writeToShapeFile(
tim@649: String uuid,
tim@649: Collection data,
tim@799: CallContext callContext,
tim@859: String geometryType,
tim@859: int layerNumber
tim@649: ) {
tim@649: boolean success = false;
tim@859: if (data != null && !data.isEmpty()){
tim@859: File shapeDir = new File(shapeFilePath);
tim@859: try {
tim@859: File shapeFile = new File(shapeDir, createShapeFileName(layerNumber));
tim@859: if (!ShapeFileWriter.writeDataToFile(shapeFile, "data", data,geometryType)){
tim@859: log.error("writing data into shapefile failed");
tim@649: return null;
tim@649: }
tim@859: success = true;
tim@859: callContext.afterCall(CallContext.STORE);
tim@859: return shapeFilePath;
tim@649: }
tim@859: finally {
tim@859: if (!success) {
tim@859: FileUtils.deleteRecursive(shapeDir);
tim@859: }
tim@649: }
tim@859: }else{
tim@859: return null;
tim@649: }
tim@649: }
sascha@778:
tim@859: /**
tim@859: * Check if the ShapeDir exists and if it exists delete all Contents
tim@859: * in it. If it not exists the Director will be created.
tim@859: * @param baseDir the BaseDirectory for all ShapeDirs
tim@859: * @param uuid the UUID which is used to create the Directory
ingo@870: * @return true if the directory exists or could be created.
tim@859: * false if the directory could not be created.
tim@859: */
tim@859: private boolean createShapeDir(File baseDir, String uuid){
tim@859: File shapeDir = new File(baseDir, uuid);
tim@859: boolean createdDir = false;
tim@859: synchronized (shapeFileLock) {
tim@859: if (shapeDir.exists()) {
tim@859: FileUtils.deleteContent(shapeDir); // TODO Place on getZip and getWMS
tim@859: }
tim@859: else if (!shapeDir.mkdirs()) {
tim@859: log.error("cannot create directory '"
tim@859: + shapeDir.getAbsolutePath() + "'");
tim@859: return false;
tim@859: }
tim@859: createdDir = true;
tim@859: }
tim@859: shapeFilePath = shapeDir.getAbsolutePath();
tim@859: return createdDir;
tim@859: }
ingo@813:
ingo@813: /**
ingo@813: * Create a zip archive with the shapefiles of the given shapefiles path and
ingo@813: * write it to output
.
ingo@813: *
ingo@813: * @param uuid The UUID of the current artifact.
ingo@813: * @param callContext The CallContext object.
ingo@813: * @param output The output stream.
ingo@813: * @param data The data to be written to shapefile.
ingo@813: * @param geometryType The geometry type.
ingo@813: * @throws StateException if an error occured while zipfile creation.
ingo@813: */
tim@649: protected void writeZip(
tim@649: String uuid,
tim@649: CallContext callContext,
tim@649: OutputStream output,
tim@859: Collection layerMetaData
sascha@778: )
tim@649: throws StateException
tim@649: {
tim@649: try {
tim@649: String p = getShapeFilePath();
tim@649: if (p != null) {
tim@649: File dir = new File(p);
tim@649: if (dir.isDirectory()) {
tim@649: FileUtils.createZipArchive(dir, output);
tim@649: }
tim@649: }
tim@649: else {
tim@859: File baseDir = shapefileDirectory(callContext);
tim@859: if (!this.createShapeDir(baseDir, uuid)){
tim@859: return;
tim@859: }
tim@859: Iterator it = layerMetaData.iterator();
tim@859: int i = 1;
tim@1070: Envelope mbr = new Envelope();
tim@859: while(it.hasNext()){
tim@859: LayerMetaData lmd = it.next();
tim@1070: Collection data = this.fetchData(lmd, mbr);
tim@859: p = writeToShapeFile(uuid, data, callContext,lmd.getGeometryType(),i++);
tim@859: }
tim@859: if (p != null) {
tim@649: FileUtils.createZipArchive(new File(p), output);
tim@649: }
tim@649: }
tim@649: }
tim@649: catch (IOException ioe) {
tim@649: log.error(ioe.getLocalizedMessage(), ioe);
tim@649: }
tim@649: }
sascha@778:
ingo@813: /**
ingo@813: * Returns the shapefile path.
ingo@813: *
ingo@813: * @return the shapefile path.
ingo@813: */
tim@649: public String getShapeFilePath() {
tim@649: synchronized (shapeFileLock) {
tim@649: return shapeFilePath;
tim@649: }
tim@649: }
sascha@778:
ingo@1044:
ingo@1044: /**
ingo@1044: * Set the shapefile path.
ingo@1044: */
ingo@1044: public void setShapeFilePath(String shapeFilePath) {
ingo@1044: synchronized (shapeFileLock) {
ingo@1044: this.shapeFilePath = shapeFilePath;
ingo@1044: }
ingo@1044: }
ingo@1044:
tim@859: /**
tim@859: * Returns the basic-directory where the Shapefiles should be placed in.
tim@859: * @param callContext the Context of this Call
tim@859: * @return the Directory where the Shapefiles could be placed in.
tim@859: * (Please create an own directory in this dir and not put the
tim@859: * Files directly in it)
tim@859: */
tim@649: private static File shapefileDirectory(CallContext callContext) {
tim@859: // Code was taken from HorizontalCrossSectionMeshOutputState
tim@649: GNVArtifactContext context =
tim@649: (GNVArtifactContext)callContext.globalContext();
tim@649: File dir = (File)context.get(
tim@649: GNVArtifactContext.HORIZONTAL_CROSS_SECTION_RESULT_SHAPEFILE_PATH_KEY);
tim@649: return dir != null
tim@649: ? dir
tim@649: : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SHAPEFILE_PATH;
tim@649: }
sascha@778:
ingo@813:
tim@649: @Override
tim@649: public void endOfLife(Object globalContext) {
tim@649: super.endOfLife(globalContext);
tim@649: // do it in background
tim@649: new Thread() {
ingo@813: @Override
tim@649: public void run() {
tim@649: String path = resetShapeFilePath();
tim@649: if (path == null) {
tim@649: return;
tim@649: }
tim@649: File dir = new File(path);
tim@649: for (int i = 0; i < 10; ++i) {
tim@649: if (!dir.exists() || FileUtils.deleteRecursive(dir)) {
tim@649: MapfileGenerator.getInstance().update();
tim@649: return;
tim@649: }
tim@649: try {
tim@649: Thread.sleep(10000L);
tim@649: }
tim@649: catch (InterruptedException ie) {
tim@649: }
tim@649: }
tim@649:
tim@649: log.error("failed to remove directory '" + path + "'");
tim@649: } // run
tim@649: }.start();
tim@649: }
sascha@778:
tim@822: /**
tim@822: * Resets the Settings e.g shapeFilePath and templateID
tim@822: * @return
tim@822: */
tim@822: private String resetShapeFilePath() {
tim@649: synchronized (shapeFileLock) {
tim@649: String path = shapeFilePath;
tim@649: shapeFilePath = null;
tim@649: return path;
tim@649: }
tim@649: }
ingo@813:
ingo@813:
ingo@813: /**
ingo@813: * Write data to shapefiles and feed a map service with information about
ingo@813: * these shapefiles. The map service can be queried for displaying
ingo@813: * corresponding layers as WMS.
ingo@813: *
ingo@813: * @param uuid The UUID of the current artifact.
ingo@813: * @param callContext The CallContext object.
tim@859: * @param layerMetaData The Metadata which is required to create the
tim@859: * different Layers.
tim@828: * @param inputData the Parameters which are send by the out-Call.
ingo@813: * @return a document with some meta information (shapefile path, geometry
ingo@813: * type, time to live of the current artifact, etc).
ingo@813: * @throws StateException if an error occured while shapefile writing.
ingo@813: */
ingo@1044: protected Document getWMS(
ingo@1044: String uuid,
ingo@1044: CallContext callContext,
ingo@1044: Collection layerMetaData,
ingo@1044: Collection inputData)
tim@655: throws StateException
tim@655: {
ingo@1044: Document document = XMLUtils.newDocument();
ingo@1044:
ingo@1044: File baseDir = shapefileDirectory(callContext);
ingo@1044: File shapeDir = new File(baseDir, uuid);
ingo@1044:
ingo@1044: boolean success = false;
ingo@1044: boolean createdDir = false;
ingo@1044:
ingo@1044: try {
ingo@1044: // create shapefile directory or delete content if it already exists
ingo@1044: synchronized (shapeFileLock) {
ingo@1044: if (shapeDir.exists()) {
ingo@1044: FileUtils.deleteContent(shapeDir);
tim@859: }
ingo@1044: else if (!shapeDir.mkdirs()) {
ingo@1044: log.error("cannot create directory '"
ingo@1044: + shapeDir.getAbsolutePath() + "'");
ingo@1044: return null;
ingo@1044: }
ingo@1044: setShapeFilePath(shapeDir.getAbsolutePath());
ingo@1044: createdDir = true;
tim@859: }
ingo@1044:
ingo@1044: // process data
tim@859: Iterator it = layerMetaData.iterator();
ingo@1057:
ingo@1057: // create meta file
ingo@1057: Document meta = MetaWriter.initMeta();
ingo@1057: MetaWriter.insertAbstractMeta(callContext, meta);
ingo@1057:
ingo@1057: String path = getShapeFilePath();
ingo@1057: String prefix = getLayerPrefix(inputData);
ingo@1057:
ingo@1057: if (prefix == null) {
ingo@1057: prefix = uuid;
ingo@1057: }
ingo@1057:
tim@859: int layerNumber = 0;
tim@1070: Envelope mbr = new Envelope();
tim@859: while (it.hasNext()){
tim@859: LayerMetaData lmd = it.next();
tim@859: layerNumber ++;
ingo@1057:
tim@859: String geometryType = lmd.getGeometryType();
ingo@1057: String templateId = lmd.getTemplateID();
ingo@1057:
tim@859: ExclusiveExec.UniqueKey key = ExclusiveExec.INSTANCE.acquire(uuid);
tim@859: try{
tim@1070: Collection results = this.fetchData(lmd,mbr);
ingo@1057: if (results != null && writeToShapeFile(uuid, results,
ingo@1057: callContext,
ingo@1057: geometryType,
ingo@1057: layerNumber) != null) {
ingo@1057: String name = getLayerName(uuid, layerNumber);
ingo@1057: String base = lmd.getLayertitle();
ingo@1057: String title = getLayerTitle(prefix, base);
ingo@1057: String data = getLayerData(
ingo@1057: uuid, createShapeFileName(layerNumber));
ingo@1057: String type = determineGeometryType(geometryType);
ingo@1057: String status = "OFF";
ingo@1057: String model = findParameterTitle(
ingo@1057: geometryType, templateId);
ingo@1057:
ingo@1057: MetaWriter.insertLayer(
ingo@1057: callContext, meta, name, title,
ingo@1057: data, model, type, status);
tim@859: }
ingo@1044:
ingo@1044: success = true;
ingo@1044:
tim@859: if (meta != null && !it.hasNext()) {
tim@1070: MetaWriter.insertMbr(mbr, "EPSG:4326",meta);
ingo@1057: MetaWriter.writeMetaFile(path, meta);
tim@859: MapfileGenerator.getInstance().update();
ingo@1057: return meta;
tim@859: }
tim@859: }finally{
tim@859: ExclusiveExec.INSTANCE.release(key);
tim@859: }
tim@859: }
tim@1070:
tim@859: return document;
tim@859: }
ingo@1044: finally {
ingo@1044: if (!success && createdDir) {
ingo@1044: FileUtils.deleteRecursive(shapeDir);
ingo@1044: }
ingo@1044: }
tim@859: }
tim@655:
tim@859: /**
tim@859: * Creates the name of the Shapefile
tim@859: * @param layerNumber the Number of the Layer
tim@859: * @return the create name of the Shapefile.
tim@859: */
tim@859: private String createShapeFileName(int layerNumber) {
tim@859: return SHAPEFILE_NAME+"_"+layerNumber+".shp";
tim@859: }
tim@655:
sascha@778:
ingo@1057: protected String getLayerName(String uuid, int idx) {
ingo@1111: return "GNV_" + uuid + "_" + idx;
ingo@1057: }
ingo@1057:
ingo@1057:
ingo@1057: protected String getLayerTitle(String prefix, String base) {
ingo@1111: return "GNV_" + prefix + "_" + base;
ingo@1057: }
ingo@1057:
ingo@1057:
ingo@1057: protected String getLayerData(String shapeDir, String filename) {
ingo@1057: File path = new File(shapeDir, filename);
ingo@1057:
ingo@1057: return path.toString();
ingo@1057: }
ingo@1057:
ingo@1057:
tim@828: /**
tim@828: * Returns the parameterType for the Layer.
tim@828: * @param geometryType
tim@828: * @return
tim@828: */
tim@859: private String findParameterTitle(String geometryType, String templateID) {
tim@828: String paramType = LAYER_MODEL+"_"+templateID;
tim@828: if (!MapfileGenerator.getInstance().templateExists(paramType)){
tim@828: // If the template doesn't exist the Defaulttemplates will be used.
tim@828: paramType = LAYER_MODEL+"_"+
tim@828: this.determineDefaultTemplateName(geometryType);
tim@828: }
tim@828: return paramType;
tim@828: }
tim@828:
tim@828: /**
tim@828: * Find the title for a wms layer specified by the user.
tim@828: *
tim@828: * @param inputData A collection with InputData objects.
tim@828: * @return the title.
tim@828: */
ingo@1057: protected String getLayerPrefix(Collection inputData) {
tim@828: for (InputData data: inputData) {
tim@828: String name = data.getName();
tim@828: if (name != null && name.equals("title")) {
tim@828: return (String) data.getValue();
tim@828: }
tim@828: }
tim@828: return null;
tim@828: }
tim@828:
ingo@813:
ingo@813: /**
ingo@813: * Turns the geometry type into a form used for the templating mechanism
ingo@813: * while mapfile generation.
sascha@835: *
ingo@813: * @param geometryType The original geometry type.
ingo@813: * @return a valid geometry type fpr the template mechanism.
ingo@813: */
tim@799: private String determineGeometryType(String geometryType){
tim@799: String returnValue = geometryType.toLowerCase();
tim@655: if (returnValue.equalsIgnoreCase("linestring")){
tim@655: returnValue = "Line";
tim@799: }else if (returnValue.equalsIgnoreCase("multilinestring")){
tim@799: returnValue ="Line";
tim@799: }else if (returnValue.equalsIgnoreCase("multipolygon")){
tim@799: returnValue = "Polygon";
tim@799: }
tim@799: return returnValue;
tim@799: }
sascha@803:
ingo@813:
ingo@813: /**
ingo@813: * Determine the default template name if no special template is existing
ingo@813: * for this layer.
ingo@813: *
ingo@813: * @param geometryType The geometry type.
ingo@813: * @return a default geometry fitting to the original geometry type.
ingo@813: */
tim@799: private String determineDefaultTemplateName(String geometryType){
tim@799: String returnValue = geometryType.toLowerCase();
tim@799: if (returnValue.equalsIgnoreCase("multilinestring")){
tim@799: returnValue ="linestring";
tim@799: }else if (returnValue.equalsIgnoreCase("multipolygon")){
tim@799: returnValue = "polygon";
tim@799: }else if (returnValue.equalsIgnoreCase("multipoint")){
tim@799: returnValue = "point";
tim@655: }
tim@655: return returnValue;
tim@655: }
tim@616: }
sascha@836: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :