001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/owscommon_1_1_0/CommonsDocument.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.owscommon_1_1_0; 038 039 import static org.deegree.framework.xml.XMLTools.getElement; 040 import static org.deegree.framework.xml.XMLTools.getElements; 041 import static org.deegree.framework.xml.XMLTools.getNodeAsString; 042 import static org.deegree.framework.xml.XMLTools.getNodesAsStringList; 043 import static org.deegree.framework.xml.XMLTools.getRequiredElement; 044 import static org.deegree.framework.xml.XMLTools.getRequiredNodeAsString; 045 import static org.deegree.ogcbase.CommonNamespaces.XLINK_PREFIX; 046 047 import java.util.ArrayList; 048 import java.util.List; 049 050 import org.deegree.framework.log.ILogger; 051 import org.deegree.framework.log.LoggerFactory; 052 import org.deegree.framework.util.Pair; 053 import org.deegree.framework.xml.XMLFragment; 054 import org.deegree.framework.xml.XMLParsingException; 055 import org.deegree.framework.xml.XMLTools; 056 import org.deegree.ogcbase.CommonNamespaces; 057 import org.w3c.dom.Document; 058 import org.w3c.dom.Element; 059 060 /** 061 * <code>CommonsDocument</code> supplies helper methods for all common ows (version 1.1.0) xml elements. 062 * 063 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a> 064 * 065 * @author last edited by: $Author: mschneider $ 066 * 067 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 068 * 069 */ 070 public class CommonsDocument extends XMLFragment { 071 072 private static ILogger LOG = LoggerFactory.getLogger( CommonsDocument.class ); 073 074 /** 075 * 076 */ 077 private static final long serialVersionUID = -7211342372381557201L; 078 079 /** 080 * The ows 1.1 prefix with a ':' (colon) suffix. 081 */ 082 protected static String PRE_OWS = CommonNamespaces.OWS_1_1_0PREFIX + ":"; 083 084 /** 085 * @param operationElements 086 * to be parsed. 087 * @return a list of operations which may be empty but never <code>null</code> 088 * @throws XMLParsingException 089 */ 090 protected List<Operation> parseOperations( List<Element> operationElements ) 091 throws XMLParsingException { 092 if ( operationElements == null || operationElements.size() < 2 ) { 093 throw new XMLParsingException( "At least two " + PRE_OWS + "operations must be defined in the " + PRE_OWS 094 + "OperationMetadata element." ); 095 } 096 List<Operation> operations = new ArrayList<Operation>( operationElements.size() ); 097 for ( Element op : operationElements ) { 098 /** 099 * from owsOperationsMetadata<br/> Unordered list of Distributed Computing Platforms (DCPs) supported for 100 * this operation. At present, only the HTTP DCP is defined, so this element will appear only once. 101 */ 102 Element dcp = getRequiredElement( op, PRE_OWS + "DCP", nsContext ); 103 Element http = getRequiredElement( dcp, PRE_OWS + "HTTP", nsContext ); 104 List<Element> getters = getElements( http, PRE_OWS + "Get", nsContext ); 105 List<Pair<String, List<DomainType>>> getURLs = new ArrayList<Pair<String, List<DomainType>>>(); 106 if ( getters != null && getters.size() > 0 ) { 107 for ( Element get : getters ) { 108 Pair<String, List<DomainType>> t = parseHTTPChild( get ); 109 if ( t != null ) { 110 getURLs.add( t ); 111 } 112 } 113 } 114 115 List<Element> posts = getElements( http, PRE_OWS + "Post", nsContext ); 116 List<Pair<String, List<DomainType>>> postURLs = new ArrayList<Pair<String, List<DomainType>>>(); 117 if ( posts != null && posts.size() > 0 ) { 118 for ( Element post : posts ) { 119 Pair<String, List<DomainType>> t = parseHTTPChild( post ); 120 if ( t != null ) { 121 postURLs.add( t ); 122 } 123 } 124 } 125 126 List<Element> params = getElements( op, PRE_OWS + "Parameter", nsContext ); 127 List<DomainType> parameters = new ArrayList<DomainType>(); 128 if ( params != null && params.size() > 0 ) { 129 for ( Element param : params ) { 130 DomainType t = parseDomainType( param ); 131 if ( t != null ) { 132 parameters.add( t ); 133 } 134 } 135 } 136 137 List<Element> consts = getElements( op, PRE_OWS + "Constraint", nsContext ); 138 List<DomainType> constraints = new ArrayList<DomainType>(); 139 if ( params != null && params.size() > 0 ) { 140 for ( Element ce : consts ) { 141 DomainType t = parseDomainType( ce ); 142 if ( t != null ) { 143 constraints.add( t ); 144 } 145 } 146 } 147 List<Metadata> metadataAttribs = parseMetadatas( getElements( op, PRE_OWS + "MetaData", nsContext ) ); 148 String name = getRequiredNodeAsString( op, "@name", nsContext ); 149 operations.add( new Operation( getURLs, postURLs, parameters, constraints, metadataAttribs, name ) ); 150 } 151 return operations; 152 } 153 154 /** 155 * parses the post or get information beneath a http element. 156 * 157 * @param getOrPost 158 * @return the pair containing the xlink, list<contraint>. or <code>null</code> if attribute and elements 159 * were not found. 160 * @throws XMLParsingException 161 */ 162 163 protected Pair<String, List<DomainType>> parseHTTPChild( Element getOrPost ) 164 throws XMLParsingException { 165 if ( getOrPost == null ) { 166 return null; 167 } 168 String httpURL = getNodeAsString( getOrPost, "@" + XLINK_PREFIX + ":href", nsContext, null ); 169 List<DomainType> getConstraints = null; 170 171 List<Element> getConstElements = getElements( getOrPost, PRE_OWS + "Constraint", nsContext ); 172 if ( getConstElements != null && getConstElements.size() > 0 ) { 173 for ( Element gce : getConstElements ) { 174 DomainType getConstraint = parseDomainType( gce ); 175 if ( getConstraint != null ) { 176 // create a list instance. 177 if ( getConstraints == null ) { 178 getConstraints = new ArrayList<DomainType>( getConstElements.size() ); 179 } 180 getConstraints.add( getConstraint ); 181 } 182 } 183 } 184 if ( getConstraints != null || httpURL != null ) { 185 return new Pair<String, List<DomainType>>( httpURL, getConstraints ); 186 } 187 return null; 188 } 189 190 /** 191 * @param domainType 192 * to parse 193 * @return a bean representation of the domainType or <code>null</code> if given element is <code>null</code>. 194 * @throws XMLParsingException 195 */ 196 protected DomainType parseDomainType( Element domainType ) 197 throws XMLParsingException { 198 if ( domainType == null ) { 199 return null; 200 } 201 boolean allowedValues = getElement( domainType, PRE_OWS + "AllowedValues", nsContext ) != null; 202 List<String> values = null; 203 List<Range> ranges = null; 204 if ( allowedValues ) { 205 values = getNodesAsStringList( domainType, PRE_OWS + "AllowedValues/" + PRE_OWS + "Value", nsContext ); 206 ranges = parseRanges( getElements( domainType, PRE_OWS + "AllowedValues/" + PRE_OWS + "Range", nsContext ) ); 207 if ( ( values == null || values.size() == 0 ) && ( ranges == null || ranges.size() == 0 ) ) { 208 throw new XMLParsingException( "One of the following values must be defined in an " + PRE_OWS 209 + "AllowedValues: - " + PRE_OWS + "Values or " + PRE_OWS + "Range" ); 210 } 211 } 212 boolean anyValue = getElement( domainType, PRE_OWS + "AnyValue", nsContext ) != null; 213 boolean noValues = getElement( domainType, PRE_OWS + "NoValues", nsContext ) != null; 214 Pair<String, String> valuesReference = parseDomainMetadataType( getElement( domainType, PRE_OWS 215 + "ValuesReference", 216 nsContext ) ); 217 if ( valuesReference != null && valuesReference.second == null ) { 218 throw new XMLParsingException( "The reference attribute of the " + PRE_OWS + "DomatainType/" + PRE_OWS 219 + "ValuesReference must be set." ); 220 } 221 if ( !( allowedValues || anyValue || noValues || valuesReference != null ) ) { 222 throw new XMLParsingException( "One of the following values must be defined in an " + PRE_OWS 223 + "DomainType: - " + PRE_OWS + "AllowedValues, " + PRE_OWS + "AnyValue, " 224 + PRE_OWS + "NoValues or " + PRE_OWS + "ValuesReference" ); 225 } 226 String defaultValue = getNodeAsString( domainType, PRE_OWS + "DefaultValue", nsContext, null ); 227 Pair<String, String> meaning = parseDomainMetadataType( getElement( domainType, PRE_OWS + "Meaning", nsContext ) ); 228 Pair<String, String> dataType = parseDomainMetadataType( getElement( domainType, PRE_OWS + "DataType", 229 nsContext ) ); 230 Element valuesUnit = getElement( domainType, PRE_OWS + "ValuesUnit", nsContext ); 231 Pair<String, String> uom = null; 232 Pair<String, String> referenceSystem = null; 233 if ( valuesUnit != null ) { 234 uom = parseDomainMetadataType( getElement( valuesUnit, PRE_OWS + "UOM", nsContext ) ); 235 referenceSystem = parseDomainMetadataType( getElement( valuesUnit, PRE_OWS + "ReferenceSystem", nsContext ) ); 236 if ( uom == null && referenceSystem == null ) { 237 throw new XMLParsingException( "Either " + PRE_OWS + "UOM or " + PRE_OWS 238 + "ReferenceSystem are required in a " + PRE_OWS + "ValuesUnit element." ); 239 } 240 } 241 List<Metadata> metadataAttribs = parseMetadatas( getElements( domainType, PRE_OWS + "MetaData", nsContext ) ); 242 243 String name = getRequiredNodeAsString( domainType, "@name", nsContext ); 244 245 return new DomainType( values, ranges, anyValue, noValues, valuesReference, defaultValue, meaning, dataType, 246 uom, referenceSystem, metadataAttribs, name ); 247 248 } 249 250 /** 251 * @param metadataElements 252 * to be parsed. 253 * @return a List of pairs of optional <xlink:href, about> attributes, or an empty list <code>null</code> if 254 * no elements were found. 255 */ 256 protected List<Metadata> parseMetadatas( List<Element> metadataElements ) { 257 if ( metadataElements == null || metadataElements.size() == 0 ) { 258 return null; 259 } 260 List<Metadata> result = new ArrayList<Metadata>( metadataElements.size() ); 261 for ( Element mde : metadataElements ) { 262 263 try { 264 Metadata md = parseMetadata( mde ); 265 if ( md != null ) { 266 result.add( md ); 267 } 268 } catch ( XMLParsingException e ) { 269 LOG.logError( e ); 270 } 271 272 } 273 if ( result.size() == 0 ) { 274 return null; 275 } 276 return result; 277 278 } 279 280 /** 281 * @param metadataElement 282 * to be parsed. 283 * @return the pair of optional <xlink:href, about> attributes. 284 * @throws XMLParsingException 285 * if the abstract metadatas could not be parsed. 286 */ 287 protected Metadata parseMetadata( Element metadataElement ) 288 throws XMLParsingException { 289 if ( metadataElement == null ) { 290 return null; 291 } 292 String metadataHref = metadataElement.getAttributeNS( CommonNamespaces.XLNNS.toASCIIString(), ":href" ); 293 metadataHref = "".equals( metadataHref ) ? null : metadataHref; 294 String metadataAbout = metadataElement.getAttribute( "about" ); 295 metadataAbout = "".equals( metadataAbout ) ? null : metadataAbout; 296 Element abstractElement = getElement( metadataElement, "*[1]", nsContext ); 297 Element result = null; 298 if ( abstractElement != null ) { 299 Document doc = XMLTools.create(); 300 Element t = (Element) doc.importNode( abstractElement, true ); 301 result = (Element) doc.appendChild( t ); 302 } 303 if ( metadataAbout != null || metadataHref != null || result != null ) { 304 return new Metadata( metadataHref, metadataAbout, result ); 305 } 306 return null; 307 } 308 309 /** 310 * Parses the domain metadata type and it's reference attribute and puts them in a pair, like name, reference, which 311 * may be null 312 * 313 * @param domainMDElements 314 * @return a list of pairs containing the values or <code>null</code> if given list is <code>null</code> or it 315 * does not contain any domain elements value. 316 * @throws XMLParsingException 317 */ 318 protected List<Pair<String, String>> parseDomainMetadataTypes( List<Element> domainMDElements ) 319 throws XMLParsingException { 320 if ( domainMDElements == null || domainMDElements.size() == 0 ) { 321 return null; 322 } 323 List<Pair<String, String>> domainMDTypes = new ArrayList<Pair<String, String>>( domainMDElements.size() ); 324 for ( Element mdT : domainMDElements ) { 325 Pair<String, String> t = parseDomainMetadataType( mdT ); 326 if ( t != null ) { 327 domainMDTypes.add( t ); 328 } 329 } 330 return ( domainMDTypes.size() == 0 ) ? null : domainMDTypes; 331 } 332 333 /** 334 * Parses the domain metadata type and it's reference attribute and puts them in a pair, like name, reference, the 335 * latter may be null 336 * 337 * @param domainMDElement 338 * to parse 339 * @return a pair containing the values or <code>null</code> if given element is null or it does not contain a 340 * value. 341 * @throws XMLParsingException 342 */ 343 protected Pair<String, String> parseDomainMetadataType( Element domainMDElement ) 344 throws XMLParsingException { 345 if ( domainMDElement == null ) { 346 return null; 347 } 348 String valuesReference = getNodeAsString( domainMDElement, ".", nsContext, null ); 349 String reference = getNodeAsString( domainMDElement, "@reference", nsContext, null ); 350 if ( valuesReference != null ) { 351 return new Pair<String, String>( valuesReference, reference ); 352 } 353 return null; 354 } 355 356 /** 357 * @param rangeElements 358 * @return the ranges or <code>null</code> if no elements were given. 359 * @throws XMLParsingException 360 */ 361 private List<Range> parseRanges( List<Element> rangeElements ) 362 throws XMLParsingException { 363 if ( rangeElements == null || rangeElements.size() == 0 ) { 364 return null; 365 } 366 List<Range> ranges = new ArrayList<Range>( rangeElements.size() ); 367 for ( Element range : rangeElements ) { 368 String minimumValue = getNodeAsString( range, PRE_OWS + "Range/" + PRE_OWS + "MinimumValue", nsContext, 369 null ); 370 String maximumValue = getNodeAsString( range, PRE_OWS + "Range/" + PRE_OWS + "MaximumValue", nsContext, 371 null ); 372 String spacing = getNodeAsString( range, PRE_OWS + "Range/" + PRE_OWS + "Spacing", nsContext, null ); 373 String rangeClosure = getNodeAsString( range, PRE_OWS + "Range/@rangeClosure", nsContext, "closed" ); 374 ranges.add( new Range( minimumValue, maximumValue, spacing, rangeClosure ) ); 375 } 376 return ranges; 377 } 378 379 /** 380 * @param serviceContact 381 * @return the service contact bean 382 * @throws XMLParsingException 383 */ 384 protected ServiceContact parseServiceContact( Element serviceContact ) 385 throws XMLParsingException { 386 String individualName = getNodeAsString( serviceContact, PRE_OWS + "IndividualName", nsContext, null ); 387 String positionName = getNodeAsString( serviceContact, PRE_OWS + "PositionName", nsContext, null ); 388 ContactInfo contactInfo = parseContactInfo( getElement( serviceContact, PRE_OWS + "ContactInfo", nsContext ) ); 389 Pair<String, String> role = null; 390 String roleS = getNodeAsString( serviceContact, PRE_OWS + "Role", nsContext, null ); 391 if ( roleS != null ) { 392 role = new Pair<String, String>( roleS, getNodeAsString( serviceContact, PRE_OWS + "Role/@codeSpace", 393 nsContext, null ) ); 394 } 395 return new ServiceContact( individualName, positionName, contactInfo, role ); 396 } 397 398 /** 399 * @param contactInfo 400 * @return the contactinfo or <code>null</code> if all underlying elements are empty. 401 * @throws XMLParsingException 402 */ 403 protected ContactInfo parseContactInfo( Element contactInfo ) 404 throws XMLParsingException { 405 if ( contactInfo == null ) { 406 return null; 407 } 408 409 Pair<List<String>, List<String>> phone = null; 410 Element phoneElement = getElement( contactInfo, PRE_OWS + "Phone", nsContext ); 411 if ( phoneElement != null ) { 412 phone = new Pair<List<String>, List<String>>( getNodesAsStringList( phoneElement, PRE_OWS + "Voice", 413 nsContext ), 414 getNodesAsStringList( phoneElement, PRE_OWS + "Facsimile", 415 nsContext ) ); 416 } 417 418 List<String> deliveryPoint = null; 419 String city = null; 420 String administrativeArea = null; 421 String postalCode = null; 422 String country = null; 423 List<String> electronicMailAddress = null; 424 Element address = getElement( contactInfo, PRE_OWS + "Address", nsContext ); 425 boolean hasAdress = false; 426 if ( address != null ) { 427 deliveryPoint = getNodesAsStringList( address, PRE_OWS + "DeliveryPoint", nsContext ); 428 city = getNodeAsString( address, PRE_OWS + "City", nsContext, null ); 429 administrativeArea = getNodeAsString( address, PRE_OWS + "AdministrativeArea", nsContext, null ); 430 postalCode = getNodeAsString( address, PRE_OWS + "PostalCode", nsContext, null ); 431 country = getNodeAsString( address, PRE_OWS + "Country", nsContext, null ); 432 electronicMailAddress = getNodesAsStringList( address, PRE_OWS + "ElectronicMailAddress", nsContext ); 433 if ( electronicMailAddress.size() == 0 ) { 434 electronicMailAddress = null; 435 } 436 hasAdress = ( deliveryPoint != null || city != null || administrativeArea != null || postalCode != null 437 || country != null || electronicMailAddress != null ); 438 } 439 440 String onlineResource = getNodeAsString( contactInfo, PRE_OWS + "OnlineResource/@" + XLINK_PREFIX + ":href", 441 nsContext, null ); 442 String hoursOfService = getNodeAsString( contactInfo, PRE_OWS + "HoursOfService", nsContext, null ); 443 String contactInstructions = getNodeAsString( contactInfo, PRE_OWS + "ContactInstructions", nsContext, null ); 444 if ( ( phone != null ) && !hasAdress && onlineResource == null && hoursOfService == null 445 && contactInstructions == null ) { 446 return null; 447 } 448 return new ContactInfo( phone, hasAdress, deliveryPoint, city, administrativeArea, postalCode, country, 449 electronicMailAddress, onlineResource, hoursOfService, contactInstructions ); 450 } 451 452 /** 453 * @param basicIdentificationType 454 * to be parsed. 455 * @return the {@link BasicIdentification} bean representation or <code>null</code> if the given element is 456 * <code>null</code>. 457 * @throws XMLParsingException 458 * if the given param can not be parsed. 459 */ 460 protected BasicIdentification parseBasicIdentificationType( Element basicIdentificationType ) 461 throws XMLParsingException { 462 if ( basicIdentificationType == null ) { 463 return null; 464 } 465 List<String> title = getNodesAsStringList( basicIdentificationType, PRE_OWS + "Title", nsContext ); 466 List<String> abstracts = getNodesAsStringList( basicIdentificationType, PRE_OWS + "Abstract", nsContext ); 467 List<Element> kws = getElements( basicIdentificationType, PRE_OWS + "Keywords", nsContext ); 468 // Pair<List<keywords>, codetype> 469 List<Keywords> keywords = new ArrayList<Keywords>( ( ( kws == null ) ? 0 : kws.size() ) ); 470 if ( kws != null ) { 471 for ( Element keyword : kws ) { 472 keywords.add( parseKeywords( keyword ) ); 473 } 474 } 475 Pair<String, String> identifier = parseIdentifier( basicIdentificationType ); 476 List<Metadata> metadatas = parseMetadatas( getElements( basicIdentificationType, PRE_OWS + "Metadata", 477 nsContext ) ); 478 return new BasicIdentification( title, abstracts, keywords, identifier, metadatas ); 479 } 480 481 /** 482 * @param root 483 * element to be parsed for the identifier. 484 * @return a <value, codeSpace> pair or <code>null</code> if the given element is <code>null</code> or if 485 * the identifier has no value and codeSpace. 486 * @throws XMLParsingException 487 */ 488 protected Pair<String, String> parseIdentifier( Element root ) 489 throws XMLParsingException { 490 if ( root == null ) { 491 return null; 492 } 493 Pair<String, String> identifier = null; 494 Element id = getElement( root, PRE_OWS + "Identifier", nsContext ); 495 if ( id != null ) { 496 String value = getNodeAsString( id, ".", nsContext, "" ); 497 String codeSpace = id.getAttribute( "codeSpace" ); 498 if ( !"".equals( value ) || !"".equals( codeSpace.trim() ) ) { 499 identifier = new Pair<String, String>( value, codeSpace ); 500 } 501 } 502 return identifier; 503 } 504 505 /** 506 * Return the ows_1_1_0 keywords.. 507 * 508 * @param keywords 509 * element to parse from 510 * @return a <List<Keywords>,Type> pair. 511 * @throws XMLParsingException 512 */ 513 protected Keywords parseKeywords( Element keywords ) 514 throws XMLParsingException { 515 if ( keywords == null ) { 516 return null; 517 } 518 String codetype = getNodeAsString( keywords, PRE_OWS + "Type", nsContext, null ); 519 String typeSpace = null; 520 Pair<String, String> type = null; 521 if ( codetype != null ) { 522 typeSpace = getNodeAsString( keywords, PRE_OWS + "Type/@codeSpace", nsContext, null ); 523 type = new Pair<String, String>( codetype, typeSpace ); 524 } 525 return new Keywords( getNodesAsStringList( keywords, PRE_OWS + "Keyword", nsContext ), type ); 526 527 } 528 529 }