001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wms/GetMapServiceInvokerForUL.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2007 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     53177 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    package org.deegree.ogcwebservices.wms;
044    
045    import java.io.ByteArrayOutputStream;
046    import java.io.InputStreamReader;
047    import java.io.StringReader;
048    import java.net.URI;
049    import java.net.URL;
050    import java.util.Arrays;
051    import java.util.Iterator;
052    import java.util.List;
053    import java.util.Map;
054    
055    import org.deegree.datatypes.QualifiedName;
056    import org.deegree.framework.log.ILogger;
057    import org.deegree.framework.log.LoggerFactory;
058    import org.deegree.framework.util.CharsetUtils;
059    import org.deegree.framework.util.IDGenerator;
060    import org.deegree.framework.util.NetWorker;
061    import org.deegree.framework.xml.XMLFragment;
062    import org.deegree.graphics.MapFactory;
063    import org.deegree.graphics.sld.AbstractStyle;
064    import org.deegree.graphics.sld.FeatureTypeConstraint;
065    import org.deegree.graphics.sld.LayerFeatureConstraints;
066    import org.deegree.graphics.sld.RemoteOWS;
067    import org.deegree.graphics.sld.StyleUtils;
068    import org.deegree.graphics.sld.UserLayer;
069    import org.deegree.graphics.sld.UserStyle;
070    import org.deegree.model.feature.FeatureCollection;
071    import org.deegree.model.feature.GMLFeatureCollectionDocument;
072    import org.deegree.model.filterencoding.Filter;
073    import org.deegree.ogcbase.PropertyPath;
074    import org.deegree.ogcwebservices.OGCWebServiceException;
075    import org.deegree.ogcwebservices.wfs.WFService;
076    import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
077    import org.deegree.ogcwebservices.wfs.operation.GetFeature;
078    import org.w3c.dom.Element;
079    
080    /**
081     * class for accessing the data of one user layer and creating <tt>DisplayElement</tt>s and a
082     * <tt>Thrme</tt> from it. The class extends <tt>Thread</tt> and implements the run method, so
083     * that a parallel data accessing from several layers is possible.
084     * 
085     * @version $Revision: 6891 $
086     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
087     * @author last edited by: $Author: aschmitz $
088     * 
089     * @version 1.0. $Revision: 6891 $, $Date: 2007-05-08 14:02:55 +0200 (Di, 08 Mai 2007) $
090     * 
091     * @since 2.0
092     */
093    class GetMapServiceInvokerForUL extends GetMapServiceInvoker implements Runnable {
094    
095        private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvokerForUL.class );
096    
097        private UserLayer layer = null;
098    
099        private UserStyle[] styles = null;
100    
101        /**
102         * 
103         * @param handler
104         * @param layer
105         * @param scale
106         *            current mapscale denominator
107         * @param index
108         */
109        GetMapServiceInvokerForUL( DefaultGetMapHandler handler, UserLayer layer, double scale, int index ) {
110            super( handler, index, scale );
111    
112            this.layer = layer;
113            AbstractStyle[] tmp = layer.getStyles();
114            styles = new UserStyle[tmp.length];
115            for ( int i = 0; i < tmp.length; i++ ) {
116                styles[i] = (UserStyle) tmp[i];
117            }
118    
119        }
120    
121        /**
122         * overrides/implements the run-method of <tt>Thread</tt>
123         */
124        public void run() {
125    
126            try {
127                if ( layer.getRemoteOWS() == null || layer.getRemoteOWS().getService().equals( RemoteOWS.WFS ) ) {
128                    handleWFS();
129                } else if ( layer.getRemoteOWS().getService().equals( RemoteOWS.WCS ) ) {
130                    handleWCS();
131                }
132            } catch ( Exception e ) {
133                LOG.logError( e.getMessage(), e );
134                OGCWebServiceException exce = new OGCWebServiceException( "ServiceInvokerForUL: " + layer.getName(),
135                                                                          "Couldn't perform query!" );
136                this.handler.putTheme( index, exce );
137                this.handler.increaseCounter();
138                LOG.exiting();
139                return;
140            }
141    
142        }
143    
144        /**
145         * handles requests against a WFS
146         */
147        private void handleWFS()
148                                throws Exception {
149    
150            FeatureCollection fc = null;
151            String request = createGetFeatureRequest();
152            LOG.logDebug( request );
153            if ( layer.getRemoteOWS() != null ) {
154                // handle request against a remote WFS
155                RemoteOWS remoteOWS = layer.getRemoteOWS();
156                URL url = remoteOWS.getOnlineResource();
157    
158                NetWorker nw = new NetWorker( CharsetUtils.getSystemCharset(), url, request );
159                InputStreamReader isr = new InputStreamReader( nw.getInputStream(), CharsetUtils.getSystemCharset() );
160                GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
161                doc.load( isr, url.toString() );
162                Element root = doc.getRootElement();
163    
164                if ( root.getNodeName().indexOf( "Exception" ) > -1 ) {
165                    ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000 );
166                    doc.write( bos );
167                    throw new Exception( new String( bos.toByteArray() ) );
168                }
169                fc = doc.parse();
170            } else {
171                // handle request agaist a local WFS; this is bit problematic
172                // because deegree WMS is able to handle more than one
173                // local WFS. At the moment the WFS will be used that will
174                // returned by the WFServiceFactory as default
175                XMLFragment xml = new XMLFragment( new StringReader( request ), XMLFragment.DEFAULT_URL );
176                Element root = xml.getRootElement();
177                // create OGCWebServiceEvent object
178                IDGenerator idg = IDGenerator.getInstance();
179                GetFeature gfr = GetFeature.create( "" + idg.generateUniqueID(), root );
180    
181                // returns the WFS responsible for handling current feature type
182                WFService wfs = getResponsibleService( layer );
183                FeatureResult fr = (FeatureResult) wfs.doService( gfr );
184                fc = (FeatureCollection) fr.getResponse();
185            }
186            org.deegree.graphics.Layer fl = MapFactory.createFeatureLayer( layer.getName(), this.handler.getRequestCRS(),
187                                                                           fc );
188            this.handler.putTheme( index, MapFactory.createTheme( layer.getName(), fl, styles ) );
189            this.handler.increaseCounter();
190    
191        }
192    
193        /**
194         * creates a GetFeature request related to the UserLayer encapsulated in this object
195         */
196        private String createGetFeatureRequest()
197                                throws Exception {
198    
199            LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints();
200            FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
201    
202            List<UserStyle> styleList = Arrays.asList( styles );
203            List<PropertyPath> pp = StyleUtils.extractRequiredProperties( styleList, scaleDen );
204            LOG.logDebug( "required properties: ", pp );
205            pp = findGeoProperties( layer, ftc, pp );
206            Map<String, URI> namesp = extractNameSpaceDef( pp );
207            for ( int i = 0; i < ftc.length; i++ ) {
208                QualifiedName qn = ftc[i].getFeatureTypeName();
209                namesp.put( qn.getPrefix(), qn.getNamespace() );
210            }
211    
212            StringBuffer sb = new StringBuffer( 5000 );
213            sb.append( "<?xml version='1.0' encoding='" + CharsetUtils.getSystemCharset() + "'?>" );
214            sb.append( "<GetFeature xmlns='http://www.opengis.net/wfs' " );
215            sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " );
216            sb.append( "xmlns:gml='http://www.opengis.net/gml' " );
217    
218            Iterator<String> iter = namesp.keySet().iterator();
219            while ( iter.hasNext() ) {
220                String pre = iter.next();
221                URI nsp = namesp.get( pre );
222                if ( !pre.equals( "xmlns" ) ) {
223                    sb.append( "xmlns:" ).append( pre ).append( "='" );
224                    sb.append( nsp.toASCIIString() ).append( "' " );
225                }
226            }
227    
228            sb.append( "service='WFS' version='1.1.0' " );
229            sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" );
230            for ( int i = 0; i < ftc.length; i++ ) {
231                QualifiedName qn = ftc[i].getFeatureTypeName();
232                sb.append( "<Query typeName='" ).append( qn.getPrefixedName() ).append( "'>" );
233    
234                for ( int j = 0; j < pp.size(); j++ ) {
235                    if ( !pp.get( j ).getAsString().endsWith( "$SCALE" ) ) {
236                        // $SCALE is a dynamicly created property of each feature
237                        // and can not be requested
238                        sb.append( "<PropertyName>" ).append( pp.get( j ).getAsString() );
239                        sb.append( "</PropertyName>" );
240                    }
241                }
242    
243                Filter filter = ftc[i].getFilter();
244                if ( filter != null ) {
245                    sb.append( filter.toXML() );
246                }
247                sb.append( "</Query>" );
248            }
249            sb.append( "</GetFeature>" );
250    
251            LOG.logDebug( sb.toString() );
252    
253            return sb.toString();
254        }
255    
256        /**
257         * handles requests against a WCS
258         */
259        private void handleWCS()
260                                throws Exception {
261    
262            /*
263             * TODO RemoteOWS remoteOWS = layer.getRemoteOWS(); URL url = remoteOWS.getOnlineResource();
264             * 
265             * NetWorker nw = new NetWorker( url ); MemoryCacheSeekableStream mcss = new
266             * MemoryCacheSeekableStream( nw.getInputStream() );
267             * 
268             * RenderedOp rop = JAI.create("stream", mcss);
269             * 
270             * GC_GridCoverage gc = new ImageGridCoverage(rop.getAsBufferedImage(),
271             * request.getBoundingBox(), reqCRS, false); mcss.close();
272             * 
273             * org.deegree.graphics.Layer rl = MapFactory.createRasterLayer(layer.getName(), gc);
274             * 
275             * putTheme(index, MapFactory.createTheme(layer.getName(), rl)); mcss.close();
276             * increaseCounter();
277             */
278    
279        }
280    
281    }