001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/wms/control/HighlightingListener.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.portal.standard.wms.control;
037    
038    import java.io.FileOutputStream;
039    import java.io.IOException;
040    import java.io.OutputStreamWriter;
041    import java.net.URL;
042    import java.util.Map;
043    
044    import javax.servlet.http.HttpServletRequest;
045    import javax.servlet.http.HttpSession;
046    
047    import org.deegree.enterprise.control.FormEvent;
048    import org.deegree.enterprise.control.RPCMember;
049    import org.deegree.enterprise.control.RPCMethodCall;
050    import org.deegree.enterprise.control.RPCParameter;
051    import org.deegree.enterprise.control.RPCStruct;
052    import org.deegree.enterprise.control.RPCWebEvent;
053    import org.deegree.framework.log.ILogger;
054    import org.deegree.framework.log.LoggerFactory;
055    import org.deegree.framework.util.KVP2Map;
056    import org.deegree.framework.util.NetWorker;
057    import org.deegree.framework.util.StringTools;
058    import org.deegree.model.spatialschema.Envelope;
059    import org.deegree.model.spatialschema.GeometryFactory;
060    import org.deegree.model.spatialschema.Position;
061    import org.deegree.ogcwebservices.OGCWebServiceException;
062    import org.deegree.ogcwebservices.OWSUtils;
063    import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
064    import org.deegree.ogcwebservices.wfs.operation.GetFeature;
065    import org.deegree.ogcwebservices.wms.operation.GetMap;
066    import org.deegree.portal.context.GeneralExtension;
067    import org.deegree.portal.context.IOSettings;
068    import org.deegree.portal.context.LayerExtension;
069    import org.deegree.portal.context.ViewContext;
070    
071    /**
072     * This class is for highlighting polygons via a RPC request event from the client. A new WMS request will be created
073     * with SLD. The SLD xml file will be created and saved. The WMS request for highlighting will be set.
074     *
075     * <p>
076     * ------------------------------------------------------------------------
077     * </p>
078     *
079     * @author <a href="mailto:k.lupp@web.de>Katharina Lupp</a>
080     * @author last edited by: $Author: mays$
081     *
082     * @version $Revision: 18195 $, $Date: 27.05.2008 17:13:56$
083     */
084    public class HighlightingListener extends AbstractMapListener {
085    
086        private static final ILogger LOG = LoggerFactory.getLogger( HighlightingListener.class );
087    
088        // private String sldUserStyle = "highlightingSLDUserStyle.xml";
089        private String sldUserStyle = System.currentTimeMillis() + ".xml";
090    
091        /**
092         * This method will be called by the <tt>MapListener</tt> if a highlighting action/event occurs.
093         */
094        @Override
095        public void actionPerformed( FormEvent event ) {
096    
097            // default actions
098            super.actionPerformed( event );
099            RPCWebEvent rpc = (RPCWebEvent) event;
100            RPCMethodCall mc = rpc.getRPCMethodCall();
101            RPCParameter[] para = mc.getParameters();
102            RPCStruct struct = (RPCStruct) para[0].getValue();
103    
104            HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true );
105            ViewContext vc = (ViewContext) session.getAttribute( "DefaultMapContext" );
106    
107            try {
108                GetMap wmsRequest = createRequest( para, vc );
109                Position[] coords = getCoordinates( struct );
110                String queryLayer = getQueryLayer( struct );
111                Envelope env = wmsRequest.getBoundingBox();
112                StringBuffer sld = createSLD( coords, env, queryLayer, vc );
113                saveSLD( sld, vc );
114                highlight( queryLayer, wmsRequest, vc );
115            } catch ( Exception ex ) {
116                LOG.logError( "Highlighting was not successful: ", ex );
117            }
118    
119        }
120    
121        /**
122         * creates the modified WMS Request including the URL for the SLD.
123         */
124        private GetMap createRequest( RPCParameter[] para, ViewContext vc ) {
125    
126            GeneralExtension ge = vc.getGeneral().getExtension();
127            IOSettings ios = ge.getIOSettings();
128            URL onlineResource = ios.getSLDDirectory().getOnlineResource();
129    
130            RPCStruct struct = (RPCStruct) para[1].getValue();
131            RPCMember[] member = struct.getMembers();
132            String request = (String) member[0].getValue();
133            Map<String, String> getMR = KVP2Map.toMap( request );
134            getMR.put( "ID", "id" );
135            getMR.put( "FORMAT", "image/gif" );
136            getMR.put( "TRANSPARENT", "true" );
137            getMR.put( "SLD", NetWorker.url2String( onlineResource ) + "/" + sldUserStyle );
138            GetMap modifiedRequest = null;
139            try {
140                modifiedRequest = GetMap.create( getMR );
141            } catch ( Exception e ) {
142                e.printStackTrace();
143            }
144            return modifiedRequest;
145        }
146    
147        /**
148         * calculates the coordinates of the click event.
149         */
150        private Position[] getCoordinates( RPCStruct struct ) {
151    
152            String x = (String) struct.getMember( "X" ).getValue();
153            String y = (String) struct.getMember( "Y" ).getValue();
154            String[] tmpX = StringTools.toArray( x, ",", false );
155            String[] tmpY = StringTools.toArray( y, ",", false );
156    
157            Position[] pos = new Position[tmpX.length];
158            for ( int i = 0; i < tmpX.length; i++ ) {
159                double xtmp = Double.parseDouble( tmpX[i] );
160                double ytmp = Double.parseDouble( tmpY[i] );
161                pos[i] = GeometryFactory.createPosition( xtmp, ytmp );
162            }
163    
164            return pos;
165        }
166    
167        /**
168         * gets the layer to be highlighted.
169         */
170        private String getQueryLayer( RPCStruct struct ) {
171            RPCMember queryLayers = struct.getMember( "queryLayers" );
172            String queryLay = (String) queryLayers.getValue();
173            int index = queryLay.indexOf( "|" );
174            queryLay = queryLay.substring( 0, index );
175    
176            return queryLay;
177        }
178    
179        /**
180         * sets the request for highlighting.
181         */
182        private void highlight( String queryLayer, GetMap gmr, ViewContext vc )
183                                throws OGCWebServiceException {
184    
185            URL wmsURL = vc.getLayerList().getLayer( queryLayer, null ).getServer().getOnlineResource();
186    
187            String s = OWSUtils.validateHTTPGetBaseURL( wmsURL.toExternalForm() );
188            this.getRequest().setAttribute( "HighlightingRequest", s + gmr.getRequestParameter() );
189    
190        }
191    
192        /**
193         * creates the SLD xml file.
194         */
195        private StringBuffer createSLD( Position[] coords, Envelope env, String queryLay, ViewContext vc ) {
196            GeneralExtension ge = vc.getGeneral().getExtension();
197            IOSettings ios = ge.getIOSettings();
198            URL onlineResource = ios.getSLDDirectory().getOnlineResource();
199            LayerExtension le = vc.getLayerList().getLayer( queryLay, null ).getExtension();
200    
201            WFSCapabilities capa = (WFSCapabilities) le.getDataService().getServer().getCapabilities();
202            URL wfsurl = OWSUtils.getHTTPGetOperationURL( capa, GetFeature.class );
203    
204            StringBuffer sb = new StringBuffer( 10000 );
205    
206            sb.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
207            sb.append( "<StyledLayerDescriptor version=\"1.0.0\" xmlns=\"http://www.opengis.net/sld\" " );
208            sb.append( "xmlns:gml=\"http://www.opengis.net/gml\" xmlns:wfs=\"http://www.opengis.net/wfs\" " );
209            sb.append( "xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" " );
210            sb.append( "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" );
211            sb.append( "<UserLayer><Name>MyLayer</Name><RemoteOWS>" );
212            sb.append( "<Service>WFS</Service>" );
213            sb.append( "<OnlineResource xmlns:xlink='http://www.w3.org/1999/xlink' xlink:type='simple' " );
214            sb.append( "xlink:href='" + wfsurl.toExternalForm() + "'/>" );
215            sb.append( "</RemoteOWS><LayerFeatureConstraints><FeatureTypeConstraint>" );
216            sb.append( "<FeatureTypeName>" + queryLay + "</FeatureTypeName>" );
217            sb.append( "<ogc:Filter><ogc:And>" );
218            if ( coords.length > 1 )
219                sb.append( "<ogc:Or>" );
220            for ( int k = 0; k < coords.length; k++ ) {
221                sb.append( "<ogc:Intersects><ogc:PropertyName>GEOM</ogc:PropertyName>" );
222                sb.append( "<gml:Point><gml:coordinates>" + coords[k].getX() + "," );
223                sb.append( coords[k].getY() + "</gml:coordinates></gml:Point>" );
224                sb.append( "</ogc:Intersects>" );
225            }
226            if ( coords.length > 1 )
227                sb.append( "</ogc:Or>" );
228            sb.append( "<ogc:BBOX><ogc:PropertyName>GEOM</ogc:PropertyName>" );
229            sb.append( "<gml:Box><gml:coord><gml:X>" + env.getMin().getX() );
230            sb.append( "</gml:X><gml:Y>" + env.getMin().getY() + "</gml:Y>" );
231            sb.append( "</gml:coord><gml:coord><gml:X>" + env.getMax().getX() );
232            sb.append( "</gml:X><gml:Y>" + env.getMax().getY() + "</gml:Y>" );
233            sb.append( "</gml:coord></gml:Box></ogc:BBOX></ogc:And>" );
234            sb.append( "</ogc:Filter></FeatureTypeConstraint></LayerFeatureConstraints> " );
235    
236            sb.append( "<UserStyle><FeatureTypeStyle><Rule><MinScaleDenominator>0" );
237            sb.append( "</MinScaleDenominator><MaxScaleDenominator>999999999" );
238            sb.append( "</MaxScaleDenominator><PolygonSymbolizer><Fill><GraphicFill>" );
239            sb.append( "<Graphic><ExternalGraphic><OnlineResource xmlns:xlink=" );
240            sb.append( "'http://www.w3.org/1999/xlink' xlink:type='simple' xlink:href='" );
241            sb.append( NetWorker.url2String( onlineResource ) + "/pattern.gif' />" );
242            sb.append( "<Format>image/gif</Format></ExternalGraphic></Graphic></GraphicFill>" );
243            sb.append( "</Fill><Stroke><CssParameter name=\"stroke\">#FF0000</CssParameter>" );
244            sb.append( "<CssParameter name=\"stroke-opacity\">1.0</CssParameter>" );
245            sb.append( "<CssParameter name=\"stroke-width\">1.0</CssParameter>" );
246            sb.append( "<CssParameter name=\"stroke-dasharray\">1</CssParameter>" );
247            sb.append( "</Stroke></PolygonSymbolizer></Rule></FeatureTypeStyle>" );
248            sb.append( "</UserStyle></UserLayer></StyledLayerDescriptor>" );
249    
250            return sb;
251        }
252    
253        /**
254         * saves the created SLD file.
255         */
256        private void saveSLD( StringBuffer sld, ViewContext vc )
257                                throws IOException {
258            GeneralExtension ge = vc.getGeneral().getExtension();
259            IOSettings ios = ge.getIOSettings();
260            String dir = ios.getSLDDirectory().getDirectoryName();
261            OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream( dir + "/" + sldUserStyle ), "UTF-8" );
262            writer.write( sld.toString() );
263            writer.close();
264        }
265    
266    }