view gnv-artifacts/src/main/java/de/intevation/gnv/utils/MapfileGenerator.java @ 745:d194939ecbaf

Improvement: Values of Type Geometry which are Points will be prepared as Regions for DB-Query. gnv-artifacts/trunk@785 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Tue, 16 Mar 2010 12:53:37 +0000
parents 452fad121560
children 9a828e5a2390
line wrap: on
line source
package de.intevation.gnv.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 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;

import de.intevation.artifactdatabase.Config;
import de.intevation.artifactdatabase.XMLUtils;
import de.intevation.artifacts.ArtifactNamespaceContext;
import de.intevation.gnv.wms.LayerInfo;


/**
 * @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_TITLE  = "art:title";
    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");
        }
    }
    
    public boolean templateExists(String templateID){
        Template template = getTemplateByName(templateID);
        return template != null;
    }


    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 title = parseLayerAttr(layer, XPATH_LAYER_TITLE);
        if (title != null && !title.equals("")) {
            info.setTitle(title);
        }
        else {
            info.setTitle(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