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 }