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