org.kalypso.mapserver.utils.MapFileUtilities.java Source code

Java tutorial

Introduction

Here is the source code for org.kalypso.mapserver.utils.MapFileUtilities.java

Source

/*----------------    FILE HEADER KALYPSO ------------------------------------------
 *
 *  This file is part of kalypso.
 *  Copyright (C) 2004 by:
 *
 *  Technical University Hamburg-Harburg (TUHH)
 *  Institute of River and coastal engineering
 *  Denickestrae 22
 *  21073 Hamburg, Germany
 *  http://www.tuhh.de/wb
 *
 *  and
 *
 *  Bjoernsen Consulting Engineers (BCE)
 *  Maria Trost 3
 *  56070 Koblenz, Germany
 *  http://www.bjoernsen.de
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  Contact:
 *
 *  E-Mail:
 *  belger@bjoernsen.de
 *  schlienger@bjoernsen.de
 *  v.doemming@tuhh.de
 *
 *  ---------------------------------------------------------------------------*/
package org.kalypso.mapserver.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.List;
import java.util.Locale;

import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.graphics.RGB;
import org.geotools.referencing.CRS;
import org.kalypso.commons.KalypsoCommonsPlugin;
import org.kalypso.commons.bind.JaxbUtilities;
import org.kalypso.mapserver.utils.exceptions.MapServerException;
import org.kalypsodeegree.model.geometry.GM_Curve;
import org.kalypsodeegree.model.geometry.GM_Envelope;
import org.kalypsodeegree.model.geometry.GM_MultiCurve;
import org.kalypsodeegree.model.geometry.GM_MultiPoint;
import org.kalypsodeegree.model.geometry.GM_Point;
import org.kalypsodeegree.model.geometry.GM_Polygon;
import org.kalypsodeegree_impl.tools.GMLConstants;
import org.mapserver.mapserver.BooleanEnum;
import org.mapserver.mapserver.Class;
import org.mapserver.mapserver.ExpressionType;
import org.mapserver.mapserver.ItemType;
import org.mapserver.mapserver.ItemType.Item;
import org.mapserver.mapserver.Label;
import org.mapserver.mapserver.Layer;
import org.mapserver.mapserver.Legend;
import org.mapserver.mapserver.Map;
import org.mapserver.mapserver.ObjectFactory;
import org.mapserver.mapserver.OutputFormat;
import org.mapserver.mapserver.PositionEnum;
import org.mapserver.mapserver.RgbColorType;
import org.mapserver.mapserver.SizeType;
import org.mapserver.mapserver.StateEnum;
import org.mapserver.mapserver.Style;
import org.mapserver.mapserver.Web;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * This class provides utility functions for dealing with map files.
 *
 * @author Holger Albert
 */
public class MapFileUtilities {
    private static final URL XSL_URL = MapFileUtilities.class.getResource("/etc/mapfile/mapfile.xsl"); //$NON-NLS-1$

    /**
     * The object factory.
     */
    public static final ObjectFactory OF = new ObjectFactory();

    /**
     * The JAXB context.
     */
    private static final JAXBContext JC = JaxbUtilities.createQuiet(ObjectFactory.class);

    /**
     * The constructor.
     */
    private MapFileUtilities() {
    }

    /**
     * This function loads a map file from XML.
     *
     * @param inputStream
     *          The input stream.
     * @return The contents of the map file.
     */
    public static Map loadFromXML(final InputStream inputStream)
            throws JAXBException, SAXException, ParserConfigurationException, IOException {
        /* Create the unmarshaller. */
        final Unmarshaller unmarshaller = JC.createUnmarshaller();

        /* Get the sax parser factory. */
        final SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setNamespaceAware(true);
        spf.setXIncludeAware(true);

        /* Get the xml reader. */
        final XMLReader xr = spf.newSAXParser().getXMLReader();
        xr.setContentHandler(unmarshaller.getUnmarshallerHandler());
        xr.parse(new InputSource(inputStream));

        return (Map) unmarshaller.getUnmarshallerHandler().getResult();
    }

