diff flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java @ 1190:f514894ec2fd

merged flys-artifacts/2.5
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:17 +0200
parents bcf70a452646
children 6c0b79efd2c9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/MapfileGenerator.java	Fri Sep 28 12:14:17 2012 +0200
@@ -0,0 +1,462 @@
+package de.intevation.flys.utils;
+
+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 org.apache.log4j.Logger;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+import de.intevation.flys.artifacts.model.LayerInfo;
+
+/**
+ * This class iterates over a bunch of directories, searches for meta
+ * information coresponding to shapefiles and creates a mapfile which is used by
+ * a <i>MapServer</i>.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class MapfileGenerator
+extends Thread
+{
+    public static final String WSPLGEN_RESULT_SHAPE   = "wsplgen.shp";
+    public static final String WSPLGEN_LINES_SHAPE    = "barrier_lines.shp";
+    public static final String WSPLGEN_POLYGONS_SHAPE = "barrier_polygons.shp";
+
+    public static final String MS_WSPLGEN_POSTFIX  = "-wsplgen";
+    public static final String MS_BARRIERS_POSTFIX = "-barriers";
+    public static final String MS_LINE_POSTFIX     = "-lines";
+    public static final String MS_POLYGONS_POSTFIX = "-polygons";
+
+    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 File shapefileDirectory;
+
+    private String mapServerUrl;
+    private String templatePath;
+    private String velocityLogfile;
+
+    private VelocityEngine velocityEngine;
+    private boolean lock[];
+
+
+
+    private MapfileGenerator() {
+        lock = new boolean[1];
+    }
+
+
+    /**
+     * A main method which can be used to create a mapfile without a running
+     * artifact server.<br>
+     * <b>NOTE:</b> This method is not implemented yet!
+     *
+     * @param args Arguments.
+     */
+    public static void main(String[] args) {
+        throw new Error("MapfileGenerator.main() is CURRENTLY NOT IMPLEMENTED!");
+    }
+
+
+    /**
+     * Returns the instance of this generator.
+     *
+     * @return the instance.
+     */
+    public static synchronized MapfileGenerator getInstance() {
+        if (instance == null) {
+            instance = new MapfileGenerator();
+            instance.setDaemon(true);
+            instance.start();
+        }
+
+        return instance;
+    }
+
+
+    /**
+     * Triggers the mapfile generation process.
+     */
+    public void update() {
+        synchronized (lock) {
+            logger.debug("update");
+            lock[0] = true;
+            lock.notify();
+        }
+    }
+
+
+    /**
+     * Thread to generate a mapfile.
+     */
+    @Override
+    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.");
+        }
+        catch (FileNotFoundException fnfe) {
+            logger.debug("Error while mapfile creation: " + fnfe.getMessage());
+        }
+        finally {
+            logger.debug("THREAD END");
+        }
+    }
+
+    /**
+     * Method to check the existance of a template file.
+     *
+     * @param templateID The name of a template.
+     * @return true, of the template exists - otherwise false.
+     */
+    public boolean templateExists(String templateID){
+        Template template = getTemplateByName(templateID);
+        return template != null;
+    }
+
+
+    /**
+     * Method which starts searching for meta information file and mapfile
+     * generation.
+     */
+    protected void generate()
+    throws    FileNotFoundException
+    {
+        File[]        userDirs = getUserDirs();
+        List<LayerInfo> layers = parseLayers(userDirs);
+
+        logger.info("Found " + layers.size() + " layers for user mapfile.");
+
+        writeMapfile(layers);
+    }
+
+
+    /**
+     * Returns the VelocityEngine used for the template mechanism.
+     *
+     * @return the velocity engine.
+     */
+    protected VelocityEngine getVelocityEngine() {
+        if (velocityEngine == null) {
+            velocityEngine = new VelocityEngine();
+            try {
+                setupVelocity(velocityEngine);
+            }
+            catch (Exception e) {
+                logger.error(e, e);
+                return null;
+            }
+        }
+        return velocityEngine;
+    }
+
+
+    /**
+     * Initialize velocity.
+     *
+     * @param engine Velocity engine.
+     * @throws Exception if an error occured while initializing velocity.
+     */
+    protected void setupVelocity(VelocityEngine engine)
+    throws Exception
+    {
+        engine.setProperty(
+            "input.encoding",
+            "UTF-8");
+
+        engine.setProperty(
+            VelocityEngine.RUNTIME_LOG,
+            FLYSUtils.getXPathString(FLYSUtils.XPATH_VELOCITY_LOGFILE));
+
+        engine.setProperty(
+            "resource.loader",
+            "file");
+
+        engine.setProperty(
+            "file.resource.loader.path",
+            FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_TEMPLATE_PATH));
+
+        engine.init();
+    }
+
+
+    /**
+     * Returns a template specified by <i>model</i>.
+     *
+     * @param model The name of the template.
+     * @return a template.
+     */
+    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;
+    }
+
+
+    /**
+     * Returns the mapfile  template.
+     *
+     * @return the mapfile template.
+     * @throws Exception if an error occured while reading the configuration.
+     */
+    protected Template getMapfileTemplate()
+    throws Exception
+    {
+        String mapfileName = FLYSUtils.getXPathString(
+            FLYSUtils.XPATH_MAPFILE_TEMPLATE);
+
+        return getTemplateByName(mapfileName);
+    }
+
+
+    /**
+     * Returns the base directory storing the shapefiles.
+     *
+     * @return the shapefile base directory.
+     *
+     * @throws FileNotFoundException if no shapefile path is found or
+     * configured.
+     */
+    protected File getShapefileBaseDir()
+    throws    FileNotFoundException
+    {
+        if (shapefileDirectory == null) {
+            String path = FLYSUtils.getXPathString(
+                FLYSUtils.XPATH_SHAPEFILE_DIR);
+
+            if (path != null) {
+                shapefileDirectory = new File(path);
+            }
+
+            if (shapefileDirectory == null || !shapefileDirectory.exists()) {
+                throw new FileNotFoundException("No shapefile directory given");
+            }
+        }
+
+        return shapefileDirectory;
+    }
+
+
+    protected File[] getUserDirs()
+    throws    FileNotFoundException
+    {
+        File   baseDir      = getShapefileBaseDir();
+        File[] artifactDirs = baseDir.listFiles();
+
+        // TODO ONLY RETURN DIRECTORIES OF THE SPECIFIED USER
+
+        return artifactDirs;
+    }
+
+
+
+    protected List<LayerInfo> parseLayers(File[] dirs) {
+        List<LayerInfo> layers = new ArrayList<LayerInfo>();
+
+        for (File dir: dirs) {
+            LayerInfo layer = parseUeskLayer(dir);
+            if (layer != null && layer.getData() != null) {
+                logger.debug("   Add WSPLGEN layer.");
+                layers.add(layer);
+            }
+
+            List<LayerInfo> barriers = parseBarriersLayers(dir);
+            int num = barriers != null ? barriers.size() : 0;
+            if (num > 0) {
+                if (barriers.get(0).getData() != null) {
+                    logger.debug("   Add " + num + " BARRIERS layers.");
+                    layers.addAll(barriers);
+                }
+            }
+        }
+
+        return layers;
+    }
+
+
+    protected LayerInfo parseUeskLayer(File dir) {
+        File uesk = new File(dir, WSPLGEN_RESULT_SHAPE);
+
+        if (!uesk.exists() || !uesk.isFile()) {
+            return null;
+        }
+
+        return new LayerInfo(
+            dir.getName() + MS_WSPLGEN_POSTFIX,
+            "POLYGON",
+            dir.getName(),
+            WSPLGEN_RESULT_SHAPE,
+            "I18N_WSPLGEN_RESULT");
+    }
+
+
+    protected List<LayerInfo> parseBarriersLayers(File dir) {
+        List<LayerInfo> barriers = new ArrayList<LayerInfo>(2);
+
+        String group      = dir.getName() + MS_BARRIERS_POSTFIX;
+        String groupTitle = "I18N_BARRIERS_TITLE";
+
+        File lines    = new File(dir, WSPLGEN_LINES_SHAPE);
+        File polygons = new File(dir, WSPLGEN_POLYGONS_SHAPE);
+
+        if (lines.exists() || lines.isFile()) {
+            barriers.add(
+                new LayerInfo(
+                    dir.getName() + MS_LINE_POSTFIX,
+                    "LINE",
+                    dir.getName(),
+                    WSPLGEN_LINES_SHAPE,
+                    "I18N_LINE_SHAPE",
+                    group,
+                    groupTitle));
+        }
+
+        if (polygons.exists() || polygons.isFile()) {
+            barriers.add(
+                new LayerInfo(
+                    dir.getName() + MS_POLYGONS_POSTFIX,
+                    "POLYGON",
+                    dir.getName(),
+                    WSPLGEN_POLYGONS_SHAPE,
+                    "I18N_POLYGON_SHAPE",
+                    group,
+                    groupTitle));
+        }
+
+        return barriers;
+    }
+
+
+    /**
+     * Creates a mapfile with the layer information stored in <i>layers</i>.
+     *
+     * @param layers Layer information.
+     */
+    protected void writeMapfile(List<LayerInfo> layers) {
+        String tmpMapName = "mapfile" + new Date().getTime();
+
+        File mapfile = new File(
+            FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPFILE_PATH));
+
+        File   tmp     = null;
+        Writer writer  = null;
+
+        try {
+            tmp = new File(mapfile.getParent(), tmpMapName);
+            tmp.createNewFile();
+
+            writer = new FileWriter(tmp);
+
+            VelocityContext context = new VelocityContext();
+            context.put("MAPSERVERURL",
+                FLYSUtils.getXPathString(FLYSUtils.XPATH_MAPSERVER_URL));
+            context.put("SHAPEFILEPATH",
+                FLYSUtils.getXPathString(FLYSUtils.XPATH_SHAPEFILE_DIR));
+            context.put("LAYERS", fillLayerTemplates(layers));
+
+            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(mapfile);
+        }
+        catch (FileNotFoundException fnfe) {
+            logger.error(fnfe, fnfe);
+        }
+        catch (IOException ioe) {
+            logger.error(ioe, ioe);
+        }
+        catch (Exception e) {
+            logger.error(e, e);
+        }
+        finally {
+            try {
+                if (writer != null) {
+                    writer.close();
+                }
+
+                if (tmp.exists()) {
+                    tmp.delete();
+                }
+            }
+            catch (IOException ioe) {
+                logger.debug(ioe, ioe);
+            }
+        }
+    }
+
+
+    protected List<String> fillLayerTemplates(List<LayerInfo> layers) {
+        List<String> evaluated = new ArrayList<String>(layers.size());
+
+        for (LayerInfo layer: layers) {
+            StringWriter writer = new StringWriter();
+
+            VelocityContext context = new VelocityContext();
+            context.put("LAYER", layer);
+
+            Template t = getTemplateByName("layer.vm");
+            if (t == null) {
+                logger.warn("No 'layer.vm' template found.");
+                return evaluated;
+            }
+
+            t.merge(context, writer);
+
+            evaluated.add(writer.toString());
+        }
+
+        return evaluated;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org