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