    /**
     * This function saves a map file as XML.
     *
     * @param map
     *          The contents of the map file.
     * @param outputStream
     *          The output stream.
     * @param encoding
     *          The encoding.
     */
    public static void saveAsXML(final Map map, final OutputStream outputStream, final String encoding)
            throws JAXBException {
        /* Create the marshaller. */
        final Marshaller marshaller = JC.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
        marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MapFileNamespacePrefixMapper()); //$NON-NLS-1$
        marshaller.marshal(map, outputStream);
    }

    /**
     * This function saves a map file in ASCII.
     *
     * @param map
     *          The contents of the map file.
     * @param outputStream
     *          The output stream.
     * @param encoding
     *          The encoding.
     */
    public static void saveInASCII(final Map map, final OutputStream outputStream, final String encoding)
            throws ParserConfigurationException, JAXBException, SAXException, IOException, TransformerException {

        /* the input stream. */
        InputStream inputStream = null;

        try {
            /* Create the document builder factory. */
            final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);

            /* Create the document builder. */
            final DocumentBuilder builder = factory.newDocumentBuilder();

            /* Create a XML document. */
            final Document xmlDOM = builder.newDocument();

            /* Create the marshaller. */
            final Marshaller marshaller = JC.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
            marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MapFileNamespacePrefixMapper()); //$NON-NLS-1$

            /* Marshal the contents of the map file into the XML document. */
            marshaller.marshal(map, xmlDOM);

            /* Load the XLS document. */
            inputStream = XSL_URL.openStream();
            final Document xslDOM = builder.parse(inputStream);

            /* Create the transformer factory. */
            final TransformerFactory transformerFactory = KalypsoCommonsPlugin.getDefault().getTransformerFactory();

            /* Create the transformer using the XSL document. */
            final Transformer transformer = transformerFactory.newTransformer(new DOMSource(xslDOM));

            /* Transform the XML document document and write it to the output stream. */
            transformer.transform(new DOMSource(xmlDOM), new StreamResult(outputStream));
        } finally {
            /* Close the input stream. */
            IOUtils.closeQuietly(inputStream);
        }
    }

    /**
     * This function creates the contents of the map file without any layers.
     *
     * @param wmsURL
     * @param mapFile
     * @param width
     * @param height
     * @param mapName
     * @param envelope
     * @param sourceCRS
     * @param otherCRSs
     * @return The contents of the map file.
     */
    public static Map createMap(final String wmsURL, final File mapFile, final int width, final int height,
            final String mapName, final GM_Envelope envelope, final String sourceCRS, final String[] otherCRSs)
            throws NoSuchAuthorityCodeException, FactoryException {
        /* Create the root element of the XML map file. */
        final Map map = OF.createMap();
        map.setName(mapName);
        map.setStatus(StateEnum.ON);

        /* Create the size element. */
        if (width > 0 && height > 0) {
            final SizeType size = OF.createSizeType();
            size.setX(BigInteger.valueOf(width));
            size.setY(BigInteger.valueOf(height));
            map.setSize(size);
        }

        /* Fill the extent element. */
        map.getExtent().add(envelope.getMinX());
        map.getExtent().add(envelope.getMinY());
        map.getExtent().add(envelope.getMaxX());
        map.getExtent().add(envelope.getMaxY());

        /* Detrermine the units. */
        final CoordinateReferenceSystem referenceSystem = CRS.decode(sourceCRS);
        final CoordinateSystem coordinateSystem = referenceSystem.getCoordinateSystem();
        final CoordinateSystemAxis axis = coordinateSystem.getAxis(0);
        final Unit<?> unit = axis.getUnit();
        String units = null;
        if (SI.KILOMETER.equals(unit))
            units = "kilometers"; //$NON-NLS-1$
        else if (SI.METER.equals(unit))
            units = "meters"; //$NON-NLS-1$
        else if (NonSI.DEGREE_ANGLE.equals(unit))
            units = "dd"; //$NON-NLS-1$

        if (units != null && units.length() > 0)
            map.setUnits(units);

        /* Create the rgb color element. */
        // RgbColorType rgbColor = OF.createRgbColorType();
        // rgbColor.setRed( 255 );
        // rgbColor.setGreen( 255 );
        // rgbColor.setBlue( 255 );
        // map.setImageColor( rgbColor );

        /* Create the output format element. */
        final OutputFormat outputFormat = OF.createOutputFormat();
        outputFormat.setName("PNG"); //$NON-NLS-1$
        outputFormat.setDriver("AGG/PNG"); //$NON-NLS-1$
        outputFormat.setMimeType("image/png"); //$NON-NLS-1$
        outputFormat.setImageMode("RGBA"); //$NON-NLS-1$
        outputFormat.setExtension("png"); //$NON-NLS-1$
        map.getOutputFormat().add(outputFormat);

        /* Fill the projection element. */
        map.getProjection().add("init=" + sourceCRS); //$NON-NLS-1$

        /* Create the item element. */
        final String resource = String.format("%s?map=%s&", wmsURL, mapFile.getAbsolutePath().replace("\\", "/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        final ItemType item = OF.createItemType();
        item.getItem().add(createItem("wms_title", mapName)); //$NON-NLS-1$
        item.getItem().add(createItem("wms_onlineresource", resource)); //$NON-NLS-1$
        item.getItem()
                .add(createItem("wms_srs", String.format("%s %s", sourceCRS, StringUtils.join(otherCRSs, " ")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        item.getItem().add(createItem("wms_feature_info_mime_type", "text/html")); //$NON-NLS-1$ //$NON-NLS-2$

        /* Create the map element. */
        final Web web = OF.createWeb();
        web.setMetadata(item);

        /* Fill the web element. */
        map.getWeb().add(web);

        /* Create a label element. */
        final Label label = OF.createLabel();
        label.setAntialias(BooleanEnum.TRUE);
        label.setType("bitmap"); //$NON-NLS-1$
        label.setSize("medium"); //$NON-NLS-1$
        label.setPosition("AUTO"); //$NON-NLS-1$
        label.setPartials(BooleanEnum.FALSE);

        /* Create the outline color element. */
        final RgbColorType outlineColor = OF.createRgbColorType();
        outlineColor.setRed(0);
        outlineColor.setGreen(0);
        outlineColor.setBlue(0);

        /* Create the legend element. */
        final Legend legend = OF.createLegend();
        legend.setStatus("on"); //$NON-NLS-1$
        legend.setPosition(PositionEnum.LR);
        legend.setLabel(label);
        legend.setOutlineColor(outlineColor);
        map.setLegend(legend);

        return map;
    }

    /**
     * This function creates the contents of the item.
     *
     * @param name
     * @param value
     * @return The contents of the item.
     */
    public static Item createItem(final String name, final String value) {
        final Item item = OF.createItemTypeItem();
        item.setName(name);
        item.setValue(value);

        return item;
    }

    /**
     * This function creates the contents of the layer.
     *
     * @param wmsURL
     * @param mapFile
     * @param layerName
     *          Used for naming the layer and the wms layer.
     * @paramd data
     * @param geoemtryType
     * @param envelope
     * @param sourceCRS
     * @param otherCRSs
     * @return The contents of the layer.
     */
    public static Layer createLayerForShape(final String wmsURL, final File mapFile, final String layerName,
            final String data, final QName geoemtryType, final GM_Envelope envelope, final String sourceCRS,
            final String[] otherCRSs) throws MapServerException {
        String shapeType = "POLYGON"; //$NON-NLS-1$
        if (GM_Point.POINT_ELEMENT.equals(geoemtryType) || GM_MultiPoint.MULTI_POINT_ELEMENT.equals(geoemtryType))
            shapeType = "POINT"; //$NON-NLS-1$
        else if (GM_Curve.CURVE_ELEMENT.equals(geoemtryType)
                || GM_MultiCurve.MULTI_CURVE_ELEMENT.equals(geoemtryType))
            shapeType = "LINE"; //$NON-NLS-1$
        else if (GM_Polygon.POLYGON_ELEMENT.equals(geoemtryType)
                || GMLConstants.QN_MULTI_POLYGON.equals(geoemtryType))
            shapeType = "POLYGON"; //$NON-NLS-1$

        /* Create the layer element. */
        final Layer layer = OF.createLayer();
        layer.setName(layerName);
        layer.setType(shapeType);
        layer.setStatus("ON"); //$NON-NLS-1$
        layer.setData(data);
        layer.setTemplate("getfeatureinfo.html"); //$NON-NLS-1$

        /* Fill the projection element. */
        layer.getProjection().add("init=" + sourceCRS); //$NON-NLS-1$

        /* Create the item element. */
        final String resource = String.format("%s?map=%s&", wmsURL, mapFile.getAbsolutePath().replace("\\", "/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        final ItemType item = OF.createItemType();
        item.getItem().add(createItem("wms_title", layerName)); //$NON-NLS-1$
        item.getItem().add(createItem("wms_onlineresource", resource)); //$NON-NLS-1$
        item.getItem()
                .add(createItem("wms_srs", String.format("%s %s", sourceCRS, StringUtils.join(otherCRSs, " ")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        item.getItem().add(createItem("wms_extent", String.format(Locale.PRC, "%f %f %f %f", envelope.getMinX(), //$NON-NLS-1$//$NON-NLS-2$
                envelope.getMinY(), envelope.getMaxX(), envelope.getMaxY())));
        layer.setMetadata(item);

        /* Create the class element. */
        final Class clazz = createClass("Standard", null, null, new RGB(0, 0, 0)); //$NON-NLS-1$

        /* Fill the class element. */
        layer.getClazz().add(clazz);

        return layer;
    }

    /**
     * This function creates the contents of the layer without any classes.
     *
     * @param wmsURL
     * @param mapFile
     * @param layerName
     *          Used for naming the layer and the wms layer.
     * @param opacity
     * @param data
     * @param bigMin
     * @param bigMax
     * @param envelope
     * @param sourceCRS
     * @param otherCRSs
     * @return The contents of the layer.
     */
    public static Layer createLayerForRaster(final String wmsURL, final File mapFile, final String layerName,
            final String opacity, final String data, final BigDecimal bigMin, final BigDecimal bigMax,
            final GM_Envelope envelope, final String sourceCRS, final String[] otherCRSs) {
        /* Create the layer element. */
        final Layer layer = OF.createLayer();
        layer.setName(layerName);
        layer.setType("RASTER"); //$NON-NLS-1$
        layer.setStatus("ON"); //$NON-NLS-1$
        layer.setOpacity(opacity);
        layer.setData(data);
        layer.setTemplate("getfeatureinfo.html"); //$NON-NLS-1$

        /* Fill the processing element. */
        double min = -Double.MAX_VALUE;
        if (bigMin != null)
            min = bigMin.doubleValue();

        double max = Double.MAX_VALUE;
        if (bigMax != null)
            max = bigMax.doubleValue();

        double buckets = Math.floor((max - min) / 0.05);
        if (buckets < 2.0)
            buckets = 2.0;

        final List<String> processing = layer.getProcessing();
        processing.add(String.format(Locale.PRC, "SCALE=%.2f %.2f", min, max)); //$NON-NLS-1$
        processing.add(String.format(Locale.PRC, "SCALE_BUCKETS=%d", (int) buckets)); //$NON-NLS-1$
        processing.add("RESAMPLE=BILINEAR"); //$NON-NLS-1$

        /* Fill the projection element. */
        layer.getProjection().add("init=" + sourceCRS); //$NON-NLS-1$

        /* Create the item element. */
        final String resource = String.format("%s?map=%s&", wmsURL, mapFile.getAbsolutePath().replace("\\", "/")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        final ItemType item = OF.createItemType();
        item.getItem().add(createItem("wms_title", layerName)); //$NON-NLS-1$
        item.getItem().add(createItem("wms_onlineresource", resource)); //$NON-NLS-1$
        item.getItem()
                .add(createItem("wms_srs", String.format("%s %s", sourceCRS, StringUtils.join(otherCRSs, " ")))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
        item.getItem().add(createItem("wms_extent", String.format(Locale.PRC, "%f %f %f %f", envelope.getMinX(), //$NON-NLS-1$//$NON-NLS-2$
                envelope.getMinY(), envelope.getMaxX(), envelope.getMaxY())));
        layer.setMetadata(item);

        return layer;
    }

    /**
     * This function creates the content of the class.
     *
     * @param label
     * @param expressionValue
     *          Used to evaluate specific criteria. May be null.
     * @param expressionType
     *          Must be set, if a expressionValue is set. Otherwise it may be null.
     * @param rgb
     *          The rgb colors.
     * @return The contents of the class.
     */
    public static Class createClass(final String label, final String expressionValue, final String expressionType,
            final RGB rgb) throws MapServerException {
        /* Create the class element. */
        final Class clazz = OF.createClass();
        clazz.setName(label);

        /* Create the expression element. */
        if (expressionValue != null && expressionValue.length() > 0) {
            if (expressionType == null || expressionType.length() == 0)
                throw new MapServerException("Expression value without expression type set..."); //$NON-NLS-1$

            final ExpressionType expression = OF.createExpressionType();
            expression.setValue(expressionValue);
            expression.setType(expressionType);
            clazz.setExpression(expression);
        }

        /* Create the rgb color element. */
        final RgbColorType rgbColor = OF.createRgbColorType();
        rgbColor.setRed(rgb.red);
        rgbColor.setGreen(rgb.green);
        rgbColor.setBlue(rgb.blue);

        /* Create the style element. */
        final Style style = OF.createStyle();
        style.setColor(rgbColor);
        clazz.getStyle().add(style);

        return clazz;
    }
}