diff gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java @ 622:89aca25642d6

Implemented method stubs of MapfileGenerator. Mapfiles are successfully created corresponding meta.xml files. gnv-artifacts/trunk@693 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Fri, 19 Feb 2010 13:28:34 +0000
parents 567216b56983
children 65f09139e9b3
line wrap: on
line diff
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java	Wed Feb 17 09:40:15 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java	Fri Feb 19 13:28:34 2010 +0000
@@ -1,6 +1,36 @@
 package de.intevation.gnv.utils;
 
+import de.intevation.artifactdatabase.Config;
+import de.intevation.artifactdatabase.XMLUtils;
+import de.intevation.artifacts.ArtifactNamespaceContext;
+import de.intevation.gnv.artifacts.context.GNVArtifactContext;
+import de.intevation.gnv.wms.LayerInfo;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+
+import javax.xml.xpath.XPathConstants;
+
 import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 
 /**
@@ -9,9 +39,29 @@
 public class MapfileGenerator
 extends Thread
 {
+    public static final String TEMPLATE_PATH =
+        "/artifact-database/map-generator/templates/path/text()";
+
+    public static final String TEMPLATE_MAPFILE =
+        "/artifact-database/map-generator/templates/maptemplate/text()";
 
     public static final String MAPFILE_PATH =
-        "/artifact-database/map-generator/mapfile/@path";
+        "/artifact-database/map-generator/mapfile/path/text()";
+
+    public static final String MAPFILE_NAME =
+        "/artifact-database/map-generator/mapfile/name/text()";
+
+    public static final String SHAPEFILE_BASE_DIR =
+        "/artifact-database/map-generator/mapfile/shapefiles/text()";
+
+    public static final String META_FILE_NAME = "meta.xml";
+
+    public static final String XPATH_LAYER        = "/art:meta/art:layer";
+    public static final String XPATH_LAYER_NAME   = "art:name";
+    public static final String XPATH_LAYER_TYPE   = "art:type";
+    public static final String XPATH_LAYER_DATA   = "art:data";
+    public static final String XPATH_LAYER_STATUS = "art:status";
+    public static final String XPATH_LAYER_MODEL  = "art:model";
 
     protected static final long SLEEPTIME = 10 * 1000L; // 10 seconds
 
@@ -19,6 +69,7 @@
 
     private static MapfileGenerator instance;
 
+    private VelocityEngine velocityEngine;
     private boolean lock[];
 
 
@@ -29,7 +80,7 @@
 
 
     public static void main(String[] args) {
-        // TODO Implement me
+        // TODO IMPLEMENT ME
     }
 
 
@@ -46,6 +97,7 @@
 
     public void update() {
         synchronized (lock) {
+            logger.debug("update");
             lock[0] = true;
             lock.notify();
         }
@@ -53,27 +105,292 @@
 
 
     public void run() {
+        logger.debug("Start MapfileGenerator thread...");
         try {
             for (;;) {
                 synchronized (lock) {
                     while (!lock[0]) {
                         lock.wait(SLEEPTIME);
                     }
-                    
                     lock[0] = false;
                 }
-                
-                logger.info("Update mapfile for MapServer.");
+
+                logger.debug("Start sync process now...");
                 generate();
             }
         }
         catch (InterruptedException ie) {
+            logger.debug("MapfileGenerator thread got an interrupt.");
+        }
+        finally {
+            logger.debug("THREAD END");
         }
     }
 
 
-    private void generate() {
-        logger.debug("IMPLEMENT ME");
+    protected void generate() {
+        File basedir       = new File(getShapefileBaseDir());
+        List layers        = new ArrayList();
+        searchMetaInformation(basedir, layers);
+        writeMapfile(layers);
+    }
+
+
+    protected VelocityEngine getVelocityEngine() {
+        if (velocityEngine == null) {
+            velocityEngine = new VelocityEngine();
+            try {
+                setupVelocity(velocityEngine);
+            }
+            catch (Exception e) {
+                logger.error(e, e);
+                return null;
+            }
+        }
+        return velocityEngine;
+    }
+
+
+    protected void setupVelocity(VelocityEngine engine)
+    throws Exception
+    {
+        Properties ps = new Properties();
+
+        ps.setProperty(
+            "input.encoding",
+            "UTF-8");
+
+        ps.setProperty(
+            "resource.loader",
+            "class");
+
+        ps.setProperty(
+            "class.resource.loader.class",
+            "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+
+        engine.init(ps);
+    }
+
+
+    protected String getTemplateBaseDir() {
+        return Config.getStringXPath(TEMPLATE_PATH);
+    }
+
+
+    protected Template getTemplateByName(String model) {
+        String templatePath   = getTemplateBaseDir();
+        if (model.indexOf(".vm") < 0) {
+            model = model.concat(".vm");
+        }
+
+        File file = new File(templatePath, model);
+        if (!file.exists() || !file.canRead()) {
+            logger.warn("Can't find template file: " + file.getAbsolutePath());
+            return null;
+        }
+
+        try {
+            VelocityEngine engine = getVelocityEngine();
+            if (engine == null) {
+                logger.error("Error while fetching VelocityEngine.");
+                return null;
+            }
+
+            return engine.getTemplate(file.getAbsolutePath());
+        }
+        catch (Exception e) {
+            logger.warn(e, e);
+        }
+
+        return null;
+    }
+
+
+    protected Template getMapfileTemplate()
+    throws Exception
+    {
+        String mapfileName = Config.getStringXPath(TEMPLATE_MAPFILE);
+        return getTemplateByName(mapfileName);
+    }
+
+
+    protected String getShapefileBaseDir() {
+        return Config.getStringXPath(SHAPEFILE_BASE_DIR);
+    }
+
+
+    protected void searchMetaInformation(File file, List store) {
+        if (file.isDirectory()) {
+            File[] files = file.listFiles();
+
+            if (files != null && files.length != 0) {
+                int size = files.length;
+                for (File tmp: files) {
+                    searchMetaInformation(tmp, store);
+                }
+            }
+        }
+        else if (file.getName().equals(META_FILE_NAME)) {
+            LayerInfo[] info = parseMeta(file);
+
+            int infoSize = info.length;
+            for (int j = 0; j < infoSize; j++) {
+                if (info[j] != null) {
+                    store.add(info[j]);
+                }
+            }
+        }
+    }
+
+
+    protected LayerInfo[] parseMeta(File file) {
+        Document meta = XMLUtils.parseDocument(file);
+        List layers   = new ArrayList();
+
+        NodeList layerset = (NodeList) XMLUtils.xpath(
+            meta,
+            XPATH_LAYER,
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        int size = layerset.getLength();
+        for (int i = 0; i < size; i++) {
+            LayerInfo info = parseLayer(layerset.item(i));
+
+            if (info != null && !info.isEmpty() && !info.isBroken()) {
+                layers.add(info);
+            }
+            else {
+                logger.warn("Found broken LayerInfo object.");
+            }
+        }
+
+        return (LayerInfo[]) layers.toArray(new LayerInfo[layers.size()]);
+    }
+
+
+    protected LayerInfo parseLayer(Node layer) {
+        LayerInfo info  = new LayerInfo();
+
+        String name = parseLayerAttr(layer, XPATH_LAYER_NAME);
+        if (name != null && !name.equals("")) {
+            info.setName(name);
+        }
+
+        String model = parseLayerAttr(layer, XPATH_LAYER_MODEL);
+        if (model != null && !model.equals("")) {
+            info.setModel(model);
+        }
+
+        String type = parseLayerAttr(layer, XPATH_LAYER_TYPE);
+        if (type != null && !type.equals("")) {
+            info.setType(type);
+        }
+
+        String data = parseLayerAttr(layer, XPATH_LAYER_DATA);
+        if (data != null && !data.equals("")) {
+            info.setData(data);
+        }
+
+        String status = parseLayerAttr(layer, XPATH_LAYER_STATUS);
+        if (status != null && !status.equals("")) {
+            info.setStatus(status);
+        }
+
+        return info;
+    }
+
+
+    protected String parseLayerAttr(Node node, String xpath) {
+        return (String) XMLUtils.xpath(
+            node,
+            xpath,
+            XPathConstants.STRING,
+            ArtifactNamespaceContext.INSTANCE);
+    }
+
+
+    protected void writeMapfile(List layers) {
+        String pathName   = Config.getStringXPath(MAPFILE_PATH);
+        String mapName    = Config.getStringXPath(MAPFILE_NAME);
+        String tmpMapName = "mapfile" + new Date().getTime();
+
+        int layersize         = layers.size();
+        StringBuilder sb      = new StringBuilder();
+        StringWriter sw       = null;
+        LayerInfo info        = null;
+
+        for (int i = 0; i < layersize; i++) {
+            sw   = new StringWriter();
+            info = (LayerInfo) layers.get(i);
+
+            Template layerTemplate  = getTemplateByName(info.getModel());
+            VelocityContext context = new VelocityContext();
+            context.put("info", info);
+
+            try {
+                layerTemplate.merge(context, sw);
+                sb.append(sw.toString());
+            }
+            catch (IOException ioe) {
+                logger.warn("Error while filling layer template.");
+                logger.warn(ioe, ioe);
+            }
+        }
+
+        Writer writer = null;
+        File   tmp    = null;
+        File   map    = null;
+
+        try {
+            tmp = new File(pathName, tmpMapName);
+            map = new File(pathName, mapName);
+
+            tmp.createNewFile();
+            writer   = new FileWriter(tmp);
+
+            VelocityContext context = new VelocityContext();
+            context.put("LAYERS", sb.toString());
+
+            Template mapTemplate = getMapfileTemplate();
+            if (mapTemplate == null) {
+                logger.warn("No mapfile template found.");
+                return;
+            }
+
+            mapTemplate.merge(context, writer);
+
+            // we need to create a temporary mapfile first und rename it into
+            // real mapfile because we don't run into race conditions on this
+            // way. (iw)
+            tmp.renameTo(map);
+        }
+        catch (FileNotFoundException fnfe) {
+            logger.error(fnfe, fnfe);
+        }
+        catch (IOException ioe) {
+            logger.error(ioe, ioe);
+        }
+        catch (Exception e) {
+            logger.error(e, e);
+        }
+        finally {
+            try {
+                // close file writer
+                if (writer != null) {
+                    writer.close();
+                }
+
+                // remove temporary mapfile if an error occured and it still
+                // exists
+                if (tmp.exists()) {
+                    tmp.delete();
+                }
+            }
+            catch (IOException ioe) {
+                logger.debug(ioe, ioe);
+            }
+        }
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org