Mercurial > dive4elements > river
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 :