Package org.geotools.renderer.markwkt

Source Code of org.geotools.renderer.markwkt.WKTMarkFactory

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
*
*    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;
*    version 2.1 of the License.
*
*    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.
*/
package org.geotools.renderer.markwkt;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.factory.CommonFactoryFinder;
import org.geotools.geometry.jts.LiteShape;
import org.geotools.geometry.jts.WKTReader2;
import org.geotools.renderer.style.MarkFactory;
import org.geotools.util.SoftValueHashMap;
import org.opengis.feature.Feature;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.expression.Expression;

/**
* Factory to produce marks based on WKT representation of symbols. WKT geometries may be defined
* directly in the SLD (prefixing it with @see {@value #WKT_PREFIX}, or in a WKT library stored in a
* properties file (prefixing it with @see {@link #WKTLIB_PREFIX}).
*
* The symbols stored in properties files are cached in soft references for better
* performance. The root directory for properties files can be set using the {@link setRoot}
* method.
*
* @author Luca Morandini lmorandini@ieee.org
* @author Simone Giannecchini, GeoSolutions
*
* @source $URL$
* @version $Id$
*
*/
public class WKTMarkFactory implements MarkFactory {

    /** The logger for the rendering module. */
    protected static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(WKTMarkFactory.class);

    public static final String WKT_PREFIX = "wkt://";

    public static final String WKTLIB_PREFIX = "wktlib://";

    public static final String WKT_SEPARATOR = "#";

    protected static URL ROOT_DIRECTORY = null;

    // Cache used to store libraries of WKT geometries
    protected final static SoftValueHashMap<String, Map<String, String>> CACHE = new SoftValueHashMap<String, Map<String, String>>();

    /*
     * Clears cache. While the cache uses {@link
     * http://download.oracle.com/javase/1.5.0/docs/api/java/lang/ref/SoftReference.html soft
     * references}, a clearing of the cache may be useful when the WKT libraries (stored in
     * properties file) are updated.
     */
    public void clearCache() {
        CACHE.clear();
    }

    /**
     * Sets the root dir for WKT libraries
     *
     * @param root Directory from which the search for WKT libraries starts
     */
    public void setRoot(URL root) {
        ROOT_DIRECTORY = root;
    }

    /**
     * Returns a WKT geometry from cache given its URL
     *
     * @param urlLib URL of the WKT library
     *
     * @param wktName name of the WKT shape
     */
    protected String getFromCache(String urlLib, String wktName) {
        Map<String, String> library = CACHE.get(urlLib);
        if (library != null) {
            return (String) library.get(wktName);
        }
        return null;
    }

    /**
     * Adds the shapes contained in a WKT library to the cache; if the url already exists in the
     * cache, the shapes are not added
     *
     * @param urlLib URL of the WKT library as a properties file URL
     */
    protected void addToCache(String urlLib) {
        Map<String, String> library = CACHE.get(urlLib);
        if (library == null) {
            library = new HashMap<String, String>();
            Properties propLib = null;
            try {
                propLib = this.loadLibrary(urlLib);
            } catch (IOException e) {
                LOGGER.log(Level.FINER, e.getMessage(), e);
            }
            for (Enumeration<String> e = (Enumeration<String>) propLib.propertyNames(); e
                    .hasMoreElements();) {
                String shpName = (String) (e.nextElement());
                library.put(shpName, (String) (propLib.get(shpName)));
            }
            CACHE.put(urlLib, library);
        }
    }

    /**
     * Returns a WKT shaoe given that its URL specifies a WKT geometry or contains a reference to a
     * WKT geometry specfied in a properties file
     *
     * @see org.geotools.renderer.style.MarkFactory#getShape(java.awt.Graphics2D,
     * org.opengis.filter.expression.Expression, org.opengis.feature.Feature)
     */
    public Shape getShape(Graphics2D graphics, Expression symbolUrl, Feature feature)
            throws Exception {

        // cannot handle a null url
        if (symbolUrl == null) {
            return null;
        }

        // If it does not start with either prefix, it cannot create symbols
        String wellKnown = symbolUrl.evaluate(feature, String.class);
        if (!wellKnown.startsWith(WKT_PREFIX) && !wellKnown.startsWith(WKTLIB_PREFIX)) {
            return null;
        }

        // See if it is a simple WKT, so that i can extract the WKT symbols
        // directly
        String wkt = null;
        if (wellKnown.startsWith(WKT_PREFIX)) {
            wkt = wellKnown.substring(WKT_PREFIX.length());
        }

        // See if it is a WKT library reference
        if (wellKnown.startsWith(WKTLIB_PREFIX)) {
            String[] urlComponents = wellKnown.substring(WKTLIB_PREFIX.length()).split(WKT_SEPARATOR);
            synchronized (this) {
                wkt = this.getFromCache(urlComponents[0], urlComponents[1]);
                if (wkt == null) {
                    this.addToCache(urlComponents[0]);
                    wkt = this.getFromCache(urlComponents[0], urlComponents[1]);
                }
            }

        }

        if (wkt == null) {
            LOGGER.info("This is not recognised a WKT symbol: " + wellKnown);
        }

        // Creates and return the symbol
        WKTReader2 reader = new WKTReader2();
        LiteShape shape = new LiteShape(reader.read(wkt), null, false);
        LOGGER.info("Created symbol from WKT " + wkt);
        return shape;
    }

    /**
     * Loads a WKT symbol library as a properties file
     *
     * @param libFile Location of the properties file (it could be a CQL expression)
     */
    protected Properties loadLibrary(String libFile) throws IOException {

        final Properties properties = new Properties();
        URL libUrl = null;
        try {
            libUrl = new URL(ROOT_DIRECTORY.toString() + "/" + libFile);
        } catch (MalformedURLException e) {
            LOGGER.log(Level.WARNING, "Could not parse WKT library URL: " + ROOT_DIRECTORY + "/" + libFile, e);
        }

        InputStream in = null;
        try {
            in = libUrl.openStream();
            properties.load(in);
        } catch (Exception e) {
            LOGGER.log(Level.WARNING, e.getMessage(), e);
        } finally {
            if (in != null) {
                in.close();
            }
        }

        return properties;
    }
}
TOP

Related Classes of org.geotools.renderer.markwkt.WKTMarkFactory

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.