view src/java/de/intevation/mxd/writer/MapScriptWriter.java @ 49:0fecdcc28b1b

Created one method for each symbol type in the writer.
author Raimund Renkert <rrenkert@intevation.de>
date Wed, 20 Apr 2011 11:56:35 +0200
parents 34a93dad7604
children 691864097eb1
line wrap: on
line source
package de.intevation.mxd.writer;

import org.apache.log4j.Logger;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.xpath.XPathConstants;
import java.awt.Color;

import edu.umn.gis.mapscript.mapObj;
import edu.umn.gis.mapscript.layerObj;
import edu.umn.gis.mapscript.classObj;
import edu.umn.gis.mapscript.styleObj;
import edu.umn.gis.mapscript.colorObj;
import edu.umn.gis.mapscript.symbolObj;
import edu.umn.gis.mapscript.symbolSetObj;
import edu.umn.gis.mapscript.lineObj;
import edu.umn.gis.mapscript.pointObj;

import edu.umn.gis.mapscript.MS_UNITS;
import edu.umn.gis.mapscript.MS_LAYER_TYPE;
import edu.umn.gis.mapscript.MS_SYMBOL_TYPE;

import de.intevation.mxd.utils.XMLUtils;

/**
 * The Mapfile Writer.
 * This Writer uses the MapScript Java API to create Mapfiles from a DOM.
 *
 * @author <a href="mailto:raimund.renkert@intevation.de">Raimund Renkert</a>
 */
