001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/graphics/sld/ExternalGraphic.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 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 static org.deegree.framework.xml.XMLTools.escape;
047    
048    import java.awt.image.BufferedImage;
049    import java.io.ByteArrayInputStream;
050    import java.io.ByteArrayOutputStream;
051    import java.io.IOException;
052    import java.io.InputStream;
053    import java.net.MalformedURLException;
054    import java.net.URL;
055    
056    import javax.media.jai.JAI;
057    import javax.media.jai.RenderedOp;
058    
059    import org.apache.batik.transcoder.Transcoder;
060    import org.apache.batik.transcoder.TranscoderException;
061    import org.apache.batik.transcoder.TranscoderInput;
062    import org.apache.batik.transcoder.TranscoderOutput;
063    import org.apache.batik.transcoder.image.PNGTranscoder;
064    import org.deegree.framework.util.NetWorker;
065    import org.deegree.framework.util.StringTools;
066    import org.deegree.framework.xml.Marshallable;
067    import org.deegree.model.feature.Feature;
068    import org.deegree.model.feature.FeatureProperty;
069    
070    import com.sun.media.jai.codec.MemoryCacheSeekableStream;
071    
072    /**
073     * The ExternalGraphic element allows a reference to be made to an external graphic file with a Web
074     * URL. The OnlineResource sub-element gives the URL and the Format sub-element identifies the
075     * expected document MIME type of a successful fetch. Knowing the MIME type in advance allows the
076     * styler to select the best- supported format from the list of URLs with equivalent content.
077     * 
078     * 
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
080     * @author last edited by: $Author: aschmitz $
081     * 
082     * @version. $Revision: 12167 $, $Date: 2008-06-04 16:06:48 +0200 (Mi, 04 Jun 2008) $
083     */
084    public class ExternalGraphic implements Marshallable {
085    
086        private BufferedImage image = null;
087    
088        private String format = null;
089    
090        private URL onlineResource = null;
091    
092        private TranscoderInput input = null;
093    
094        private ByteArrayOutputStream bos = null;
095    
096        private TranscoderOutput output = null;
097    
098        private Transcoder trc = null;
099    
100        /**
101         * Creates a new ExternalGraphic_Impl object.
102         * 
103         * @param format
104         * @param onlineResource
105         */
106        ExternalGraphic( String format, URL onlineResource ) {
107            setFormat( format );
108            setOnlineResource( onlineResource );
109        }
110    
111        /**
112         * the Format sub-element identifies the expected document MIME type of a successful fetch.
113         * 
114         * @return Format of the external graphic
115         * 
116         */
117        public String getFormat() {
118            return format;
119        }
120    
121        /**
122         * sets the format (MIME type)
123         * 
124         * @param format
125         *            Format of the external graphic
126         * 
127         */
128        public void setFormat( String format ) {
129            this.format = format;
130        }
131    
132        /**
133         * The OnlineResource gives the URL of the external graphic
134         * 
135         * @return URL of the external graphic
136         * 
137         */
138        public URL getOnlineResource() {
139            return onlineResource;
140        }
141    
142        /**
143         * sets the online resource / URL of the external graphic
144         * 
145         * @param onlineResource
146         *            URL of the external graphic
147         * 
148         */
149        public void setOnlineResource( URL onlineResource ) {
150    
151            this.onlineResource = onlineResource;
152            String file = onlineResource.getFile();
153            int idx = file.indexOf( "$" );
154            if ( idx == -1 ) {
155                retrieveImage( onlineResource );
156            }
157        }
158    
159        /**
160         * @param onlineResource
161         */
162        private void retrieveImage( URL onlineResource ) {
163    
164            try {
165                String t = onlineResource.toExternalForm();
166                if ( t.trim().toLowerCase().endsWith( ".svg" ) ) {
167                    // initialize the the classes required for svg handling
168                    bos = new ByteArrayOutputStream( 2000 );
169                    output = new TranscoderOutput( bos );
170                    // PNGTranscoder is needed to handle transparent parts
171                    // of a SVG
172                    trc = new PNGTranscoder();
173                    try {
174                        input = new TranscoderInput( NetWorker.url2String( onlineResource ) );
175                    } catch ( Exception e ) {
176                        e.printStackTrace();
177                    }
178                } else {
179                    InputStream is = onlineResource.openStream();
180                    MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is );
181                    RenderedOp rop = JAI.create( "stream", mcss );
182                    image = rop.getAsBufferedImage();
183                    mcss.close();
184                    is.close();
185                }
186            } catch ( IOException e ) {
187                System.out.println( "Yikes: " + e );
188            }
189        }
190    
191        /**
192         * returns the external graphic as an image. this method is not part of the sld specifications
193         * but it is added for speed up applications
194         * 
195         * @return the external graphic as BufferedImage
196         */
197        public BufferedImage getAsImage( int targetSizeX, int targetSizeY, Feature feature ) {
198    
199            if ( ( ( this.input == null ) && ( this.image == null ) ) || feature != null ) {
200                URL onlineResource = initializeOnlineResource( feature );
201                retrieveImage( onlineResource );
202            }
203    
204            if ( image != null && image.getWidth() == targetSizeX && image.getHeight() == targetSizeY ) {
205    
206            } else {
207                if ( input != null ) {
208                    if ( targetSizeX <= 0 )
209                        targetSizeX = 0;
210                    if ( targetSizeY <= 0 )
211                        targetSizeY = 0;
212    
213                    trc.addTranscodingHint( PNGTranscoder.KEY_HEIGHT, new Float( targetSizeX ) );
214                    trc.addTranscodingHint( PNGTranscoder.KEY_WIDTH, new Float( targetSizeY ) );
215                    try {
216                        trc.transcode( input, output );
217                        try {
218                            bos.flush();
219                            bos.close();
220                        } catch ( IOException e3 ) {
221                            e3.printStackTrace();
222                        }
223                    } catch ( TranscoderException e ) {
224                        e.printStackTrace();
225                    }
226                    try {
227                        ByteArrayInputStream is = new ByteArrayInputStream( bos.toByteArray() );
228                        MemoryCacheSeekableStream mcss = new MemoryCacheSeekableStream( is );
229                        RenderedOp rop = JAI.create( "stream", mcss );
230                        image = rop.getAsBufferedImage();
231                        mcss.close();
232                    } catch ( IOException e1 ) {
233                        e1.printStackTrace();
234                    }
235                }
236            }
237    
238            return image;
239        }
240    
241        /**
242         * @param feature
243         * @return online resource URL
244         */
245        private URL initializeOnlineResource( Feature feature ) {
246    
247            String file = this.onlineResource.getFile();
248            String[] tags = StringTools.extractStrings( file, "$", "$" );
249    
250            if ( tags != null ) {
251                FeatureProperty[] properties = feature.getProperties();
252                for ( int i = 0; i < tags.length; i++ ) {
253                    String tag = tags[i].substring( 1, tags[i].length() - 1 );
254                    for ( int j = 0; j < properties.length; j++ ) {
255                        if ( properties[j].getName().getLocalName().equals( tag ) ) {
256                            String to = (String) properties[j].getValue();
257                            file = StringTools.replace( file, tags[i], to, true );
258                        }
259                    }
260                }
261            }
262            URL onlineResource = null;
263            try {
264                String protocol = this.onlineResource.getProtocol();
265                String host = this.onlineResource.getHost();
266                onlineResource = new URL( protocol, host, file );
267            } catch ( MalformedURLException e ) {
268                e.printStackTrace();
269            }
270            return onlineResource;
271        }
272    
273        /**
274         * sets the external graphic as an image.
275         * 
276         * @param image
277         *            the external graphic as BufferedImage
278         */
279        public void setAsImage( BufferedImage image ) {
280            this.image = image;
281        }
282    
283        /**
284         * exports the content of the ExternalGraphic as XML formated String
285         * 
286         * @return xml representation of the ExternalGraphic
287         */
288        public String exportAsXML() {
289    
290            StringBuffer sb = new StringBuffer( 200 );
291            sb.append( "<ExternalGraphic>" );
292            sb.append( "<OnlineResource xmlns:xlink='http://www.w3.org/1999/xlink' " );
293            sb.append( "xlink:type='simple' xlink:href='" );
294            sb.append( NetWorker.url2String( onlineResource ) + "'/>" );
295            sb.append( "<Format>" ).append( escape( format ) ).append( "</Format>" );
296            sb.append( "</ExternalGraphic>" );
297            return sb.toString();
298        }
299    
300    }