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