    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/portal/standard/csw/control/ISO19115RequestFactory.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
    037    package org.deegree.portal.standard.csw.control;
    038
    039    import java.io.BufferedReader;
    040    import java.io.InputStream;
    041    import java.io.InputStreamReader;
    042    import java.util.Properties;
    043
    044    import org.deegree.datatypes.QualifiedName;
    045    import org.deegree.enterprise.control.RPCStruct;
    046    import org.deegree.framework.log.ILogger;
    047    import org.deegree.framework.log.LoggerFactory;
    048    import org.deegree.framework.util.StringTools;
    049    import org.deegree.i18n.Messages;
    050    import org.deegree.model.crs.CRSFactory;
    051    import org.deegree.model.crs.CoordinateSystem;
    052    import org.deegree.model.crs.GeoTransformer;
    053    import org.deegree.model.crs.UnknownCRSException;
    054    import org.deegree.model.filterencoding.Literal;
    055    import org.deegree.model.filterencoding.Operation;
    056    import org.deegree.model.filterencoding.OperationDefines;
    057    import org.deegree.model.filterencoding.PropertyIsCOMPOperation;
    058    import org.deegree.model.filterencoding.PropertyIsLikeOperation;
    059    import org.deegree.model.filterencoding.PropertyIsNullOperation;
    060    import org.deegree.model.filterencoding.PropertyName;
    061    import org.deegree.model.filterencoding.SpatialOperation;
    062    import org.deegree.model.spatialschema.Envelope;
    063    import org.deegree.model.spatialschema.Geometry;
    064    import org.deegree.model.spatialschema.GeometryException;
    065    import org.deegree.model.spatialschema.GeometryFactory;
    066    import org.deegree.portal.standard.csw.CatalogClientException;
    067
    068    /**
    069     * A <code>${type_name}</code> class.<br/>
    070     *
    071     * class for creating a get GetRecord Request against a catalog based on OGC Stateless Web Service Catalog Profil and
    072     * GDI NRW catalog specifications to access data metadata (ISO 19115).
    073     * <p>
    074     * The only public method of the class receives a 'model' represented by a <tt>HashMap</tt> that contains the request
    075     * parameters as name-value-pairs. The names corresponds to the form-field-names. For common this will be the fields of
    076     * a HTML-form but it can be any other form (e.g. swing-application)
    077     * </p>
    078     *
    079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    080     * @author last edited by: $Author: jmays $
    081     *
    082     * @version $Revision: 19183 $, $Date: 2009-08-17 18:05:15 +0200 (Mo, 17. Aug 2009) $
    083     */
    084    public class ISO19115RequestFactory extends CSWRequestFactory {
    085
    086        private static final ILogger LOG = LoggerFactory.getLogger( ISO19115RequestFactory.class );
    087
    088        static final String RPC_SIMPLESEARCH = "RPC_SIMPLESEARCH";
    089
    090        private static final char WILDCARD = '*';
    091
    092        // private static final String OUTPUTSCHEMA = "csw:profile";
    093        private static final String OUTPUTSCHEMA = "http://www.isotc211.org/2005/gmd";
    094
    095        private RPCStruct struct = null;
    096
    097        private Properties requestElementsProps = new Properties();
    098
    099        /**
    100         *
    101         */
    102        public ISO19115RequestFactory() {
    103            try {
    104                InputStream is = ISO19115RequestFactory.class.getResourceAsStream( "ISO19115requestElements.properties" );
    105                this.requestElementsProps.load( is );
    106            } catch ( Exception e ) {
    107                LOG.logError( e.getLocalizedMessage(), e );
    108            }
    109        }
    110
    111        /**
    112         * creates a GetRecord request that is conform to the OGC Stateless Web Service Catalog Profil and GDI NRW catalog
    113         * specifications from a RPC struct.
    114         *
    115         * @param struct
    116         *            RPC structure containing the request parameter
    117         * @param resultType
    118         * @return GetFeature request as a string
    119         * @throws CatalogClientException
    120         */
    121        @Override
    122        public String createRequest( RPCStruct struct, String resultType )
    123                                throws CatalogClientException {
    124
    125            this.struct = struct;
    126            boolean isSearchRequest = false;
    127            boolean isOverviewRequest = false;
    128
    129            if ( "HITS".equals( resultType ) || "RESULTS".equals( resultType ) ) {
    130                isSearchRequest = true;
    131                LOG.logDebug( "request is searchRequest" );
    132            } else if ( resultType == null ) {
    133                LOG.logDebug( "request is overviewRequest" );
    134                isOverviewRequest = true;
    135            }
    136
    137            InputStream is = null;
    138            InputStreamReader ireader = null;
    139            BufferedReader br = null;
    140            StringBuffer sb = null;
    141            String request = null;
    142
    143            if ( isSearchRequest ) {
    144                is = ISO19115RequestFactory.class.getResourceAsStream( "CSWGetRecordsTemplate.xml" );
    145            } else if ( isOverviewRequest ) {
    146                is = ISO19115RequestFactory.class.getResourceAsStream( "CSWGetRecordByIdTemplate.xml" );
    147            }
    148
    149            try {
    150                ireader = new InputStreamReader( is );
    151                br = new BufferedReader( ireader );
    152                sb = new StringBuffer( 50000 );
    153
    154                while ( ( request = br.readLine() ) != null ) {
    155                    sb.append( request );
    156                }
    157                request = sb.toString();
    158                br.close();
    159
    160            } catch ( Exception e ) {
    161                LOG.logError( e.getMessage(), e );
    162            }
    163
    164            if ( isSearchRequest ) {
    165                try {
    166                    request = replaceVarsInSearchRequest( request, resultType );
    167                } catch ( UnknownCRSException e ) {
    168                    throw new CatalogClientException( e.getMessage(), e );
    169                }
    170            } else if ( isOverviewRequest ) {
    171                request = replaceVarsInOverviewRequest( request );
    172            }
    173
    174            return request;
    175        }
    176
    177        /**
    178         * @param request
    179         * @param resultType
    180         * @return Returns the request, where all variables are replaced by values.
    181         * @throws CatalogClientException
    182         * @throws UnknownCRSException
    183         */
    184        private String replaceVarsInSearchRequest( String request, String resultType )
    185                                throws CatalogClientException, UnknownCRSException {
    186
    187            // replace variables from template
    188
    189            String filter = createFilterEncoding();
    190            request = request.replaceFirst( "\\$FILTER", filter );
    191
    192            request = request.replaceFirst( "\\$OUTPUTSCHEMA", OUTPUTSCHEMA );
    193
    194            request = request.replaceFirst( "\\$RESULTTYPE", resultType );
    195
    196            // According to OGC CSW-spec default is 1
    197            String startPos = "1";
    198            if ( struct.getMember( RPC_STARTPOSITION ) != null ) {
    199                startPos = (String) struct.getMember( RPC_STARTPOSITION ).getValue();
    200            }
    201            request = request.replaceFirst( "\\$STARTPOSITION", startPos );
    202
    203            // According to OGC CSW-spec default is 10
    204            String maxRecords = Integer.toString( config.getMaxRecords() );
    205            request = request.replaceFirst( "\\$MAXRECORDS", maxRecords );
    206
    207            // For 2.0.0
    208            // String queryType = "csw:dataset"; // dataset, dataseries, application
    209            // For 2.0.2
    210            String queryType = "gmd:MD_Metadata"; // possible values are: csw:Records, gmd:MD_Metadata, csw:service
    211            if ( struct.getMember( RPC_TYPENAME ) != null ) {
    212                queryType = (String) struct.getMember( RPC_TYPENAME ).getValue();
    213            }
    214            /*
    215             * if ( struct.getMember( RPC_TYPENAME ) != null ) { queryType = (String) struct.getMember( RPC_TYPENAME
    216             * ).getValue(); if ( !"gmd:MD_Metadata".equals( queryType ) && !"csw:Record".equals( queryType )) {
    217             * LOG.logError( StringTools.concat( 100, "typename ", queryType, " is not a supported type.", "Suuported types
    218             * are: ", "gmd:MD_Metadata", "csw:Record" ) ); queryType = "gmd:MD_Metadata"; } }
    219             */
    220            request = request.replaceFirst( "\\$TYPENAME", queryType );
    221
    222            String elementSet = "brief"; // brief, summary, full
    223            if ( struct.getMember( RPC_ELEMENTSETNAME ) != null ) {
    224                elementSet = (String) struct.getMember( RPC_ELEMENTSETNAME ).getValue();
    225            }
    226            request = request.replaceFirst( "\\$ELEMENTSETNAME", elementSet );
    227
    228            return request;
    229        }
    230
    231        /**
    232         * @param request
    233         * @return Returns the request, where all variables are replaced by values.
    234         * @throws CatalogClientException
    235         */
    236        private String replaceVarsInOverviewRequest( String request )
    237                                throws CatalogClientException {
    238
    239            String id = null;
    240            if ( struct.getMember( Constants.RPC_IDENTIFIER ) != null ) {
    241                id = (String) struct.getMember( Constants.RPC_IDENTIFIER ).getValue();
    242            } else {
    243                throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_ID_NOT_SET" ) );
    244            }
    245            request = request.replaceFirst( "\\$IDENTIFIER", id );
    246
    247            request = request.replaceFirst( "\\$OUTPUTSCHEMA", OUTPUTSCHEMA );
    248
    249            String elementSet = "full"; // brief, summary, full
    250            if ( struct.getMember( RPC_ELEMENTSETNAME ) != null ) {
    251                elementSet = (String) struct.getMember( RPC_ELEMENTSETNAME ).getValue();
    252            }
    253            request = request.replaceFirst( "\\$ELEMENTSETNAME", elementSet );
    254
    255            return request;
    256        }
    257
    258        /**
    259         * takes RequestModel and builds a String result out of it. The result should be OGC FilterEncoding conformant.
    260         *
    261         * @return Returns the fragment for filter encoding.
    262         * @throws CatalogClientException
    263         * @throws UnknownCRSException
    264         */
    265        private String createFilterEncoding()
    266                                throws CatalogClientException, UnknownCRSException {
    267
    268            StringBuffer sb = new StringBuffer( 2000 );
    269            int expCounter = 0;
    270            LOG.logDebug( "in method createFilterEncoding" );
    271            sb.append( "<csw:Constraint version='1.0.0'><ogc:Filter>" );
    272
    273            // build filter encoding structure, handle all known fields sequentially
    274            String s = handleFileIdentifier();
    275            LOG.logDebug( "file identifier=", s );
    276            if ( ( s != null ) && ( s.length() > 0 ) ) {
    277                expCounter++;
    278                sb.append( s );
    279            }
    280
    281            s = handleParentIdentifier();
    282            LOG.logDebug( "parent identifier=", s );
    283            if ( ( s != null ) && ( s.length() > 0 ) ) {
    284                expCounter++;
    285                sb.append( s );
    286            }
    287
    288            s = handleSimpleSearch();
    289            LOG.logDebug( "simple search=", s );
    290            if ( ( s != null ) && ( s.length() > 0 ) ) {
    291                expCounter++;
    292                sb.append( s );
    293            }
    294
    295            s = handleTopiccategory();
    296            LOG.logDebug( "topic category=", s );
    297            if ( ( s != null ) && ( s.length() > 0 ) ) {
    298                expCounter++;
    299                sb.append( s );
    300            }
    301
    302            s = handleKeywords();
    303            LOG.logDebug( "handle keywords=", s );
    304            if ( ( s != null ) && ( s.length() > 0 ) ) {
    305                expCounter++;
    306                sb.append( s );
    307            }
    308
    309            s = handleDate();
    310            LOG.logDebug( "date=", s );
    311            if ( ( s != null ) && ( s.length() > 0 ) ) {
    312                expCounter++;
    313                sb.append( s );
    314            }
    315
    316            s = handleBbox();
    317            LOG.logDebug( "box=", s );
    318            if ( ( s != null ) && ( s.length() > 0 ) ) {
    319                expCounter++;
    320                sb.append( s );
    321            }
    322
    323            s = handleMetadataType();
    324            LOG.logDebug( "MetadataType=", s );
    325            if ( ( s != null ) && ( s.length() > 0 ) ) {
    326                expCounter++;
    327                sb.append( s );
    328            }
    329
    330            if ( expCounter > 1 ) {
    331                sb.insert( "<csw:Constraint version='1.0.0'><ogc:Filter>".length(), "<ogc:And>" );
    332                sb.append( "</ogc:And>" );
    333            }
    334
    335            sb.append( "</ogc:Filter></csw:Constraint>" );
    336
    337            return sb.toString();
    338        }
    339
    340        /**
    341         * Build OGC Filterencoding fragment: use <code>CSWRequestmodel</code> field <b>fileIdentifier</b> to create
    342         * Comparison Operation.
    343         *
    344         * @return Returns the fragment for fileIdentifier. May be empty.
    345         */
    346        private String handleFileIdentifier() {
    347
    348            StringBuffer sb = new StringBuffer( 1000 );
    349
    350            String id = null;
    351            if ( struct.getMember( Constants.RPC_IDENTIFIER ) != null ) {
    352                id = (String) struct.getMember( Constants.RPC_IDENTIFIER ).getValue();
    353            }
    354
    355            if ( ( id != null ) && ( id.trim().length() > 0 ) ) {
    356                String cf_props = requestElementsProps.getProperty( Constants.CONF_IDENTIFIER );
    357                String[] cf = cf_props.split( ";" );
    358
    359                sb = new StringBuffer( 1000 );
    360                Operation op1 = createOperation( OperationDefines.PROPERTYISEQUALTO, cf[0], id );
    361                sb.append( op1.toXML() );
    362            }
    363
    364            return sb.toString();
    365        }
    366
    367        /**
    368         * Build OGC Filterencoding fragment: use <code>CSWRequestmodel</code> field <b>parentIdentifier</b> to create
    369         * Comparison Operation.
    370         *
    371         * @return Returns the fragment for apiiso:type property. May be empty
    372         */
    373        private String handleMetadataType() {
    374
    375            StringBuffer sb = new StringBuffer( 50 );
    376
    377            if ( ( struct.getMember( RPC_MDTYPE ) ) != null ) {
    378                String rpc_mdType = (String) struct.getMember( RPC_MDTYPE ).getValue();
    379                String[] mdTypes = null;
    380                if ( rpc_mdType != null ) {
    381                    mdTypes = rpc_mdType.split( "," );
    382                }
    383
    384                String property = requestElementsProps.getProperty( Constants.CONF_MDTYPE );
    385                if ( mdTypes != null && mdTypes.length > 0 ) {
    386                    if ( mdTypes.length > 1 && mdTypes.length <= 3 ) {
    387                        sb.append( "<ogc:Or>" );
    388                        for ( int i = 0; i < mdTypes.length; i++ ) {
    389
    390                            Operation op = createOperation( OperationDefines.PROPERTYISEQUALTO, property, mdTypes[i] );
    391                            sb.append( op.toXML() );
    392                        }
    393                        sb.append( "</ogc:Or>" );
    394                    } else if ( mdTypes.length == 1 ) {
    395                        Operation op = createOperation( OperationDefines.PROPERTYISEQUALTO, property, mdTypes[0] );
    396                        sb.append( op.toXML() );
    397                    } // else {
    398                    // This block does nothing, I just added it for clarity.
    399                    // This is the case, where the three metadata types are searched and in this case, no type filter
    400                    // shall be added at all
    401                    // Update: since no MD of type service shall be returned, we use the first if condition of this block
    402                    /*
    403                     * Operation op = createOperation( OperationDefines.PROPERTYISLIKE, property, "*" ); sb.append(
    404                     * op.toXML() );
    405                     */
    406                    // }
    407                }
    408            }
    409            return sb.toString();
    410        }
    411
    412        /**
    413         * Build OGC Filterencoding fragment: use <code>CSWRequestmodel</code> field <b>parentIdentifier</b> to create
    414         * Comparison Operation.
    415         *
    416         * @return Returns the fragment for parentIdentifier. May be empty.
    417         */
    418        private String handleParentIdentifier() {
    419
    420            StringBuffer sb = new StringBuffer( 1000 );
    421            String seriesIdentifier = null;
    422            if ( struct.getMember( Constants.RPC_DATASERIES ) != null ) {
    423                seriesIdentifier = (String) struct.getMember( Constants.RPC_DATASERIES ).getValue();
    424            }
    425
    426            if ( ( seriesIdentifier != null ) && ( seriesIdentifier.trim().length() > 0 ) ) {
    427                String cf_props = requestElementsProps.getProperty( Constants.CONF_DATASERIES );
    428                String[] cf = cf_props.split( ";" );
    429
    430                sb = new StringBuffer( 1000 );
    431                Operation op1 = createOperation( OperationDefines.PROPERTYISEQUALTO, cf[0], seriesIdentifier );
    432                sb.append( op1.toXML() );
    433            }
    434
    435            return sb.toString();
    436        }
    437
    438        /**
    439         * Spread <code>CSWRequestmodel</code> field <b>terms</b> to several Comparison Operations with pre-defined
    440         * Property names.
    441         *
    442         * @return Returns the fragment for the search string. May be empty.
    443         */
    444        private String handleSimpleSearch() {
    445
    446            StringBuffer sb = new StringBuffer( 2000 );
    447
    448            String[] keywords = null;
    449            if ( struct.getMember( RPC_SIMPLESEARCH ) != null ) {
    450                String rpcVal = (String) struct.getMember( RPC_SIMPLESEARCH ).getValue();
    451                keywords = StringTools.toArray( rpcVal, ",;|", true );
    452            }
    453
    454            if ( ( keywords != null ) && ( keywords.length > 0 ) ) {
    455                sb.append( "<ogc:Or>" );
    456
    457                for ( int i = 0; i < keywords.length; i++ ) {
    458                    // replace invalid chars
    459                    if ( ( keywords[i] != null ) && ( keywords[i].length() > 0 ) ) {
    460                        keywords[i] = StringTools.replace( keywords[i], "'", " ", true );
    461                        keywords[i] = StringTools.replace( keywords[i], "\"", " ", true );
    462
    463                        // determine the way to build FilterEncoding part
    464                        String cf_props = requestElementsProps.getProperty( Constants.CONF_SIMPLESEARCH );
    465                        String[] cf = cf_props.split( ";" );
    466                        for ( int k = 0; k < cf.length; k++ ) {
    467                            String strOp = keywords[i];
    468
    469                            if ( ( strOp != null ) && ( strOp.length() > 0 ) ) {
    470                                // LOWERCASE SECTION
    471                                strOp = strOp.substring( 0, 1 ).toLowerCase() + strOp.substring( 1 );
    472                                Operation op = createOperation( OperationDefines.PROPERTYISLIKE, cf[k], strOp );
    473                                sb.append( op.toXML() );
    474
    475                                // FIRST LETTER UPPERCASE SECTION
    476                                strOp = strOp.substring( 0, 1 ).toUpperCase() + strOp.substring( 1 );
    477                                op = createOperation( OperationDefines.PROPERTYISLIKE, cf[k], strOp );
    478                                sb.append( op.toXML() );
    479                            }
    480                        }
    481                    }
    482                }
    483                sb.append( "</ogc:Or>" );
    484            }
    485
    486            return sb.toString();
    487        }
    488
    489        /**
    490         * Builds OGC Filterencoding fragment: for <code>CSWRequestmodel</code> field <b>topiccategory</b>.
    491         *
    492         * @return Returns the fragment for topiccategory. May be null, if no topiccategory is specified.
    493         */
    494        private String handleTopiccategory() {
    495
    496            String rpcVal = null;
    497            if ( struct.getMember( RPC_TOPICCATEGORY ) != null ) {
    498                rpcVal = (String) struct.getMember( RPC_TOPICCATEGORY ).getValue();
    499            }
    500
    501            if ( rpcVal != null && !rpcVal.startsWith( "..." ) && rpcVal.length() > 0 ) {
    502                String cf_props = requestElementsProps.getProperty( Constants.CONF_TOPICCATEGORY );
    503                String[] cf = cf_props.split( ";" );
    504
    505                Operation op1 = createOperation( OperationDefines.PROPERTYISEQUALTO, cf[0], rpcVal );
    506                rpcVal = op1.toXML().toString();
    507            } else {
    508                rpcVal = null;
    509            }
    510
    511            return rpcVal;
    512        }
    513
    514        /**
    515         * Build OGC Filterencoding fragment: Split <code>CSWRequestmodel</code> field <b>keywords</b> to one Comparison
    516         * Operation for each keyword.
    517         *
    518         * @return Returns the fragment for keywords. May be empty, if no keywords are specified.
    519         */
    520        private String handleKeywords() {
    521
    522            StringBuffer sb = new StringBuffer( 1000 );
    523            String[] keywords = null;
    524            if ( struct.getMember( RPC_KEYWORDS ) != null ) {
    525                String s = (String) struct.getMember( RPC_KEYWORDS ).getValue();
    526                keywords = StringTools.toArray( s, ",;", true );
    527            }
    528
    529            if ( ( keywords != null ) && ( keywords.length > 0 ) ) {
    530                String cf_props = requestElementsProps.getProperty( Constants.CONF_KEYWORDS );
    531                String[] cf = cf_props.split( ";" );
    532
    533                sb = new StringBuffer( 1000 );
    534                int i = 0;
    535
    536                for ( i = 0; i < keywords.length; i++ ) {
    537                    if ( keywords[i].trim().length() > 0 ) {
    538                        Operation op1 = createOperation( OperationDefines.PROPERTYISEQUALTO, cf[0], keywords[i] );
    539                        sb.append( op1.toXML() );
    540                    }
    541                }
    542
    543                if ( i > 1 ) {
    544                    sb.insert( 0, "<ogc:Or>" );
    545                    sb.append( "</ogc:Or>" );
    546                }
    547            }
    548
    549            return sb.toString();
    550        }
    551
    552        /**
    553         * Build OGC Filterencoding fragment: use <code>dateFrom</code> and <code>dateTo</code> to create Comparison
    554         * Operations.
    555         *
    556         * @return Returns the fragment for dates specified in the <code>RPCStruct</code>. May be null, if no dates are
    557         *         specified.
    558         */
    559        private String handleDate() {
    560
    561            String s = null;
    562
    563            if ( struct.getMember( Constants.RPC_DATEFROM ) == null && struct.getMember( Constants.RPC_DATETO ) == null ) {
    564                return s;
    565            }
    566
    567            // RPC_DATEFROM
    568            String fromYear = null;
    569            String fromMonth = null;
    570            String fromDay = null;
    571
    572            if ( struct.getMember( Constants.RPC_DATEFROM ) != null ) {
    573                RPCStruct st = (RPCStruct) struct.getMember( Constants.RPC_DATEFROM ).getValue();
    574                if ( st.getMember( Constants.RPC_YEAR ) != null ) {
    575                    fromYear = st.getMember( Constants.RPC_YEAR ).getValue().toString();
    576                }
    577                if ( st.getMember( Constants.RPC_MONTH ) != null ) {
    578                    fromMonth = st.getMember( Constants.RPC_MONTH ).getValue().toString();
    579                }
    580                if ( st.getMember( Constants.RPC_DAY ) != null ) {
    581                    fromDay = st.getMember( Constants.RPC_DAY ).getValue().toString();
    582                }
    583            }
    584
    585            if ( fromYear == null ) {
    586                fromYear = "0000";
    587            }
    588            if ( fromMonth == null ) {
    589                fromMonth = "1";
    590            }
    591            if ( Integer.parseInt( fromMonth ) < 10 ) {
    592                fromMonth = "0" + Integer.parseInt( fromMonth );
    593            }
    594            if ( fromDay == null ) {
    595                fromDay = "1";
    596            }
    597            if ( Integer.parseInt( fromDay ) < 10 ) {
    598                fromDay = "0" + Integer.parseInt( fromDay );
    599            }
    600            String dateFrom = fromYear + "-" + fromMonth + "-" + fromDay;
    601
    602            // RPC_DATETO
    603            String toYear = null;
    604            String toMonth = null;
    605            String toDay = null;
    606
    607            if ( struct.getMember( Constants.RPC_DATETO ) != null ) {
    608                RPCStruct st = (RPCStruct) struct.getMember( Constants.RPC_DATETO ).getValue();
    609                if ( st.getMember( Constants.RPC_YEAR ) != null ) {
    610                    toYear = st.getMember( Constants.RPC_YEAR ).getValue().toString();
    611                }
    612                if ( st.getMember( Constants.RPC_MONTH ) != null ) {
    613                    toMonth = st.getMember( Constants.RPC_MONTH ).getValue().toString();
    614                }
    615                if ( st.getMember( Constants.RPC_DAY ) != null ) {
    616                    toDay = st.getMember( Constants.RPC_DAY ).getValue().toString();
    617                }
    618            }
    619
    620            if ( toYear == null ) {
    621                toYear = "9999";
    622            }
    623            if ( toMonth == null ) {
    624                toMonth = "12";
    625            }
    626            if ( Integer.parseInt( toMonth ) < 10 ) {
    627                toMonth = "0" + Integer.parseInt( toMonth );
    628            }
    629            if ( toDay == null ) {
    630                toDay = "31";
    631            }
    632            if ( Integer.parseInt( toDay ) < 10 ) {
    633                toDay = "0" + Integer.parseInt( toDay );
    634            }
    635            String dateTo = toYear + "-" + toMonth + "-" + toDay;
    636
    637            String date_props = requestElementsProps.getProperty( Constants.CONF_DATE );
    638            String[] conf_date = date_props.split( ";" );
    639
    640            if ( ( toYear != null ) && ( toYear.length() > 0 ) ) {
    641                StringBuffer sb = new StringBuffer( "<ogc:And>" );
    642
    643                Operation op1 = null;
    644                op1 = createOperation( OperationDefines.PROPERTYISGREATERTHANOREQUALTO, conf_date[0], dateFrom );
    645                sb.append( op1.toXML() );
    646                op1 = createOperation( OperationDefines.PROPERTYISLESSTHANOREQUALTO, conf_date[0], dateTo );
    647                sb.append( op1.toXML() );
    648
    649                sb.append( "</ogc:And>" );
    650                s = sb.toString();
    651            }
    652
    653            return s;
    654        }
    655
    656        /**
    657         * Build OGC Filterencoding fragment: use <code>CSWRequestmodel</code> field <b>geographicBox</b> to create
    658         * Comparison Operation.
    659         *
    660         * @return Returns the fragment for the geographic bounding box. May be empty, if no bounding box is specified.
    661         * @throws CatalogClientException
    662         * @throws UnknownCRSException
    663         */
    664        private String handleBbox()
    665                                throws CatalogClientException, UnknownCRSException {
    666
    667            StringBuffer sb = new StringBuffer( 1000 );
    668            if ( struct.getMember( Constants.RPC_BBOX ) != null ) {
    669                RPCStruct bboxStruct = (RPCStruct) struct.getMember( Constants.RPC_BBOX ).getValue();
    670
    671                Double minx = (Double) bboxStruct.getMember( Constants.RPC_BBOXMINX ).getValue();
    672                Double miny = (Double) bboxStruct.getMember( Constants.RPC_BBOXMINY ).getValue();
    673                Double maxx = (Double) bboxStruct.getMember( Constants.RPC_BBOXMAXX ).getValue();
    674                Double maxy = (Double) bboxStruct.getMember( Constants.RPC_BBOXMAXY ).getValue();
    675
    676                // FIXME check if srs is correct
    677                CoordinateSystem srs = CRSFactory.create( config.getSrs() );
    678                Envelope bbox = GeometryFactory.createEnvelope( minx.doubleValue(), miny.doubleValue(), maxx.doubleValue(),
    679                                                                maxy.doubleValue(), srs );
    680                try {
    681                    // transform request boundingbox to EPSG:4326 because a ISO 19115
    682                    // compliant catalog must store the bbox of an entry like this
    683                    GeoTransformer geoTransformer = new GeoTransformer( "EPSG:4326" );
    684                    bbox = geoTransformer.transform( bbox, config.getSrs() );
    685
    686                } catch ( Exception e ) {
    687                    throw new CatalogClientException( e.toString() );
    688                }
    689
    690                Geometry boxGeom = null;
    691                try {
    692                    boxGeom = GeometryFactory.createSurface( bbox, srs );
    693                } catch ( GeometryException e ) {
    694                    throw new CatalogClientException( Messages.getMessage( "IGEO_STD_CSW_ERROR_CREATE_SURFACE",
    695                                                                           e.getMessage() ) );
    696                }
    697
    698                String property = requestElementsProps.getProperty( Constants.CONF_GEOGRAPHICBOX );
    699                String[] re = property.split( ";" );
    700
    701                if ( boxGeom != null ) {
    702                    Operation op1 = createOperation( OperationDefines.BBOX, re[0], boxGeom );
    703                    sb.append( op1.toXML() );
    704                }
    705            }
    706
    707            return sb.toString();
    708        }
    709
    710        // /**
    711        // * @param bbox The bounding box to be used as filter condition.
    712        // * @return Returns the GML bounding box snippet.
    713        // */
    714        // private String createGMLBox( Envelope bbox ) {
    715        // StringBuffer sb = new StringBuffer( 1000 );
    716        //
    717        // sb.append( "<gml:Box xmlns:gml=\"http://www.opengis.net/gml\" >" );
    718        // sb.append( "<gml:coord><gml:X>" );
    719        // sb.append( "" + bbox.getMin().getX() );
    720        // sb.append( "</gml:X><gml:Y>" );
    721        // sb.append( "" + bbox.getMin().getY() );
    722        // sb.append( "</gml:Y></gml:coord><gml:coord><gml:X>" );
    723        // sb.append( "" + bbox.getMax().getX() );
    724        // sb.append( "</gml:X><gml:Y>" );
    725        // sb.append( "" + bbox.getMax().getY() );
    726        // sb.append( "</gml:Y></gml:coord></gml:Box>" );
    727        //
    728        // return sb.toString();
    729        // }
    730
    731        /**
    732         * @param opId
    733         * @param property
    734         * @param value
    735         * @return Returns the operation to create.
    736         */
    737        private Operation createOperation( int opId, String property, Object value ) {
    738
    739            Operation op = null;
    740
    741            switch ( opId ) {
    742            case OperationDefines.PROPERTYISEQUALTO:
    743                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISEQUALTO,
    744                                                  new PropertyName( new QualifiedName( property ) ),
    745                                                  new Literal( (String) value ) );
    746                break;
    747            case OperationDefines.PROPERTYISLIKE:
    748
    749                char wildCard = WILDCARD;
    750                char singleChar = '?';
    751                char escapeChar = '/';
    752                String lit = wildCard + (String) value + wildCard;
    753                op = new PropertyIsLikeOperation( new PropertyName( new QualifiedName( property ) ), new Literal( lit ),
    754                                                  wildCard, singleChar, escapeChar );
    755                break;
    756            case OperationDefines.PROPERTYISLESSTHANOREQUALTO:
    757                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISLESSTHANOREQUALTO,
    758                                                  new PropertyName( new QualifiedName( property ) ),
    759                                                  new Literal( (String) value ) );
    760                break;
    761            case OperationDefines.PROPERTYISGREATERTHANOREQUALTO:
    762                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISGREATERTHANOREQUALTO,
    763                                                  new PropertyName( new QualifiedName( property ) ),
    764                                                  new Literal( (String) value ) );
    765                break;
    766            case OperationDefines.BBOX:
    767                op = new SpatialOperation( OperationDefines.BBOX, new PropertyName( new QualifiedName( property ) ),
    768                                           (Geometry) value );
    769                break;
    770            case OperationDefines.PROPERTYISNULL:
    771                op = new PropertyIsNullOperation( new PropertyName( new QualifiedName( property ) ) );
    772                break;
    773            default:
    774                op = new PropertyIsCOMPOperation( OperationDefines.PROPERTYISEQUALTO,
    775                                                  new PropertyName( new QualifiedName( property ) ),
    776                                                  new Literal( (String) value ) );
    777            }
    778
    779            return op;
    780        }
    781
    782    }