001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/tools/wms/WFS2WMS.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.tools.wms; 044 045 import java.io.File; 046 import java.io.FileOutputStream; 047 import java.net.URL; 048 import java.util.ArrayList; 049 import java.util.HashMap; 050 import java.util.List; 051 import java.util.Map; 052 import java.util.Properties; 053 054 import org.deegree.datatypes.QualifiedName; 055 import org.deegree.framework.log.ILogger; 056 import org.deegree.framework.log.LoggerFactory; 057 import org.deegree.framework.util.ColorUtils; 058 import org.deegree.framework.xml.NamespaceContext; 059 import org.deegree.framework.xml.XMLFragment; 060 import org.deegree.framework.xml.XMLParsingException; 061 import org.deegree.framework.xml.XMLTools; 062 import org.deegree.framework.xml.XSLTDocument; 063 import org.deegree.graphics.sld.AbstractLayer; 064 import org.deegree.graphics.sld.NamedLayer; 065 import org.deegree.graphics.sld.StyleFactory; 066 import org.deegree.graphics.sld.StyledLayerDescriptor; 067 import org.deegree.graphics.sld.UserStyle; 068 import org.deegree.ogcbase.CommonNamespaces; 069 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException; 070 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities; 071 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument; 072 import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType; 073 import org.w3c.dom.Node; 074 075 /** 076 * creates a deegree WMS configuration document or a Layer section from a WFS capabilities document. 077 * The datasource type for each layer will be LOCALWFS. Also a style with random color(s) will be 078 * created, assigned to the layers and stored in a xml document named $OUTFILE_BASE$_styles.xml. 079 * TODO support for usage of an already existing WMS configuration document TODO determine geometry 080 * types of the feature types registered within the wfs capabilities document 081 * 082 * 083 * @version $Revision: 9346 $ 084 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 085 * @author last edited by: $Author: apoth $ 086 * 087 * @version 1.0. $Revision: 9346 $, $Date: 2007-12-27 17:39:07 +0100 (Do, 27 Dez 2007) $ 088 * 089 * @since 2.0 090 */ 091 public class WFS2WMS { 092 093 private static NamespaceContext nsc = CommonNamespaces.getNamespaceContext(); 094 095 private ILogger LOG = LoggerFactory.getLogger( WFS2WMS.class ); 096 097 private URL xsl = WFS2WMS.class.getResource( "wfs2wms.xsl" ); 098 099 private Properties prop = null; 100 101 public WFS2WMS( Properties prop ) { 102 this.prop = prop; 103 } 104 105 public static double getMinX( Node node ) { 106 double v = -180; 107 try { 108 String s = XMLTools.getNodeAsString( node, ".", nsc, "-180 -90" ); 109 String[] t = s.split( " " ); 110 v = Double.parseDouble( t[0] ); 111 } catch ( XMLParsingException e ) { 112 e.printStackTrace(); 113 } 114 return v; 115 } 116 117 public static double getMinY( Node node ) { 118 double v = -90; 119 try { 120 String s = XMLTools.getNodeAsString( node, ".", nsc, "-180 -90" ); 121 String[] t = s.split( " " ); 122 v = Double.parseDouble( t[1] ); 123 } catch ( XMLParsingException e ) { 124 e.printStackTrace(); 125 } 126 return v; 127 } 128 129 public static double getMaxX( Node node ) { 130 double v = 180; 131 try { 132 String s = XMLTools.getNodeAsString( node, ".", nsc, "180 90" ); 133 String[] t = s.split( " " ); 134 v = Double.parseDouble( t[0] ); 135 } catch ( XMLParsingException e ) { 136 e.printStackTrace(); 137 } 138 return v; 139 } 140 141 public static double getMaxY( Node node ) { 142 double v = 90; 143 try { 144 String s = XMLTools.getNodeAsString( node, ".", nsc, "180 90" ); 145 String[] t = s.split( " " ); 146 v = Double.parseDouble( t[1] ); 147 } catch ( XMLParsingException e ) { 148 e.printStackTrace(); 149 } 150 return v; 151 } 152 153 /** 154 * append all required namespace definition to the root element 155 * 156 * @param xml 157 * @return 158 * @throws InvalidCapabilitiesException 159 */ 160 private XMLFragment addNamespaces( XMLFragment wms, WFSCapabilities capa ) { 161 WFSFeatureType[] fts = capa.getFeatureTypeList().getFeatureTypes(); 162 for ( int i = 0; i < fts.length; i++ ) { 163 QualifiedName qn = fts[i].getName(); 164 XMLTools.appendNSBinding( wms.getRootElement(), qn.getPrefix(), qn.getNamespace() ); 165 } 166 return wms; 167 } 168 169 /** 170 * creates a style for each feature type registered in a WFS capabilities document 171 * 172 * @param wfs 173 * @return 174 */ 175 private List<UserStyle> createStyles( WFSCapabilities capa ) { 176 List<UserStyle> styles = new ArrayList<UserStyle>(); 177 Map<QualifiedName, Integer> types = determineGeometryType( capa ); 178 179 WFSFeatureType[] fts = capa.getFeatureTypeList().getFeatureTypes(); 180 181 UserStyle st = null; 182 for ( int i = 0; i < fts.length; i++ ) { 183 QualifiedName qn = fts[i].getName(); 184 int type = types.get( qn ); 185 switch ( type ) { 186 case 1: { 187 st = (UserStyle) StyleFactory.createPointStyle( "square", ColorUtils.getRandomColor( false ), 188 ColorUtils.getRandomColor( false ), 1, 1, 10, 10, 0, 189 Double.MAX_VALUE ); 190 break; 191 } 192 case 2: { 193 st = (UserStyle) StyleFactory.createLineStyle( ColorUtils.getRandomColor( false ), 4, 1, 0, 194 Double.MAX_VALUE ); 195 break; 196 } 197 198 case 3: { 199 st = (UserStyle) StyleFactory.createPolygonStyle( ColorUtils.getRandomColor( false ), 1, 200 ColorUtils.getRandomColor( false ), 1, 1, 0, 201 Double.MAX_VALUE ); 202 break; 203 } 204 } 205 st.setName( "default:" + qn.getPrefixedName() ); 206 styles.add( st ); 207 } 208 209 return styles; 210 } 211 212 /** 213 * 214 * @param styles 215 * @return 216 */ 217 private StyledLayerDescriptor createSLD( List<UserStyle> styles ) { 218 219 UserStyle[] us = styles.toArray( new UserStyle[styles.size()] ); 220 NamedLayer nl = new NamedLayer( "defaultstyle", null, us ); 221 return new StyledLayerDescriptor( new AbstractLayer[] { nl }, "1.0.0" ); 222 223 } 224 225 /** 226 * returns the geometrytype of each feature type registered within the passed WFS capabilities 227 * document<br> 228 * <ul> 229 * <li>1 = point or multi point 230 * <li>2 = curve or multi curve 231 * <li>3 = surface or multi surface 232 * </ul> 233 * 234 * @param capa 235 * @return 236 */ 237 private Map<QualifiedName, Integer> determineGeometryType( WFSCapabilities capa ) { 238 239 Map<QualifiedName, Integer> types = new HashMap<QualifiedName, Integer>(); 240 241 WFSFeatureType[] fts = capa.getFeatureTypeList().getFeatureTypes(); 242 for ( int i = 0; i < fts.length; i++ ) { 243 QualifiedName qn = fts[i].getName(); 244 // TODO 245 // get real geometry type 246 types.put( qn, 3 ); 247 } 248 249 return types; 250 } 251 252 /** 253 * method the starts running the conversation 254 * 255 * @throws Exception 256 */ 257 public void run() 258 throws Exception { 259 260 String out = prop.getProperty( "-outFile" ); 261 File file = new File( out ); 262 int pos = file.getName().lastIndexOf( '.' ); 263 String styleDoc = file.getName().substring( 0, pos ) + "_styles.xml"; 264 265 HashMap<String, String> param = new HashMap<String, String>(); 266 param.put( "PARENTLAYER", prop.getProperty( "-parentLayer" ) ); 267 param.put( "MINX", prop.getProperty( "-minx" ) ); 268 param.put( "MINY", prop.getProperty( "-miny" ) ); 269 param.put( "MAXX", prop.getProperty( "-maxx" ) ); 270 param.put( "MAXY", prop.getProperty( "-maxy" ) ); 271 param.put( "SRS", prop.getProperty( "-srs" ) ); 272 if ( "true".equals( prop.getProperty( "-full" ) ) ) { 273 param.put( "WMSCAPS", "1" ); 274 } 275 param.put( "STYLEDOC", styleDoc ); 276 277 LOG.logInfo( "XSLT-parameter: ", param ); 278 279 XSLTDocument outXSLSheet = new XSLTDocument(); 280 outXSLSheet.load( xsl ); 281 282 file = new File( prop.getProperty( "-wfsCaps" ) ); 283 param.put( "WFSCAPS", file.toURL().toExternalForm() ); 284 XMLFragment doc = new XMLFragment(); 285 doc.load( file.toURL() ); 286 287 XMLFragment resultDocument = outXSLSheet.transform( doc, null, null, param ); 288 289 WFSCapabilitiesDocument wfsdoc = new WFSCapabilitiesDocument(); 290 wfsdoc.setRootElement( doc.getRootElement() ); 291 WFSCapabilities capa = (WFSCapabilities) wfsdoc.parseCapabilities(); 292 293 resultDocument = addNamespaces( resultDocument, capa ); 294 295 List<UserStyle> styles = createStyles( capa ); 296 StyledLayerDescriptor sld = createSLD( styles ); 297 298 String s = prop.getProperty( "-outFile" ).replace( ".xml", "_styles.xml" ); 299 file = new File( s ); 300 FileOutputStream fos = new FileOutputStream( file ); 301 fos.write( sld.exportAsXML().getBytes() ); 302 fos.close(); 303 304 file = new File( prop.getProperty( "-outFile" ) ); 305 fos = new FileOutputStream( file ); 306 resultDocument.write( fos ); 307 fos.close(); 308 } 309 310 private static void validate( Properties map ) 311 throws Exception { 312 if ( map.get( "-parentLayer" ) == null ) { 313 throw new Exception( Messages.getString( "WFS2WMS.validate_2" ) ); 314 } 315 if ( map.get( "-minx" ) != null ) { 316 Double.parseDouble( map.getProperty( "-minx" ) ); 317 } else { 318 map.put( "-minx", "-180" ); 319 } 320 if ( map.get( "-miny" ) != null ) { 321 Double.parseDouble( map.getProperty( "-miny" ) ); 322 } else { 323 map.put( "-miny", "-90" ); 324 } 325 if ( map.get( "-maxx" ) != null ) { 326 Double.parseDouble( map.getProperty( "-maxx" ) ); 327 } else { 328 map.put( "-maxx", "180" ); 329 } 330 if ( map.get( "-maxy" ) != null ) { 331 Double.parseDouble( map.getProperty( "-maxy" ) ); 332 } else { 333 map.put( "-maxy", "90" ); 334 } 335 if ( map.get( "-srs" ) == null ) { 336 map.put( "-srs", "EPSG:4326" ); 337 } 338 if ( map.get( "-wfsCaps" ) == null ) { 339 throw new Exception( Messages.getString( "WFS2WMS.validate_0" ) ); 340 } 341 if ( map.get( "-outFile" ) == null ) { 342 throw new Exception( Messages.getString( "WFS2WMS.validate_1" ) ); 343 } 344 } 345 346 /** 347 * @param args 348 */ 349 public static void main( String[] args ) 350 throws Exception { 351 352 Properties map = new Properties(); 353 for ( int i = 0; i < args.length; i += 2 ) { 354 System.out.println( args[i + 1] ); 355 map.put( args[i], args[i + 1] ); 356 } 357 358 try { 359 validate( map ); 360 } catch ( Exception e ) { 361 System.out.println( "!!! E R R O R !!!" ); 362 System.out.println( e.getMessage() ); 363 System.out.println( "----------------------------------------------------" ); 364 System.out.println( Messages.getString( "WFS2WMS.parentLayer" ) ); 365 System.out.println( Messages.getString( "WFS2WMS.wfsCaps" ) ); 366 System.out.println( Messages.getString( "WFS2WMS.outFile" ) ); 367 return; 368 } 369 370 WFS2WMS wfs2wms = new WFS2WMS( map ); 371 wfs2wms.run(); 372 373 } 374 375 }