    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/graphics/sld/ExternalGraphic.java $
    002    /*----------------------------------------------------------------------------
    003     This file is part of deegree, http://deegree.org/
    004     Copyright (C) 2001-2009 by:
    005     Department of Geography, University of Bonn
    006     and
    007     lat/lon GmbH
    008
    009     This library is free software; you can redistribute it and/or modify it under
    010     the terms of the GNU Lesser General Public License as published by the Free
    011     Software Foundation; either version 2.1 of the License, or (at your option)
    012     any later version.
    013     This library is distributed in the hope that it will be useful, but WITHOUT
    014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    016     details.
    017     You should have received a copy of the GNU Lesser General Public License
    018     along with this library; if not, write to the Free Software Foundation, Inc.,
    019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    020
    021     Contact information:
    022
    023     lat/lon GmbH
    024     Aennchenstr. 19, 53177 Bonn
    025     Germany
    026     http://lat-lon.de/
    027
    028     Department of Geography, University of Bonn
    029     Prof. Dr. Klaus Greve
    030     Postfach 1147, 53001 Bonn
    031     Germany
    032     http://www.geographie.uni-bonn.de/deegree/
    033
    034     e-mail: info@deegree.org
    035     ----------------------------------------------------------------------------*/
    036    package org.deegree.graphics.sld;
    037
    038    import static org.deegree.framework.xml.XMLTools.escape;
    039
    040    import java.awt.image.BufferedImage;
    041    import java.io.ByteArrayInputStream;
    042    import java.io.ByteArrayOutputStream;
    043    import java.io.IOException;
    044    import java.io.InputStream;
    045    import java.net.MalformedURLException;
    046    import java.net.URISyntaxException;
    047    import java.net.URL;
    048    import java.util.HashMap;
    049    import java.util.Map;
    050
    051    import javax.media.jai.JAI;
    052    import javax.media.jai.RenderedOp;
    053
    054    import org.apache.batik.transcoder.SVGAbstractTranscoder;
    055    import org.apache.batik.transcoder.Transcoder;
    056    import org.apache.batik.transcoder.TranscoderException;
    057    import org.apache.batik.transcoder.TranscoderInput;
    058    import org.apache.batik.transcoder.TranscoderOutput;
    059    import org.apache.batik.transcoder.image.PNGTranscoder;
    060    import org.deegree.framework.log.ILogger;
    061    import org.deegree.framework.log.LoggerFactory;
    062    import org.deegree.framework.util.StringTools;
    063    import org.deegree.framework.xml.Marshallable;
    064    import org.deegree.model.feature.Feature;
    065    import org.deegree.model.feature.FeatureProperty;
    066
    067    import com.sun.media.jai.codec.MemoryCacheSeekableStream;
    068
    069    /**
    070     * The ExternalGraphic element allows a reference to be made to an external graphic file with a Web URL. The
    071     * OnlineResource sub-element gives the URL and the Format sub-element identifies the expected document MIME type of a
    072     * successful fetch. Knowing the MIME type in advance allows the styler to select the best- supported format from the
    073     * list of URLs with equivalent content.
    074     *
    075     *
    076     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    077     * @author last edited by: $Author: apoth $
    078     *
    079     * @version $Revision: 25372 $, $Date: 2010-07-15 14:11:34 +0200 (Do, 15. Jul 2010) $
    080     */
    081    public class ExternalGraphic implements Marshallable {
    082
    083        private static final ILogger LOG = LoggerFactory.getLogger( ExternalGraphic.class );
    084
    085        private BufferedImage image = null;
    086
    087        private String format = null;
    088
    089        private URL onlineResource = null;
    090
    091        private TranscoderInput input = null;
    092
    093        private ByteArrayOutputStream bos = null;
    094
    095        private TranscoderOutput output = null;
    096
    097        private Transcoder trc = null;
    098
    099        private static Map<String, BufferedImage> cache = null;
    100        static {
    101            if ( cache == null ) {
    102                cache = new HashMap<String, BufferedImage>( 500 );
    103            }
    104        }
    105
    106        /**
    107         * Creates a new ExternalGraphic_Impl object.
    108         *
    109         * @param format
    110         * @param onlineResource
    111         */
    112        ExternalGraphic( String format, URL onlineResource ) {
    113            setFormat( format );
    114            setOnlineResource( onlineResource );
    115        }
    116
    117        /**
    118         * the Format sub-element identifies the expected document MIME type of a successful fetch.
    119         *
    120         * @return Format of the external graphic
    121         *
    122         */
    123        public String getFormat() {
    124            return format;
    125        }
    126
    127        /**
    128         * sets the format (MIME type)
    129         *
    130         * @param format
    131         *            Format of the external graphic
    132         *
    133         */
    134        public void setFormat( String format ) {
    135            this.format = format;
    136        }
    137
    138        /**
    139         * The OnlineResource gives the URL of the external graphic
    140         *
    141         * @return URL of the external graphic
    142         *
    143         */
    144        public URL getOnlineResource() {
    145            return onlineResource;
    146        }
    147
    148        /**
    149         * sets the online resource / URL of the external graphic
    150         *
    151         * @param onlineResource
    152         *            URL of the external graphic
    153         *
    154         */
    155        public void setOnlineResource( URL onlineResource ) {
    156            this.onlineResource = onlineResource;
    157            // TODO
    158            // removing this is just experimental; possibly initializeOnlineResource( Feature feature )
    159            // must be adapted
    160            // String file = onlineResource.getFile();
    161            // int idx = file.indexOf( "$" );
    162            // if ( idx == -1 ) {
    163            // retrieveImage( onlineResource );
    164            // }
    165        }
    166
    167        /**
    168         * @param onlineResource
    169         */
    170        private void retrieveImage( URL onlineResource ) {
    171
    172            try {
    173                String t = onlineResource.toURI().toASCIIString();
    174                if ( t.trim().toLowerCase().endsWith( ".svg" ) ) {
    175                    // initialize the the classes required for svg handling
    176                    bos = new ByteArrayOutputStream( 2000 );
    177                    output = new TranscoderOutput( bos );
    178                    // PNGTranscoder is needed to handle transparent parts
    179                    // of a SVG
    180                    trc = new PNGTranscoder();
    181                    try {
    182                        input = new TranscoderInput( t );
    183                    } catch ( Exception e ) {
    184                        e.printStackTrace();
    185                    }
    186                } else {
    187                    InputStream is = onlineResource.openStream();
    188                    MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is );
    189                    RenderedOp rop = JAI.create( "stream", mcss );
    190                    image = rop.getAsBufferedImage();
    191                    mcss.close();
    192                    is.close();
    193                }
    194            } catch ( Exception e ) {
    195                LOG.logError( e.getMessage(), e );
    196            }
    197        }
    198
    199        /**
    200         * returns the external graphic as an image. this method is not part of the sld specifications but it is added for
    201         * speed up applications
    202         *
    203         * @param targetSizeX
    204         * @param targetSizeY
    205         * @param feature
    206         *
    207         * @return the external graphic as BufferedImage
    208         */
    209        public BufferedImage getAsImage( int targetSizeX, int targetSizeY, Feature feature ) {
    210
    211            if ( ( ( this.input == null ) && ( this.image == null ) ) || feature != null ) {
    212                URL onlineResource = initializeOnlineResource( feature );
    213                retrieveImage( onlineResource );
    214            }
    215
    216            if ( input != null ) {
    217                image = cache.get( targetSizeX + '_' + targetSizeY + '_' + onlineResource.getFile() );
    218                if ( image == null ) {
    219                    if ( targetSizeX <= 0 ) {
    220                        targetSizeX = 1;
    221                    }
    222                    if ( targetSizeY <= 0 ) {
    223                        targetSizeY = 1;
    224                    }
    225
    226                    trc.addTranscodingHint( SVGAbstractTranscoder.KEY_HEIGHT, new Float( targetSizeX ) );
    227                    trc.addTranscodingHint( SVGAbstractTranscoder.KEY_WIDTH, new Float( targetSizeY ) );
    228                    try {
    229                        trc.transcode( input, output );
    230                        try {
    231                            bos.flush();
    232                            bos.close();
    233                        } catch ( IOException e3 ) {
    234                            e3.printStackTrace();
    235                        }
    236                    } catch ( TranscoderException e ) {
    237                        LOG.logError( e.getMessage(), e );
    238                    }
    239                    try {
    240                        ByteArrayInputStream is = new ByteArrayInputStream( bos.toByteArray() );
    241                        MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is );
    242                        RenderedOp rop = JAI.create( "stream", mcss );
    243                        image = rop.getAsBufferedImage();
    244                        cache.put( targetSizeX + '_' + targetSizeY + '_' + onlineResource.getFile(), image );
    245                        mcss.close();
    246                    } catch ( IOException e1 ) {
    247                        LOG.logError( e1.getMessage(), e1 );
    248                    }
    249                }
    250            }
    251
    252            return image;
    253        }
    254
    255        /**
    256         * @param feature
    257         * @return online resource URL
    258         */
    259        private URL initializeOnlineResource( Feature feature ) {
    260
    261            String file = null;
    262            try {
    263                file = this.onlineResource.toURI().toASCIIString();
    264                LOG.logDebug( "external graphic pattern: ", file );
    265            } catch ( URISyntaxException e1 ) {
    266                e1.printStackTrace();
    267            }
    268            String[] tags = StringTools.extractStrings( file, "$", "$" );
    269
    270            if ( tags != null ) {
    271                FeatureProperty[] properties = feature.getProperties();
    272                for ( int i = 0; i < tags.length; i++ ) {
    273                    String tag = tags[i].substring( 1, tags[i].length() - 1 );
    274                    for ( int j = 0; j < properties.length; j++ ) {
    275                        if ( properties[j].getName().getLocalName().equals( tag ) ) {
    276                            String to = properties[j].getValue().toString();
    277                            file = StringTools.replace( file, tags[i], to, true );
    278                        }
    279                    }
    280                }
    281            }
    282            URL onlineResource = null;
    283            try {
    284                onlineResource = new URL( file );
    285                LOG.logDebug( "external graphic URL: ", file );
    286            } catch ( MalformedURLException e ) {
    287                LOG.logError( e.getMessage(), e );
    288            }
    289            return onlineResource;
    290        }
    291
    292        /**
    293         * sets the external graphic as an image.
    294         *
    295         * @param image
    296         *            the external graphic as BufferedImage
    297         */
    298        public void setAsImage( BufferedImage image ) {
    299            this.image = image;
    300        }
    301
    302        /**
    303         * exports the content of the ExternalGraphic as XML formated String
    304         *
    305         * @return xml representation of the ExternalGraphic
    306         */
    307        public String exportAsXML() {
    308
    309            StringBuffer sb = new StringBuffer( 200 );
    310            sb.append( "<ExternalGraphic>" );
    311            sb.append( "<OnlineResource xmlns:xlink='http://www.w3.org/1999/xlink' " );
    312            sb.append( "xlink:type='simple' xlink:href='" );
    313            try {
    314                sb.append( onlineResource.toURI().toASCIIString() + "'/>" );
    315            } catch ( URISyntaxException e ) {
    316                e.printStackTrace();
    317            }
    318            sb.append( "<Format>" ).append( escape( format ) ).append( "</Format>" );
    319            sb.append( "</ExternalGraphic>" );
    320            return sb.toString();
    321        }
    322
    323    }