public class MapScriptWriter
implements IWriter
{
    /**
     * The Logger.
     */
    private static final Logger logger = Logger.getLogger(MapScriptWriter.class);

    /**
     * Private member.
     */
    private Document root;
    private mapObj map;


    public MapScriptWriter() {
        map = new mapObj("");
    }

    public MapScriptWriter(String path) {
        map = new mapObj(path);
    }

    /**
     * Write the mapfile.
     * @param doc The root document containin the map attributes.
     *
     * @return Currently always true.
     */
    public boolean write(Document doc) {
        logger.debug("write()");
        this.root = doc;

        //Get the filename.
        Element fileNode = (Element)XMLUtils.xpath(
            root,
            "/mxd/file",
            XPathConstants.NODE);
        String filename = fileNode.getAttribute("name");
        if(filename.endsWith(".mxd")) {
            filename = filename.replace(".mxd", ".map");
        }
        //Write the map attributes.
        writeMap();
        //Write the layers.
        writeLayer();
        //Save the map.
        mapObj cloneMap = map.cloneMap();
        cloneMap.save(filename);
        return true;
    }

    /**
     * Create the map object and set the attributes.
     */
    private void writeMap() {
        logger.debug("writeMap()");
        //Get the map.
        Element mapNode = (Element)XMLUtils.xpath(
            root,
            "/mxd/map",
            XPathConstants.NODE);

        //TODO Get the following values from a template.
        map.setShapepath("/home/intevation/mxd-testbed/testdata-frida");
        map.setHeight(700);
        map.setWidth(800);
        map.setProjection("EPSG:4326");

        //Set the name.
        map.setName(mapNode.getAttribute("name"));
        map.setMetaData("wms_title", mapNode.getAttribute("name"));
        //Set the extent.
        map.setExtent(
            Double.parseDouble(mapNode.getAttribute("extent_min_x")),
            Double.parseDouble(mapNode.getAttribute("extent_min_y")),
            Double.parseDouble(mapNode.getAttribute("extent_max_x")),
            Double.parseDouble(mapNode.getAttribute("extent_max_y")));

        //Set the units.
        String units = mapNode.getAttribute("units");
        MS_UNITS msu;
        if(units.equals("feet")) {
            msu = MS_UNITS.MS_FEET;
        }
        else if(units.equals("inches")) {
            msu = MS_UNITS.MS_INCHES;
        }
        else if(units.equals("kilometers")) {
            msu = MS_UNITS.MS_KILOMETERS;
        }
        else if(units.equals("meters")) {
            msu = MS_UNITS.MS_METERS;
        }
        else if(units.equals("miles")) {
            msu = MS_UNITS.MS_MILES;
        }
        else if(units.equals("nauticalmiles")) {
            msu = MS_UNITS.MS_NAUTICALMILES;
        }
        else if(units.equals("points")) {
            msu = MS_UNITS.MS_PIXELS;
        }
        else {
            msu = MS_UNITS.MS_DD;
        }
        map.setUnits(msu);

        //TODO: Find out whats the correct scale value.
        //map.setScaledenom(Double.parseDouble(mapNode.getAttribute("scale")));
    }

    /**
     * Create layer objects and set the attributes.
     */
    private void writeLayer() {
        logger.debug("writeLayer()");
        Element mapNode = (Element)XMLUtils.xpath(
            root,
            "/mxd/map",
            XPathConstants.NODE);
        NodeList list = mapNode.getElementsByTagName("layer");
        for(int i = 0; i < list.getLength(); i++) {
            Element layerElement = (Element)list.item(i);
            layerObj layer = new layerObj(map);

            //The layer name.
            layer.setName(layerElement.getAttribute("name"));

            //The layer status.
            String stat = layerElement.getAttribute("status");
            if (stat.equals("on")) {
                layer.setStatus(1);
            }
            else {
                layer.setStatus(0);
            }

            //The scale.
            double maxScale =
                Double.parseDouble(layerElement.getAttribute("max_scale"));
            double minScale =
                Double.parseDouble(layerElement.getAttribute("min_scale"));
            layer.setMaxscaledenom(maxScale);
            layer.setMinscaledenom(minScale);

            //The layer type.
            String type = layerElement.getAttribute("type");
            if(type.equals("point")) {
                layer.setType(MS_LAYER_TYPE.MS_LAYER_POINT);
            }

            //The layer datasource.
            layer.setData(layerElement.getAttribute("data_source"));

            //Write classes.
            writeClass(layer, layerElement);
        }

    }

    /**
     * Adds the classes to the layer.
     * @param layer        Mapscript layer object.
     * @param layerElement Dom element containing the class attributes.
     */
    private void writeClass(layerObj layer, Element layerElement) {
        //Get all renderer elements (renderer in arcgis equals class in the
        //mapfile.)
        NodeList list = layerElement.getElementsByTagName("renderer");

        //Create all found class objects and write the symbols and styles for
        //each class.
        for(int i = 0; i < list.getLength(); i++) {
            Element classElement = (Element)list.item(i);
            classObj co = new classObj(layer);
            co.setName(classElement.getAttribute("name"));
            if(classElement.hasAttribute("field_count")) {
                int count =
                    Integer.parseInt(classElement.getAttribute("field_count"));
                String exp = "";
                for(int j = 0; j < count; j++) {
                    //TODO Find a way to create Expressions.
                    exp = "([" + classElement.getAttribute("expression_field_" + j);
                    exp += "] " + classElement.getAttribute("expression_operator");
                    exp += " " + classElement.getAttribute("value") + ")";
                }
                co.setExpression(exp);
            }
            //Write symbols and styles.
            writeSymbol(co, classElement);
        }
    }

    /**
     * Adds the symbols and styles to the mapfile.
     * @param co           Mapscript class object.
     * @param classElement Dom element containing the style and symbol
     *                     attributes.
     */
    private void writeSymbol(classObj co, Element classElement) {
        //Get all symbol elements from dom.
        NodeList list = classElement.getElementsByTagName("symbol");

        //Get the symbol set from the map object.
        symbolSetObj symbolSet = map.getSymbolset();

        //
        for(int i = 0; i < list.getLength(); i++){
            Element symbolElement = (Element) list.item(i);
            styleObj style = new styleObj(co);
            style.setAngle(
                Double.parseDouble(symbolElement.getAttribute("angle")));
            String c = symbolElement.getAttribute("color");
            Color col = Color.decode(c);
            colorObj color = new colorObj(
                col.getRed(),
                col.getGreen(),
                col.getBlue(),
                -4);
            style.setColor(color);
            style.setSize(Double.parseDouble(
                symbolElement.getAttribute("size")));
            if(symbolElement.hasAttribute("outline_color")) {
                Color oCol = Color.decode(
                    symbolElement.getAttribute("outline_color"));
                colorObj outlineColor = new colorObj(
                    oCol.getRed(),
                    oCol.getGreen(),
                    oCol.getBlue(),
                    -4);
                style.setOutlinecolor(outlineColor);
                style.setOutlinewidth(Double.parseDouble(
                    symbolElement.getAttribute("outline_size")));
            }
            String name = symbolElement.getAttribute("name");
            style.setSymbolByName(map, name);
            symbolObj sym = symbolSet.getSymbolByName(name);

            String symType = symbolElement.getAttribute("style");
            if(symType.equals("point")) {
                writePointSymbol(sym, symbolElement);
            }
            else if (symType.equals("arrow")) {
                writeArrowSymbol(sym, symbolElement);
            }
            else if (symType.equals("char")) {
                writeCharSymbol(sym, symbolElement);
            }
        }
        saveSymbolSet(symbolSet);
    }


    /**
     * Write point symbols to the map.
     * @param symbol The symbol object.
     * @param symbolElement The DOM object containing the attributes.
     */
    private void writePointSymbol(symbolObj symbol, Element symbolElement) {
        lineObj points = new lineObj();
        points.add(new pointObj(1,1,0));
        symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_ELLIPSE.swigValue());
        symbol.setPoints(points);
        symbol.setFilled(1);
    }


    /**
     * Write arrow symbol to the map.
     * @param symbol The symbol object.
     * @param symbolElement The DOM object containig the attributes.
     */
    private void writeArrowSymbol(symbolObj symbol, Element symbolElement) {
        double len = Double.parseDouble(symbolElement.getAttribute("length"));
        double width = Double.parseDouble(symbolElement.getAttribute("width"));
        double ratio = len/width;
        lineObj points = new lineObj();

        points.add(new pointObj(0, 0, 0));
        points.add(new pointObj((1*ratio), 0.5, 0));
        points.add(new pointObj(0, 1, 0));
        points.add(new pointObj(0, 0, 0));
        symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_VECTOR.swigValue());
        symbol.setPoints(points);
        symbol.setFilled(1);
    }


    /**
     * Write font symbols to the map.
     * @param symbol The symbol object.
     * @param symbolElement The DOM object containing the attributes.
     */
    private void writeCharSymbol(symbolObj symbol, Element symbolElement) {
        symbol.setFont(symbolElement.getAttribute("font"));
        symbol.setType(MS_SYMBOL_TYPE.MS_SYMBOL_TRUETYPE.swigValue());
        symbol.setAntialias(1);
        symbol.setCharacter("#&" + symbolElement.getAttribute("char") + ";");
    }


    /**
     * Save the symbol set.
     * @param symbols The symbol set.
     */
    private void saveSymbolSet(symbolSetObj symbols) {
        Element fileNode = (Element)XMLUtils.xpath(
            root,
            "/mxd/file",
            XPathConstants.NODE);
        String filename = fileNode.getAttribute("name");
        String path = "";
        if(filename.contains("/")) {
            path = filename.substring(0, filename.lastIndexOf("/"));
        }
        else if(filename.contains("\\")) {
            path = filename.substring(0, filename.lastIndexOf("\\"));
        }
        symbols.save(path + "/symbols.sym");
    }
}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)