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