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