001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }