001 // $HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wcs/configuration/ExtensionDocument.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2007 by: 006 EXSE, 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 53115 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.ogcwebservices.wcs.configuration; 045 046 import java.io.File; 047 import java.net.MalformedURLException; 048 import java.net.URI; 049 import java.net.URISyntaxException; 050 import java.net.URL; 051 052 import org.deegree.datatypes.values.Interval; 053 import org.deegree.datatypes.values.TypedLiteral; 054 import org.deegree.framework.log.ILogger; 055 import org.deegree.framework.log.LoggerFactory; 056 import org.deegree.framework.util.StringTools; 057 import org.deegree.framework.xml.ElementList; 058 import org.deegree.framework.xml.NamespaceContext; 059 import org.deegree.framework.xml.XMLFragment; 060 import org.deegree.framework.xml.XMLParsingException; 061 import org.deegree.framework.xml.XMLTools; 062 import org.deegree.io.IODocument; 063 import org.deegree.io.JDBCConnection; 064 import org.deegree.model.crs.CRSFactory; 065 import org.deegree.model.crs.CoordinateSystem; 066 import org.deegree.model.crs.UnknownCRSException; 067 import org.deegree.model.spatialschema.Envelope; 068 import org.deegree.model.spatialschema.GMLGeometryAdapter; 069 import org.deegree.ogcbase.CommonNamespaces; 070 import org.deegree.ogcbase.InvalidGMLException; 071 import org.deegree.ogcwebservices.InvalidParameterValueException; 072 import org.w3c.dom.Element; 073 import org.w3c.dom.Node; 074 075 /** 076 * This class creates a class representation of the Extension section of a deegree WCS coverage 077 * offering (coverage configuration) element. the extension section contains informations about data 078 * access/sources for different resolutions and ranges.<BR> 079 * an extension section must contain at least one Resolution element but can contains as much as the 080 * user may defined. A resoluton contains a access informations for data and the ranges the data are 081 * assigned to. because of this it is possible that more than one Resoultion element with same 082 * resolution range but with different other ranges (e.g. time or elevation) 083 * 084 * @version $Revision: 6939 $ 085 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 086 * @author last edited by: $Author: apoth $ 087 * 088 * @version 1.0. $Revision: 6939 $, $Date: 2007-05-08 20:31:12 +0200 (Di, 08 Mai 2007) $ 089 * 090 * @since 1.1 091 */ 092 public class ExtensionDocument { 093 094 private static final ILogger LOG = LoggerFactory.getLogger( ExtensionDocument.class ); 095 096 private static URI GMLNS = CommonNamespaces.GMLNS; 097 098 private static URI DGRNS = CommonNamespaces.DEEGREEWCS; 099 100 private static NamespaceContext nsc = CommonNamespaces.getNamespaceContext(); 101 102 private URL systemId = null; 103 104 private Element root = null; 105 106 /** 107 * constructing the ExtensionBuilder by passing the root element of a deegree WCS 108 * CoverageOffering Extension. 109 * 110 * @param root 111 */ 112 public ExtensionDocument( Element root, URL systemId ) { 113 this.root = root; 114 this.systemId = systemId; 115 } 116 117 /** 118 * returns the content of the Extension element of te deegree WCS coverage description 119 * (configuration document). the extension section contains informations about data 120 * access/sources for different resolutions and ranges.<BR> 121 * an extension section must contain at least one Resolution element but can contains as much as 122 * the user may defined. A resoluton contains a access informations for data and the ranges the 123 * data are assigned to. because of this it is possible that more than one Resoultion element 124 * with same resolution range but with different other ranges (e.g. time or elevation) 125 * 126 * @return content of the Extension element of te deegree WCS coverage description 127 * @throws InvalidCVExtensionException 128 * @throws UnknownCVExtensionException 129 * @throws InvalidParameterValueException 130 * @throws UnknownCRSException 131 */ 132 public Extension getExtension() 133 throws InvalidCVExtensionException, UnknownCVExtensionException, 134 InvalidParameterValueException, InvalidGMLException, UnknownCRSException { 135 Extension extension = null; 136 try { 137 String type = XMLTools.getRequiredNodeAsString( root, "./@type", nsc ); 138 double offset = XMLTools.getNodeAsDouble( root, "./@offset", nsc, 0 ); 139 double scaleFactor = XMLTools.getNodeAsDouble( root, "./@scaleFactor", nsc, 1 ); 140 ElementList el = XMLTools.getChildElements( "Resolution", DGRNS, root ); 141 Resolution[] resolutions = getResolutions( type, el ); 142 extension = new DefaultExtension( type, resolutions, offset, scaleFactor ); 143 } catch ( XMLParsingException e ) { 144 throw new InvalidCVExtensionException( StringTools.stackTraceToString( e ) ); 145 } 146 return extension; 147 } 148 149 /** 150 * returns the resolutions definitions within the Extension element of the deegree WCS coverage 151 * offering. Each resoultion contains access description for its data and an optional 152 * description of the ranges the data are valid for. 153 * 154 * @param type 155 * @param el 156 * @return resolutions definitions within the Extension element of the deegree WCS coverage 157 * offering 158 * @throws XMLParsingException 159 * @throws InvalidParameterValueException 160 * @throws UnknownCRSException 161 */ 162 private Resolution[] getResolutions( String type, ElementList el ) 163 throws XMLParsingException, InvalidParameterValueException, InvalidGMLException, 164 UnknownCRSException { 165 Resolution[] resolutions = new Resolution[el.getLength()]; 166 for ( int i = 0; i < resolutions.length; i++ ) { 167 resolutions[i] = getResolution( type, el.item( i ) ); 168 } 169 return resolutions; 170 } 171 172 /** 173 * creates an instance of <tt>Resoltuion</tt> from the passed <tt>Element</tt> and the type 174 * of the coverage source. Valid values for type are: 175 * <ul> 176 * <li>shapeIndexed 177 * <li>nameIndexed 178 * <li>file 179 * </ul> 180 * if an unknown typed is passed an <tt>InvalidParameterValueException</tt> will be thrown 181 * 182 * @param type 183 * @param element 184 * @return created Resoltuion 185 * @throws XMLParsingException 186 * @throws UnknownCRSException 187 */ 188 private Resolution getResolution( String type, Element element ) 189 throws XMLParsingException, InvalidParameterValueException, InvalidGMLException, 190 UnknownCRSException { 191 String tmp = XMLTools.getRequiredAttrValue( "min", null, element ); 192 double min = Double.parseDouble( tmp ); 193 tmp = XMLTools.getRequiredAttrValue( "max", null, element ); 194 double max = Double.parseDouble( tmp ); 195 ElementList el = XMLTools.getChildElements( "Range", DGRNS, element ); 196 Range[] ranges = getRanges( el ); 197 Resolution resolution = null; 198 if ( type.equals( "shapeIndexed" ) ) { 199 // TODO 200 // enable more than one shape 201 Element elem = XMLTools.getChildElement( "Shape", DGRNS, element ); 202 Shape shape = getShape( elem ); 203 resolution = new ShapeResolution( min, max, ranges, shape ); 204 } else if ( type.equals( "nameIndexed" ) ) { 205 ElementList ell = XMLTools.getChildElements( "Directory", DGRNS, element ); 206 Directory[] dirs = new Directory[ell.getLength()]; 207 for ( int i = 0; i < dirs.length; i++ ) { 208 dirs[i] = getDirectory( ell.item( i ) ); 209 } 210 resolution = new DirectoryResolution( min, max, ranges, dirs ); 211 } else if ( type.equals( "file" ) ) { 212 ElementList ell = XMLTools.getChildElements( "File", DGRNS, element ); 213 org.deegree.ogcwebservices.wcs.configuration.File[] files = new org.deegree.ogcwebservices.wcs.configuration.File[ell.getLength()]; 214 for ( int i = 0; i < files.length; i++ ) { 215 files[i] = getFile( ell.item( i ) ); 216 } 217 resolution = new FileResolution( min, max, ranges, files ); 218 } else if ( type.equals( "OracleGeoRaster" ) ) { 219 resolution = getOracleGeoRasterResolution( element, min, max, ranges ); 220 221 } else { 222 String msg = StringTools.concat( 200, "type: ", type, " not known ", "by the deegree WCS" ); 223 throw new InvalidParameterValueException( msg ); 224 } 225 return resolution; 226 } 227 228 /** 229 * creates a <tt>OracleGeoRasterResolution</tt> object from the passed element 230 * 231 * @param element 232 * @return <tt>OracleGeoRasterResolution</tt> 233 * @throws XMLParsingException 234 */ 235 private Resolution getOracleGeoRasterResolution( Element element, double min, double max, Range[] ranges ) 236 throws XMLParsingException { 237 Resolution resolution; 238 NamespaceContext nsc = CommonNamespaces.getNamespaceContext(); 239 String xpath = "deegreewcs:OracleGeoRaster/dgjdbc:JDBCConnection"; 240 Node node = XMLTools.getRequiredNode( element, xpath, nsc ); 241 IODocument io = new IODocument( (Element) node ); 242 JDBCConnection jdbc = io.parseJDBCConnection(); 243 xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Table/text()"; 244 String table = XMLTools.getRequiredNodeAsString( element, xpath, nsc ); 245 xpath = "deegreewcs:OracleGeoRaster/deegreewcs:RDTTable/text()"; 246 String rdtTable = XMLTools.getRequiredNodeAsString( element, xpath, nsc ); 247 xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Column/text()"; 248 String column = XMLTools.getRequiredNodeAsString( element, xpath, nsc ); 249 xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Identification/text()"; 250 String identification = XMLTools.getRequiredNodeAsString( element, xpath, nsc ); 251 xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Level/text()"; 252 int level = XMLTools.getNodeAsInt( element, xpath, nsc, 1 ); 253 resolution = new OracleGeoRasterResolution( min, max, ranges, jdbc, table, rdtTable, column, identification, 254 level ); 255 return resolution; 256 } 257 258 /** 259 * creates a <tt>Shape</tt> object from the passed element 260 * 261 * @param element 262 * @return created Shape 263 * @throws XMLParsingException 264 * @throws UnknownCRSException 265 */ 266 private Shape getShape( Element element ) 267 throws XMLParsingException, UnknownCRSException { 268 String tilePoperty = XMLTools.getRequiredAttrValue( "tileProperty", null, element ); 269 String directoryProperty = XMLTools.getRequiredAttrValue( "directoryProperty", null, element ); 270 String srsName = XMLTools.getRequiredAttrValue( "srsName", null, element ); 271 CoordinateSystem crs = CRSFactory.create( srsName ); 272 String rootFileName = XMLTools.getStringValue( element ); 273 rootFileName.trim(); 274 XMLFragment xml = new XMLFragment(); 275 xml.setRootElement( root ); 276 xml.setSystemId( systemId ); 277 java.io.File file = null; 278 try { 279 URL url = xml.resolve( rootFileName + ".shp" ); 280 file = new java.io.File( url.toURI() ); 281 } catch ( Exception e ) { 282 LOG.logError( e.getMessage(), e ); 283 e.printStackTrace(); 284 } 285 rootFileName = file.getAbsolutePath(); 286 rootFileName = rootFileName.substring( 0, rootFileName.lastIndexOf( "." ) ); 287 return new Shape( crs, rootFileName, tilePoperty, directoryProperty ); 288 } 289 290 /** 291 * creates a <tt>File</tt> object from the passed Element that describes the extensions and 292 * locations of the coverages assigned to a <tt>Resolution</tt> 293 * 294 * @param element 295 * @return <tt>File</tt> object from the passed Element that describes the extensions and 296 * locations of the coverages assigned to a <tt>Resolution</tt> 297 * @throws XMLParsingException 298 * @throws UnknownCRSException 299 */ 300 private org.deegree.ogcwebservices.wcs.configuration.File getFile( Element element ) 301 throws XMLParsingException, InvalidGMLException, UnknownCRSException { 302 String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element ); 303 XMLFragment xml = new XMLFragment(); 304 xml.setRootElement( element ); 305 xml.setSystemId( systemId ); 306 File file = new File( name ); 307 try { 308 URL url = xml.resolve( name ); 309 file = new java.io.File( url.toURI() ); 310 } catch ( Exception e ) { 311 LOG.logError( e.getMessage(), e ); 312 e.printStackTrace(); 313 } 314 name = file.getAbsolutePath(); 315 316 Element elem = XMLTools.getRequiredChildElement( "Envelope", GMLNS, element ); 317 Envelope envelope = GMLGeometryAdapter.wrapBox( elem, null ); 318 String srs = XMLTools.getRequiredAttrValue( "srsName", null, elem ); 319 320 String[] tmp = StringTools.toArray( srs, "#", false ); 321 // just a heuristic because it is not guarranteed that the URL 322 // in the srsName attribute can be solved 323 if ( srs.toLowerCase().indexOf( "epsg" ) > -1 ) { 324 srs = "EPSG:" + tmp[1]; 325 } else { 326 srs = "CRS:" + tmp[1]; 327 } 328 if ( tmp[1].equals( "0" ) ) { 329 srs = null; 330 } 331 332 CoordinateSystem crs = CRSFactory.create( srs ); 333 return new org.deegree.ogcwebservices.wcs.configuration.File( crs, name, envelope ); 334 } 335 336 /** 337 * creates a <tt>Directory</tt> object from the passed Elememt that describes the extensions 338 * and locations of the coverages assigned to a <tt>Resolution</tt> 339 * 340 * @param element 341 * @return <tt>Directory</tt> object from the passed Elememt that describes the extensions and 342 * locations of the coverages assigned to a <tt>Resolution</tt> 343 * @throws XMLParsingException 344 * @throws UnknownCRSException 345 */ 346 private Directory getDirectory( Element element ) 347 throws XMLParsingException, InvalidGMLException, UnknownCRSException { 348 // get valid file extension for this directory 349 String temp = XMLTools.getRequiredAttrValue( "extensions", null, element ); 350 String[] extensions = StringTools.toArray( temp, ",;", true ); 351 // get the width and height (in pixels) af the tiles in this directory 352 temp = XMLTools.getRequiredAttrValue( "tileWidth", null, element ); 353 double tileWidth = 0; 354 try { 355 tileWidth = Double.parseDouble( temp ); 356 } catch ( Exception e ) { 357 throw new XMLParsingException( "tileWidth attribute isn't a number" ); 358 } 359 double tileHeight = 0; 360 try { 361 tileHeight = Double.parseDouble( temp ); 362 } catch ( Exception e ) { 363 throw new XMLParsingException( "tileHeight attribute isn't a number" ); 364 } 365 // get the directroy name 366 String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element ); 367 XMLFragment xml = new XMLFragment(); 368 xml.setRootElement( element ); 369 xml.setSystemId( systemId ); 370 try { 371 // resolve name if relative 372 name = xml.resolve( name ).toExternalForm(); 373 } catch ( MalformedURLException e ) { 374 throw new XMLParsingException( "invalid file name/path: " + name ); 375 } 376 // get the bounding envelope of all tiles in the directory 377 Element elem = XMLTools.getRequiredChildElement( "Envelope", GMLNS, element ); 378 Envelope envelope = GMLGeometryAdapter.wrapBox( elem, null ); 379 String srs = XMLTools.getRequiredAttrValue( "srsName", null, elem ); 380 if ( srs != null ) { 381 String[] tmp = StringTools.toArray( srs, "#", false ); 382 // just a heuristic because it is not guarranteed that the URL 383 // in the srsName attribute can be solved 384 if ( srs.toLowerCase().indexOf( "epsg" ) > -1 ) { 385 srs = "EPSG:" + tmp[1]; 386 } else { 387 srs = "CRS:" + tmp[1]; 388 } 389 if ( tmp[1].equals( "0" ) ) 390 srs = null; 391 } 392 CoordinateSystem crs = CRSFactory.create( srs ); 393 return new GridDirectory( name, envelope, crs, extensions, tileWidth, tileHeight ); 394 } 395 396 /** 397 * creates an array of <tt>Ranges</tt> from the passed element list 398 * 399 * @param el 400 * @return created array of <tt>Ranges</tt> 401 * @throws XMLParsingException 402 */ 403 private Range[] getRanges( ElementList el ) 404 throws XMLParsingException { 405 Range[] ranges = new Range[el.getLength()]; 406 for ( int i = 0; i < ranges.length; i++ ) { 407 ranges[i] = getRange( el.item( i ) ); 408 } 409 return ranges; 410 } 411 412 /** 413 * creates a <tt>Range</tt> object from the passed element 414 * 415 * @param element 416 * @return created <tt>Range</tt> 417 * @throws XMLParsingException 418 */ 419 private Range getRange( Element element ) 420 throws XMLParsingException { 421 String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element ); 422 ElementList el = XMLTools.getChildElements( "Axis", DGRNS, element ); 423 Axis[] axis = getAxis( el ); 424 return new Range( name, axis ); 425 } 426 427 /** 428 * creates an array of <tt>Axis</tt> objects from the passed element list 429 * 430 * @param el 431 * @return created array of <tt>Axis</tt> 432 * @throws XMLParsingException 433 */ 434 private Axis[] getAxis( ElementList el ) 435 throws XMLParsingException { 436 Axis[] axis = new Axis[el.getLength()]; 437 for ( int i = 0; i < axis.length; i++ ) { 438 axis[i] = getAxis( el.item( i ) ); 439 } 440 return axis; 441 } 442 443 /** 444 * creates an <tt>Axis</tt> object from the passed element. The <tt>Interval</tt> included 445 * in the <tt>Axis</tt> doesn't have a resolution because it isn't required. 446 * 447 * @param element 448 * @return created <tt>Axis</tt> 449 * @throws XMLParsingException 450 */ 451 private Axis getAxis( Element element ) 452 throws XMLParsingException { 453 try { 454 String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element ); 455 Element elem = XMLTools.getRequiredChildElement( "Interval", DGRNS, element ); 456 String tmp = XMLTools.getRequiredStringValue( "min", DGRNS, elem ); 457 TypedLiteral min = new TypedLiteral( tmp, new URI( "xs:double" ) ); 458 tmp = XMLTools.getRequiredStringValue( "max", DGRNS, elem ); 459 TypedLiteral max = new TypedLiteral( tmp, new URI( "xs:double" ) ); 460 Interval interval = new Interval( min, max, null, null, null ); 461 return new Axis( name, interval ); 462 } catch ( URISyntaxException e ) { 463 LOG.logError( e.getMessage(), e ); 464 throw new XMLParsingException( e.getMessage() ); 465 } 466 } 467 468 }