// $Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/ogcwebservices/wcs/configuration/ExtensionDocument.java,v 1.3 2006/11/27 09:07:53 poth Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.ogcwebservices.wcs.configuration;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import org.deegree.datatypes.values.Interval;
import org.deegree.datatypes.values.TypedLiteral;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.StringTools;
import org.deegree.framework.xml.ElementList;
import org.deegree.framework.xml.NamespaceContext;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.framework.xml.XMLParsingException;
import org.deegree.framework.xml.XMLTools;
import org.deegree.io.IODocument;
import org.deegree.io.JDBCConnection;
import org.deegree.model.crs.CRSFactory;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.crs.UnknownCRSException;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GMLGeometryAdapter;
import org.deegree.ogcbase.CommonNamespaces;
import org.deegree.ogcbase.InvalidGMLException;
import org.deegree.ogcwebservices.InvalidParameterValueException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* This class creates a class representation of the Extension section of
* a deegree WCS coverage offering (coverage configuration) element. the
* extension section contains
* informations about data access/sources for different resolutions and
* ranges.<BR>
* an extension section must contain at least one Resolution element but
* can contains as much as the user may defined. A resoluton contains a
* access informations for data and the ranges the data are assigned to.
* because of this it is possible that more than one Resoultion element
* with same resolution range but with different other ranges (e.g. time
* or elevation)
*
* @version $Revision: 1.3 $
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author last edited by: $Author: poth $
*
* @version 1.0. $Revision: 1.3 $, $Date: 2006/11/27 09:07:53 $
*
* @since 1.1
*/
public class ExtensionDocument {
private static final ILogger LOG = LoggerFactory.getLogger( ExtensionDocument.class );
private static URI GMLNS = CommonNamespaces.GMLNS;
private static URI DGRNS = CommonNamespaces.DEEGREEWCS;
private URL systemId = null;
private Element root = null;
/**
* constructing the ExtensionBuilder by passing the root element of
* a deegree WCS CoverageOffering Extension.
*
* @param root
*/
public ExtensionDocument( Element root, URL systemId ) {
this.root = root;
this.systemId = systemId;
}
/**
* returns the content of the Extension element of te deegree WCS coverage
* description (configuration document). the extension section contains
* informations about data access/sources for different resolutions and
* ranges.<BR>
* an extension section must contain at least one Resolution element but
* can contains as much as the user may defined. A resoluton contains a
* access informations for data and the ranges the data are assigned to.
* because of this it is possible that more than one Resoultion element
* with same resolution range but with different other ranges (e.g. time
* or elevation)
* @return
* @throws InvalidCVExtensionException
* @throws UnknownCVExtensionException
* @throws InvalidParameterValueException
* @throws UnknownCRSException
*/
public Extension getExtension()
throws InvalidCVExtensionException, UnknownCVExtensionException,
InvalidParameterValueException, InvalidGMLException, UnknownCRSException {
Extension extension = null;
try {
String type = XMLTools.getRequiredAttrValue( "type", null, root );
ElementList el = XMLTools.getChildElements( "Resolution", DGRNS, root );
Resolution[] resolutions = getResolutions( type, el );
extension = new DefaultExtension( type, resolutions );
} catch ( XMLParsingException e ) {
throw new InvalidCVExtensionException( StringTools.stackTraceToString( e ) );
}
return extension;
}
/**
* returns the resolutions definitions within the Extension element of the
* deegree WCS coverage offering. Each resoultion contains access description
* for its data and an optional description of the ranges the data are
* valid for.
*
* @param type
* @param el
* @return
* @throws XMLParsingException
* @throws InvalidParameterValueException
* @throws UnknownCRSException
*/
private Resolution[] getResolutions( String type, ElementList el )
throws XMLParsingException, InvalidParameterValueException,
InvalidGMLException, UnknownCRSException {
Resolution[] resolutions = new Resolution[el.getLength()];
for ( int i = 0; i < resolutions.length; i++ ) {
resolutions[i] = getResolution( type, el.item( i ) );
}
return resolutions;
}
/**
* creates an instance of <tt>Resoltuion</tt> from the passed <tt>Element</tt>
* and the type of the coverage source. Valid values for type are:
* <ul>
* <li>shapeIndexed
* <li>nameIndexed
* <li>file
* </ul>
* if an unknown typed is passed an <tt>InvalidParameterValueException</tt> will
* be thrown
* @param type
* @param element
* @return
* @throws XMLParsingException
* @throws UnknownCRSException
*/
private Resolution getResolution( String type, Element element )
throws XMLParsingException, InvalidParameterValueException,
InvalidGMLException, UnknownCRSException {
String tmp = XMLTools.getRequiredAttrValue( "min", null, element );
double min = Double.parseDouble( tmp );
tmp = XMLTools.getRequiredAttrValue( "max", null, element );
double max = Double.parseDouble( tmp );
ElementList el = XMLTools.getChildElements( "Range", DGRNS, element );
Range[] ranges = getRanges( el );
Resolution resolution = null;
if ( type.equals( "shapeIndexed" ) ) {
// TODO
// enable more than one shape
Element elem = XMLTools.getChildElement( "Shape", DGRNS, element );
Shape shape = getShape( elem );
resolution = new ShapeResolution( min, max, ranges, shape );
} else if ( type.equals( "nameIndexed" ) ) {
ElementList ell = XMLTools.getChildElements( "Directory", DGRNS, element );
Directory[] dirs = new Directory[ell.getLength()];
for ( int i = 0; i < dirs.length; i++ ) {
dirs[i] = getDirectory( ell.item( i ) );
}
resolution = new DirectoryResolution( min, max, ranges, dirs );
} else if ( type.equals( "file" ) ) {
ElementList ell = XMLTools.getChildElements( "File", DGRNS, element );
File[] files = new File[ell.getLength()];
for ( int i = 0; i < files.length; i++ ) {
files[i] = getFile( ell.item( i ) );
}
resolution = new FileResolution( min, max, ranges, files );
} else if ( type.equals( "OracleGeoRaster" ) ) {
resolution = getOracleGeoRasterResolution( element, min, max, ranges );
} else {
throw new InvalidParameterValueException( "type: " + type + " not known "
+ "by the deegree WCS" );
}
return resolution;
}
/**
* creates a <tt>OracleGeoRasterResolution</tt> object from the passed element
* @param element
* @return
* @throws XMLParsingException
*/
private Resolution getOracleGeoRasterResolution( Element element, double min, double max,
Range[] ranges )
throws XMLParsingException {
Resolution resolution;
NamespaceContext nsc = CommonNamespaces.getNamespaceContext();
String xpath = "deegreewcs:OracleGeoRaster/dgjdbc:JDBCConnection";
Node node = XMLTools.getRequiredNode( element, xpath, nsc );
IODocument io = new IODocument( (Element) node );
JDBCConnection jdbc = io.parseJDBCConnection();
xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Table/text()";
String table = XMLTools.getRequiredNodeAsString( element, xpath, nsc );
xpath = "deegreewcs:OracleGeoRaster/deegreewcs:RDTTable/text()";
String rdtTable = XMLTools.getRequiredNodeAsString( element, xpath, nsc );
xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Column/text()";
String column = XMLTools.getRequiredNodeAsString( element, xpath, nsc );
xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Identification/text()";
String identification = XMLTools.getRequiredNodeAsString( element, xpath, nsc );
xpath = "deegreewcs:OracleGeoRaster/deegreewcs:Level/text()";
int level = XMLTools.getNodeAsInt( element, xpath, nsc, 1 );
resolution = new OracleGeoRasterResolution( min, max, ranges, jdbc, table, rdtTable,
column, identification, level );
return resolution;
}
/**
* creates a <tt>Shape</tt> object from the passed element
* @param element
* @return
* @throws XMLParsingException
* @throws UnknownCRSException
*/
private Shape getShape( Element element ) throws XMLParsingException, UnknownCRSException {
String tilePoperty = XMLTools.getRequiredAttrValue( "tileProperty", null, element );
String directoryProperty = XMLTools.getRequiredAttrValue( "directoryProperty", null, element );
String srsName = XMLTools.getRequiredAttrValue( "srsName", null, element );
CoordinateSystem crs = CRSFactory.create( srsName );
String rootFileName = XMLTools.getStringValue( element );
rootFileName.trim();
XMLFragment xml = new XMLFragment();
xml.setRootElement( root );
xml.setSystemId( systemId );
java.io.File file = null;
try {
URL url = xml.resolve( rootFileName + ".shp" );
file = new java.io.File( url.toURI() );
} catch ( Exception e ) {
LOG.logError( e.getMessage(), e );
e.printStackTrace();
}
rootFileName = file.getAbsolutePath();
rootFileName = rootFileName.substring( 0, rootFileName.lastIndexOf( "." ) );
return new Shape( crs, rootFileName, tilePoperty, directoryProperty );
}
/**
* creates a <tt>File</tt> object from the passed Element that describes
* the extensions and locations of the coverages assigned to a <tt>Resolution</tt>
* @param element
* @return
* @throws XMLParsingException
* @throws UnknownCRSException
*/
private File getFile( Element element )
throws XMLParsingException, InvalidGMLException, UnknownCRSException {
String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element );
XMLFragment xml = new XMLFragment();
xml.setRootElement( element );
xml.setSystemId( systemId );
try {
// resolve name if relative
name = xml.resolve( name ).toExternalForm();
} catch ( MalformedURLException e ) {
throw new XMLParsingException( "invalid file name/path: " + name );
}
Element elem = XMLTools.getRequiredChildElement( "Envelope", GMLNS, element );
Envelope envelope = GMLGeometryAdapter.wrapBox( elem );
String srs = XMLTools.getRequiredAttrValue( "srsName", null, elem );
if ( srs != null ) {
String[] tmp = StringTools.toArray( srs, "#", false );
// just a heuristic because it is not guarranteed that the URL
// in the srsName attribute can be solved
if ( srs.toLowerCase().indexOf( "epsg" ) > -1 ) {
srs = "EPSG:" + tmp[1];
} else {
srs = "CRS:" + tmp[1];
}
if ( tmp[1].equals( "0" ) )
srs = null;
}
CoordinateSystem crs = CRSFactory.create( srs );
return new File( crs, name, envelope );
}
/**
* creates a <tt>Directory</tt> object from the passed Elememt that describes
* the extensions and locations of the coverages assigned to a <tt>Resolution</tt>
* @param element
* @return
* @throws XMLParsingException
* @throws UnknownCRSException
*/
private Directory getDirectory( Element element )
throws XMLParsingException, InvalidGMLException, UnknownCRSException {
// get valid file extension for this directory
String temp = XMLTools.getRequiredAttrValue( "extensions", null, element );
String[] extensions = StringTools.toArray( temp, ",;", true );
// get the width and height (in pixels) af the tiles in this directory
temp = XMLTools.getRequiredAttrValue( "tileWidth", null, element );
double tileWidth = 0;
try {
tileWidth = Double.parseDouble( temp );
} catch ( Exception e ) {
throw new XMLParsingException( "tileWidth attribute isn't a number" );
}
double tileHeight = 0;
try {
tileHeight = Double.parseDouble( temp );
} catch ( Exception e ) {
throw new XMLParsingException( "tileHeight attribute isn't a number" );
}
// get the directroy name
String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element );
XMLFragment xml = new XMLFragment();
xml.setRootElement( element );
xml.setSystemId( systemId );
try {
// resolve name if relative
name = xml.resolve( name ).toExternalForm();
} catch ( MalformedURLException e ) {
throw new XMLParsingException( "invalid file name/path: " + name );
}
// get the bounding envelope of all tiles in the directory
Element elem = XMLTools.getRequiredChildElement( "Envelope", GMLNS, element );
Envelope envelope = GMLGeometryAdapter.wrapBox( elem );
String srs = XMLTools.getRequiredAttrValue( "srsName", null, elem );
if ( srs != null ) {
String[] tmp = StringTools.toArray( srs, "#", false );
// just a heuristic because it is not guarranteed that the URL
// in the srsName attribute can be solved
if ( srs.toLowerCase().indexOf( "epsg" ) > -1 ) {
srs = "EPSG:" + tmp[1];
} else {
srs = "CRS:" + tmp[1];
}
if ( tmp[1].equals( "0" ) )
srs = null;
}
CoordinateSystem crs = CRSFactory.create( srs );
return new GridDirectory( name, envelope, crs, extensions, tileWidth, tileHeight );
}
/**
* creates an array of <tt>Ranges</tt> from the passed element list
* @param el
* @return created array of <tt>Ranges</tt>
* @throws XMLParsingException
*/
private Range[] getRanges( ElementList el )
throws XMLParsingException {
Range[] ranges = new Range[el.getLength()];
for ( int i = 0; i < ranges.length; i++ ) {
ranges[i] = getRange( el.item( i ) );
}
return ranges;
}
/**
* creates a <tt>Range</tt> object from the passed element
* @param element
* @return created <tt>Range</tt>
* @throws XMLParsingException
*/
private Range getRange( Element element )
throws XMLParsingException {
String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element );
ElementList el = XMLTools.getChildElements( "Axis", DGRNS, element );
Axis[] axis = getAxis( el );
return new Range( name, axis );
}
/**
* creates an array of <tt>Axis</tt> objects from the passed element list
* @param el
* @return created array of <tt>Axis</tt>
* @throws XMLParsingException
*/
private Axis[] getAxis( ElementList el )
throws XMLParsingException {
Axis[] axis = new Axis[el.getLength()];
for ( int i = 0; i < axis.length; i++ ) {
axis[i] = getAxis( el.item( i ) );
}
return axis;
}
/**
* creates an <tt>Axis</tt> object from the passed element. The
* <tt>Interval</tt> included in the <tt>Axis</tt> doesn't have a
* resolution because it isn't required.
* @param element
* @return created <tt>Axis</tt>
* @throws XMLParsingException
*/
private Axis getAxis( Element element )
throws XMLParsingException {
try {
String name = XMLTools.getRequiredStringValue( "Name", DGRNS, element );
Element elem = XMLTools.getRequiredChildElement( "Interval", DGRNS, element );
String tmp = XMLTools.getRequiredStringValue( "min", DGRNS, elem );
TypedLiteral min = new TypedLiteral( tmp, new URI( "xs:double" ) );
tmp = XMLTools.getRequiredStringValue( "max", DGRNS, elem );
TypedLiteral max = new TypedLiteral( tmp, new URI( "xs:double" ) );
Interval interval = new Interval( min, max, null, null, null );
return new Axis( name, interval );
} catch ( URISyntaxException e ) {
LOG.logError( e.getMessage(), e );
throw new XMLParsingException( e.getMessage() );
}
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: ExtensionDocument.java,v $
Revision 1.3 2006/11/27 09:07:53 poth
JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
Revision 1.2 2006/11/23 08:36:19 bezema
a trim of the rootfilename sometimes cures the endline failure
Revision 1.1 2006/07/13 13:31:19 poth
class rename from ExtensionBuilder to ExtensionDocument
Revision 1.18 2006/05/19 12:34:52 poth
todo note added
Revision 1.17 2006/05/12 15:26:05 poth
*** empty log message ***
Revision 1.16 2006/05/01 20:15:26 poth
*** empty log message ***
Revision 1.15 2006/04/06 20:25:27 poth
*** empty log message ***
Revision 1.14 2006/04/04 20:39:42 poth
*** empty log message ***
Revision 1.13 2006/03/30 21:20:26 poth
*** empty log message ***
Revision 1.12 2006/03/14 08:42:52 poth
*** empty log message ***
Revision 1.11 2006/03/07 21:40:20 poth
*** empty log message ***
Revision 1.10 2006/03/02 21:39:38 poth
*** empty log message ***
Revision 1.9 2006/02/28 09:45:33 poth
*** empty log message ***
Revision 1.8 2006/02/06 15:54:33 poth
*** empty log message ***
Revision 1.7 2006/02/06 11:08:24 poth
*** empty log message ***
Revision 1.6 2006/02/05 20:33:09 poth
*** empty log message ***
Revision 1.5 2005/11/16 13:45:00 mschneider
Merge of wfs development branch.
Revision 1.4.2.1 2005/11/07 13:09:26 deshmukh
Switched namespace definitions in "CommonNamespaces" to URI.
Revision 1.4 2005/09/27 19:53:18 poth
no message
Revision 1.3 2005/03/09 11:55:47 mschneider
*** empty log message ***
Revision 1.2 2005/01/16 22:30:33 poth
no message
Revision 1.10 2004/08/12 10:39:44 ap
no message
Revision 1.9 2004/08/09 06:43:50 ap
no message
Revision 1.8 2004/07/19 06:20:01 ap
no message
Revision 1.7 2004/07/13 06:13:07 ap
no message
Revision 1.6 2004/07/12 13:03:21 mschneider
More work on the CatalogConfiguration and capabilities framework.
Revision 1.5 2004/07/12 06:12:11 ap
no message
Revision 1.4 2004/06/30 15:16:05 mschneider
Refactoring of XMLTools.
Revision 1.3 2004/06/28 06:26:52 ap
no message
Revision 1.2 2004/05/28 06:02:57 ap
no message
********************************************************************** */