Package org.geoserver.catalog

Source Code of org.geoserver.catalog.Styles

/* Copyright (c) 2001 - 2010 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.geoserver.catalog;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.transform.TransformerException;

import org.geoserver.ows.util.RequestUtils;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.sld.v1_1.SLDConfiguration;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.NamedStyle;
import org.geotools.styling.SLDParser;
import org.geotools.styling.SLDTransformer;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.StyledLayerDescriptor;
import org.geotools.styling.UserLayer;
import org.geotools.util.Version;
import org.geotools.util.logging.Logging;
import org.geotools.xml.Parser;
import org.vfny.geoserver.util.SLDValidator;
import org.xml.sax.InputSource;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

/**
* Provides methods to parse/encode style documents.
* <p>
* Currently SLD versions 1.0, and 1.1 are supported.
* </p>
* @author Justin Deoliveira, OpenGeo
*/
public class Styles {

    /** logger */
    static Logger LOGGER = Logging.getLogger("org.geoserver.wms");
   
    /**
     * number of bytes to "look ahead" when pre parsing xml document.
     * TODO: make this configurable, and possibley link it to the same value
     * used by the ows dispatcher.
     */
    static int XML_LOOKAHEAD = 8192;
   
    static StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);

    /**
     * Parses a style document into a StyleLayerDescriptor determining style type/version
     * from the content itself.
     * 
     * @param input a File, Reader, or InputStream object.
     *
     * @return The parsed style.
     *
     * @throws IOException Any parsing errors that occur.
     * @throws IllegalArgumentException If the type of the style can not be determined.
     */
    public static StyledLayerDescriptor parse(Object input) throws IOException {
        Object[] obj = findVersion(input);
        return parse(obj[1], (Version)obj[0]);
    }

    /**
     * Parses a style document into a StyledLayerDescriptor object explicitly specifying version.
     * <p>
     * </p>
     * @param input a File, Reader, or InputStream object.
     * @param version The SLD version
     *
     * @return The parsed StyleLayerDescriptor.
     *
     * @throws IOException Any parsing errors that occur.
     * @throws IllegalArgumentException If the specified version is not supported.
     */
    public static StyledLayerDescriptor parse(Object input, Version version) throws IOException {
        return Handler.lookup(version).parse(input);
    }
   
    /**
     * Encodes a StyledLayerDescriptor object to a style document.
     * <p>
     * </p>
     * @param sld The StyledLayerDescriptor object
     * @param version The SLD version
     * @param format Specifies if the serialized SLD should be formatted or not.
     * @param output The output stream to serialize to.
     *
     * @throws IOException Any encoding errors that occur.
     * @throws IllegalArgumentException If the specified version is not supported.
     */
    public static void encode(StyledLayerDescriptor sld, Version version, boolean format,
            OutputStream output) throws IOException {
       
        Handler.lookup(version).encode(sld, format, output);
    }
   
    /**
     * Performs schema validation on an style document determining style type from the content
     * itself.
     *
     * @param input A File, Reader, or InputStream object.
     *
     * @return A list of validation exceptions, empty if no errors are present and the document is
     *   valid.
     *
     * @throws IOException Any parsing errors that occur.
     * @throws IllegalArgumentException If the specified version is not supported.
     */
    public static List<Exception> validate(Object input) throws IOException {
        Object[] obj = findVersion(input);
        return validate(obj[1], (Version)obj[0]);
    }

    /**
     * Performs schema validation on an style document, specifying the version.
     *
     * @param input A File, Reader, or InputStream object.
     * @param version The SLD version
     *
     * @return A list of validation exceptions, empty if no errors are present and the document is
     *   valid.
     *
     * @throws IOException Any parsing errors that occur.
     * @throws IllegalArgumentException If the specified version is not supported.
     */
    public static List<Exception> validate(Object input, Version version) throws IOException {
        return Handler.lookup(version).validate(input);
    }

    /**
     * Convenience method to pull a UserSyle from a StyledLayerDescriptor.
     * <p>
     * This method will return the first UserStyle it encounters in the StyledLayerDescriptor tree.
     * </p>
     * @param sld The StyledLayerDescriptor object.
     *
     * @return The UserStyle, or <code>null</code> if no such style could be found.
     */
    public static Style style(StyledLayerDescriptor sld) {
        for (int i = 0; i < sld.getStyledLayers().length; i++) {
            Style[] styles = null;
           
            if (sld.getStyledLayers()[i] instanceof NamedLayer) {
                NamedLayer layer = (NamedLayer) sld.getStyledLayers()[i];
                styles = layer.getStyles();
            }
            else if(sld.getStyledLayers()[i] instanceof UserLayer) {
                UserLayer layer = (UserLayer) sld.getStyledLayers()[i];
                styles = layer.getUserStyles();
            }
           
            if (styles != null) {
                for (int j = 0; j < styles.length; i++) {
                    if (!(styles[j] instanceof NamedStyle)) {
                        return styles[j];
                    }
                }
            }
           
        }

        return null;
    }

    /**
     * Convenience method to wrap a UserStyle in a StyledLayerDescriptor object.
     * <p>
     * This method wraps the UserStyle in a NamedLayer, and wraps the result in a StyledLayerDescriptor.
     * </p>
     * @param style The UserStyle.
     *
     * @return The StyledLayerDescriptor.
     */
    public static StyledLayerDescriptor sld(Style style) {
        StyledLayerDescriptor sld = styleFactory.createStyledLayerDescriptor();
       
        NamedLayer layer = styleFactory.createNamedLayer();
        layer.setName(style.getName());
        sld.addStyledLayer(layer);
       
        layer.addStyle(style);
       
        return sld;
    }

    /**
     * Helper method for finding which style handler/version to use from the actual content.
     */
    static Object[] findVersion(Object input) throws IOException {
        //need to determine version of sld from actual content
        BufferedReader reader = null;
       
        if (input instanceof InputStream) {
            reader = RequestUtils.getBufferedXMLReader((InputStream) input, 8192);
        }
        else {
            reader = RequestUtils.getBufferedXMLReader(toReader(input), 8192);
        }
           
        if (!reader.ready()) {
            return null;
        }

        String version;
        try {
            //create stream parser
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(true);
            factory.setValidating(false);

            //parse root element
            XmlPullParser parser = factory.newPullParser();
            parser.setInput(reader);
            parser.nextTag();

            version = null;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                if ("version".equals(parser.getAttributeName(i))) {
                    version = parser.getAttributeValue(i);
                }
            }

            parser.setInput(null);
        }
        catch (XmlPullParserException e) {
            throw (IOException) new IOException("Error parsing content").initCause(e);
        }

        //reset input stream
        reader.reset();
       
        if (version == null) {
            LOGGER.warning("Could not determine SLD version from content. Assuming 1.0.0");
            version = "1.0.0";
        }
       
        return new Object[]{new Version(version), reader};
    }
   
    static Reader toReader(Object input) throws IOException {
        if (input instanceof Reader) {
            return (Reader) input;
        }
       
        if (input instanceof InputStream) {
            return new InputStreamReader((InputStream)input);
        }
       
        if (input instanceof File) {
            return new FileReader((File)input);
        }
       
        throw new IllegalArgumentException("Unable to turn " + input + " into reader");
    }
   
    public static enum Handler {
        SLD_10("1.0.0") {
           
            @Override
            public StyledLayerDescriptor parse(Object input) throws IOException {
                SLDParser p = parser(input);
                StyledLayerDescriptor sld = p.parseSLD();
                if (sld.getStyledLayers().length == 0) {
                    //most likely a style that is not a valid sld, try to actually parse out a
                    // style and then wrap it in an sld
                    Style[] style = p.readDOM();
                    if (style.length > 0) {
                        NamedLayer l = styleFactory.createNamedLayer();
                        l.addStyle(style[0]);
                        sld.addStyledLayer(l);
                    }
                }
               
                return sld;
            }
           
            @Override
            protected List<Exception> validate(Object input) throws IOException {
                return new SLDValidator().validateSLD(new InputSource(toReader(input)), null);
            }
           
            @Override
            public void encode(StyledLayerDescriptor sld, boolean format, OutputStream output) throws IOException {
                SLDTransformer tx = new SLDTransformer();
                if (format) {
                    tx.setIndentation(2);
                }
                try {
                    tx.transform( sld, output );
                }
                catch (TransformerException e) {
                    throw (IOException) new IOException("Error writing style").initCause(e);
                }
            }
           
           
            SLDParser parser(Object input) throws IOException {
                if (input instanceof File) {
                    return new SLDParser(styleFactory, (File) input);
                }
                else {
                    return new SLDParser(styleFactory, toReader(input));
                }
            }
        },
       
        SLD_11("1.1.0") {
           
            @Override
            public StyledLayerDescriptor parse(Object input) throws IOException {
                SLDConfiguration sld = new SLDConfiguration();
                try {
                    return (StyledLayerDescriptor) new Parser(sld).parse(toReader(input));
                }
                catch(Exception e) {
                    if (e instanceof IOException) throw (IOException) e;
                    throw (IOException) new IOException().initCause(e);
                }
            }
           
            @Override
            protected List<Exception> validate(Object input) throws IOException {
                SLDConfiguration sld = new SLDConfiguration();
                Parser p = new Parser(sld);
                p.setValidating(true);
               
                try {
                    p.parse(toReader(input));
                    return p.getValidationErrors();
                }
                catch(Exception e) {
                    return Collections.singletonList(e);
                }
            }

            @Override
            public void encode(StyledLayerDescriptor sld, boolean format, OutputStream output) throws IOException {
                // TODO Auto-generated method stub
           
        };
       
        private Version version;
       
        private Handler(String version) {
            this.version = new org.geotools.util.Version(version);
        }
       
        public Version getVersion() {
            return version;
        }

        protected abstract StyledLayerDescriptor parse(Object input) throws IOException;
       
        protected abstract void encode(StyledLayerDescriptor sld, boolean format, OutputStream output)
            throws IOException;
       
        protected abstract List<Exception> validate(Object input) throws IOException;
       
        public static Handler lookup(Version version) {
            for (Handler h : values()) {
                if (h.getVersion().equals(version)) {
                    return h;
                }
            }
            throw new IllegalArgumentException("No support for SLD " + version);
        }
    };
}
TOP

Related Classes of org.geoserver.catalog.Styles

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.