diff gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.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 40ead2d2a08d
children 9ba6bb85d6dd
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java	Fri Sep 28 12:13:53 2012 +0200
@@ -0,0 +1,417 @@
+package de.intevation.gnv.utils;
+
+import de.intevation.artifactdatabase.Config;
+import de.intevation.artifactdatabase.XMLUtils;
+import de.intevation.artifacts.ArtifactNamespaceContext;
+import de.intevation.gnv.wms.LayerInfo;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+
+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;
+
+
+/**
+ * @author Ingo Weinzierl (ingo.weinzierl@intevation.de)
+ */
+public class MapfileGenerator
+extends Thread
+{
+    public static final String TEMPLATE_PATH =
+        "/artifact-database/gnv/map-generator/templates/path/text()";
+
+    public static final String TEMPLATE_MAPFILE =
+        "/artifact-database/gnv/map-generator/templates/maptemplate/text()";
+
+    public static final String MAPFILE_PATH =
+        "/artifact-database/gnv/map-generator/mapfile/@path";
+
+    public static final String SHAPEFILE_BASE_DIR =
+        "/artifact-database/gnv/shapefile-directory/@path";
+
+    public static final String VELOCITY_LOGFILE =
+        "/artifact-database/velocity/logfile/@path";
+
+    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
+
+    private static Logger logger = Logger.getLogger(MapfileGenerator.class);
+
+    private static MapfileGenerator instance;
+
+    private File   mapfile;
+    private String shapefileDirectory;
+    private String templatePath;
+    private String velocityLogfile;
+
+    private VelocityEngine velocityEngine;
+    private boolean lock[];
+
+
+
+    private MapfileGenerator() {
+        lock = new boolean[1];
+    }
+
+
+    public static void main(String[] args) {
+        // TODO IMPLEMENT ME
+    }
+
+
+    public static synchronized MapfileGenerator getInstance() {
+        if (instance == null) {
+            instance = new MapfileGenerator();
+            instance.setDaemon(true);
+            instance.start();
+        }
+
+        return instance;
+    }
+
+
+    public void update() {
+        synchronized (lock) {
+            logger.debug("update");
+            lock[0] = true;
+            lock.notify();
+        }
+    }
+
+
+    public void run() {
+        logger.debug("Start MapfileGenerator thread...");
+        try {
+            for (;;) {
+                synchronized (lock) {
+                    while (!lock[0]) {
+                        lock.wait(SLEEPTIME);
+                    }
+                    lock[0] = false;
+                }
+
+                logger.debug("Start sync process now...");
+                generate();
+            }
+        }
+        catch (InterruptedException ie) {
+            logger.debug("MapfileGenerator thread got an interrupt.");
+        }
+        finally {
+            logger.debug("THREAD END");
+        }
+    }
+
+
+    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
+    {
+        engine.setProperty(
+            "input.encoding",
+            "UTF-8");
+
+        engine.setProperty(
+            VelocityEngine.RUNTIME_LOG,
+            getVelocityLogfile());
+
+        engine.setProperty(
+            "resource.loader",
+            "file");
+
+        engine.setProperty(
+            "file.resource.loader.path",
+            getTemplateBaseDir());
+
+        engine.init();
+    }
+
+
+    protected String getVelocityLogfile() {
+        if (velocityLogfile == null)
+            velocityLogfile = Config.getStringXPath(VELOCITY_LOGFILE);
+
+        return velocityLogfile;
+    }
+
+
+    protected String getTemplateBaseDir() {
+        if (templatePath == null) {
+            templatePath = Config.getStringXPath(TEMPLATE_PATH);
+            templatePath = Config.replaceConfigDir(templatePath);
+        }
+
+        return templatePath;
+    }
+
+
+    protected Template getTemplateByName(String model) {
+        if (model.indexOf(".vm") < 0) {
+            model = model.concat(".vm");
+        }
+
+        try {
+            VelocityEngine engine = getVelocityEngine();
+            if (engine == null) {
+                logger.error("Error while fetching VelocityEngine.");
+                return null;
+            }
+
+            return engine.getTemplate(model);
+        }
+        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() {
+        if (shapefileDirectory == null) {
+            shapefileDirectory = Config.getStringXPath(SHAPEFILE_BASE_DIR);
+            shapefileDirectory = Config.replaceConfigDir(shapefileDirectory);
+        }
+
+        return shapefileDirectory;
+    }
+
+
+    protected File getMapfile() {
+        if (mapfile == null) {
+            String tmp = Config.getStringXPath(MAPFILE_PATH);
+            tmp        = Config.replaceConfigDir(tmp);
+            mapfile    = new File(tmp);
+        }
+
+        return mapfile;
+    }
+
+
+    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 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);
+            }
+        }
+
+        File   map    = getMapfile();
+        Writer writer = null;
+        File   tmp    = null;
+
+        try {
+            tmp = new File(map.getParent(), tmpMapName);
+
+            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