/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn2 Germany E-Mail: poth@lat-lon.de Prof. Dr. Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: greve@giub.uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.portal.standard.wms.control; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.URL; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.deegree.enterprise.control.FormEvent; import org.deegree.enterprise.control.RPCMember; import org.deegree.enterprise.control.RPCMethodCall; import org.deegree.enterprise.control.RPCParameter; import org.deegree.enterprise.control.RPCStruct; import org.deegree.enterprise.control.RPCWebEvent; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.framework.util.KVP2Map; import org.deegree.framework.util.NetWorker; import org.deegree.framework.util.StringTools; import org.deegree.model.spatialschema.Envelope; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.Position; import org.deegree.ogcwebservices.OGCWebServiceException; import org.deegree.ogcwebservices.OWSUtils; import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; import org.deegree.ogcwebservices.wfs.operation.GetFeature; import org.deegree.ogcwebservices.wms.operation.GetMap; import org.deegree.portal.context.GeneralExtension; import org.deegree.portal.context.IOSettings; import org.deegree.portal.context.LayerExtension; import org.deegree.portal.context.ViewContext; /** * This class is for highlighting polygons via a RPC request event from the client. A new WMS * request will be created with SLD. The SLD xml file will be created and saved. The WMS request for * highlighting will be set. * * <p> * ------------------------------------------------------------------------ * </p> * * @author lupp <a href="mailto:k.lupp@web.de>Katharina Lupp</a> Created on 15.02.2004 */ public class HighlightingListener extends AbstractMapListener { private static final ILogger LOG = LoggerFactory.getLogger( HighlightingListener.class ); // private String sldUserStyle = "highlightingSLDUserStyle.xml"; private String sldUserStyle = System.currentTimeMillis() + ".xml"; /** * This method will be called by the <tt>MapListener</tt> if a highlighting action/event * occurs. */ public void actionPerformed( FormEvent event ) { // default actions super.actionPerformed( event ); RPCWebEvent rpc = (RPCWebEvent) event; RPCMethodCall mc = rpc.getRPCMethodCall(); RPCParameter[] para = mc.getParameters(); RPCStruct struct = (RPCStruct) para[0].getValue(); HttpSession session = ( (HttpServletRequest) this.getRequest() ).getSession( true ); ViewContext vc = (ViewContext) session.getAttribute( "DefaultMapContext" ); try { GetMap wmsRequest = createRequest( para, vc ); Position[] coords = getCoordinates( struct ); String queryLayer = getQueryLayer( struct ); Envelope env = wmsRequest.getBoundingBox(); StringBuffer sld = createSLD( coords, env, queryLayer, vc ); saveSLD( sld, vc ); highlight( queryLayer, wmsRequest, vc ); } catch (Exception ex) { LOG.logError( "Highlighting was not successful: ", ex ); } } /** * creates the modified WMS Request including the URL for the SLD. */ private GetMap createRequest( RPCParameter[] para, ViewContext vc ) { GeneralExtension ge = vc.getGeneral().getExtension(); IOSettings ios = ge.getIOSettings(); URL onlineResource = ios.getSLDDirectory().getOnlineResource(); RPCStruct struct = (RPCStruct) para[1].getValue(); RPCMember[] member = struct.getMembers(); String request = (String) member[0].getValue(); Map getMR = KVP2Map.toMap( request ); getMR.put( "ID", "id" ); getMR.put( "FORMAT", "image/gif" ); getMR.put( "TRANSPARENT", "true" ); getMR.put( "SLD", NetWorker.url2String( onlineResource ) + "/" + sldUserStyle ); GetMap modifiedRequest = null; try { modifiedRequest = GetMap.create( getMR ); } catch (Exception e) { e.printStackTrace(); } return modifiedRequest; } /** * calculates the coordinates of the click event. */ private Position[] getCoordinates( RPCStruct struct ) { String x = (String) struct.getMember( "X" ).getValue(); String y = (String) struct.getMember( "Y" ).getValue(); String[] tmpX = StringTools.toArray( x, ",", false ); String[] tmpY = StringTools.toArray( y, ",", false ); Position[] pos = new Position[tmpX.length]; for (int i = 0; i < tmpX.length; i++) { double xtmp = Double.parseDouble( tmpX[i] ); double ytmp = Double.parseDouble( tmpY[i] ); pos[i] = GeometryFactory.createPosition( xtmp, ytmp ); } return pos; } /** * gets the layer to be highlighted. */ private String getQueryLayer( RPCStruct struct ) { RPCMember queryLayers = struct.getMember( "queryLayers" ); String queryLay = (String) queryLayers.getValue(); int index = queryLay.indexOf( "|" ); queryLay = queryLay.substring( 0, index ); return queryLay; } /** * sets the request for highlighting. */ private void highlight( String queryLayer, GetMap gmr, ViewContext vc ) throws OGCWebServiceException { URL wmsURL = vc.getLayerList().getLayer( queryLayer ).getServer().getOnlineResource(); String s = OWSUtils.validateHTTPGetBaseURL( wmsURL.toExternalForm() ); this.getRequest().setAttribute( "HighlightingRequest", s + gmr.getRequestParameter() ); } /** * creates the SLD xml file. */ private StringBuffer createSLD( Position[] coords, Envelope env, String queryLay, ViewContext vc ) { GeneralExtension ge = vc.getGeneral().getExtension(); IOSettings ios = ge.getIOSettings(); URL onlineResource = ios.getSLDDirectory().getOnlineResource(); LayerExtension le = vc.getLayerList().getLayer( queryLay ).getExtension(); WFSCapabilities capa = (WFSCapabilities)le.getDataService().getServer().getCapabilities(); URL wfsurl = OWSUtils.getHTTPGetOperationURL( capa, GetFeature.class ); StringBuffer sb = new StringBuffer( 10000 ); sb.append( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ); sb.append( "<StyledLayerDescriptor version=\"1.0.0\" xmlns=\"http://www.opengis.net/sld\" " ); sb.append( "xmlns:gml=\"http://www.opengis.net/gml\" xmlns:wfs=\"http://www.opengis.net/wfs\" " ); sb.append( "xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" " ); sb.append( "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" ); sb.append( "<UserLayer><Name>MyLayer</Name><RemoteOWS>" ); sb.append( "<Service>WFS</Service>" ); sb.append( "<OnlineResource xmlns:xlink='http://www.w3.org/1999/xlink' xlink:type='simple' " ); sb.append( "xlink:href='" + wfsurl.toExternalForm() + "'/>" ); sb.append( "</RemoteOWS><LayerFeatureConstraints><FeatureTypeConstraint>" ); sb.append( "<FeatureTypeName>" + queryLay + "</FeatureTypeName>" ); sb.append( "<ogc:Filter><ogc:And>" ); if ( coords.length > 1 ) sb.append( "<ogc:Or>" ); for (int k = 0; k < coords.length; k++) { sb.append( "<ogc:Intersects><ogc:PropertyName>GEOM</ogc:PropertyName>" ); sb.append( "<gml:Point><gml:coordinates>" + coords[k].getX() + "," ); sb.append( coords[k].getY() + "</gml:coordinates></gml:Point>" ); sb.append( "</ogc:Intersects>" ); } if ( coords.length > 1 ) sb.append( "</ogc:Or>" ); sb.append( "<ogc:BBOX><ogc:PropertyName>GEOM</ogc:PropertyName>" ); sb.append( "<gml:Box><gml:coord><gml:X>" + env.getMin().getX() ); sb.append( "</gml:X><gml:Y>" + env.getMin().getY() + "</gml:Y>" ); sb.append( "</gml:coord><gml:coord><gml:X>" + env.getMax().getX() ); sb.append( "</gml:X><gml:Y>" + env.getMax().getY() + "</gml:Y>" ); sb.append( "</gml:coord></gml:Box></ogc:BBOX></ogc:And>" ); sb.append( "</ogc:Filter></FeatureTypeConstraint></LayerFeatureConstraints> " ); sb.append( "<UserStyle><FeatureTypeStyle><Rule><MinScaleDenominator>0" ); sb.append( "</MinScaleDenominator><MaxScaleDenominator>999999999" ); sb.append( "</MaxScaleDenominator><PolygonSymbolizer><Fill><GraphicFill>" ); sb.append( "<Graphic><ExternalGraphic><OnlineResource xmlns:xlink=" ); sb.append( "'http://www.w3.org/1999/xlink' xlink:type='simple' xlink:href='" ); sb.append( NetWorker.url2String( onlineResource ) + "/pattern.gif' />" ); sb.append( "<Format>image/gif</Format></ExternalGraphic></Graphic></GraphicFill>" ); sb.append( "</Fill><Stroke><CssParameter name=\"stroke\">#FF0000</CssParameter>" ); sb.append( "<CssParameter name=\"stroke-opacity\">1.0</CssParameter>" ); sb.append( "<CssParameter name=\"stroke-width\">1.0</CssParameter>" ); sb.append( "<CssParameter name=\"stroke-dasharray\">1</CssParameter>" ); sb.append( "</Stroke></PolygonSymbolizer></Rule></FeatureTypeStyle>" ); sb.append( "</UserStyle></UserLayer></StyledLayerDescriptor>" ); return sb; } /** * saves the created SLD file. */ private void saveSLD( StringBuffer sld, ViewContext vc ) throws IOException { GeneralExtension ge = vc.getGeneral().getExtension(); IOSettings ios = ge.getIOSettings(); String dir = ios.getSLDDirectory().getDirectoryName(); OutputStreamWriter writer = new OutputStreamWriter( new FileOutputStream( dir + "/" + sldUserStyle ), "UTF-8" ); writer.write( sld.toString() ); writer.close(); } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: HighlightingListener.java,v $ Revision 1.10 2006/10/17 20:31:17 poth *** empty log message *** Revision 1.9 2006/09/06 08:43:38 poth code enhancment / removing references to deprecated class / use OWSUtil instead of mauelly creating a base URL Revision 1.8 2006/08/29 19:54:13 poth footer corrected Revision 1.7 2006/08/20 20:53:54 poth changes rquired as a consequence of bug fix in wmc implementation/handling. Instead of determining the correct URL as given in a services capabilities deegree always has used the base URL which is just guarenteed to be valid for GetCapabilities requests. Revision 1.6 2006/08/07 13:58:35 poth useless type cast removed / never thrown exceptions removed Revision 1.5 2006/07/12 14:46:18 poth comment footer added ********************************************************************** */