thredds.wcs.v1_0_0_Plus.GetCoverage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of netcdf Show documentation
Show all versions of netcdf Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package thredds.wcs.v1_0_0_Plus;
import java.io.File;
import java.text.ParseException;
import java.util.List;
import java.util.ArrayList;
import ucar.unidata.geoloc.ogc.EPSG_OGC_CF_Helper;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.geoloc.LatLonPointImpl;
import ucar.nc2.dt.GridCoordSystem;
import ucar.nc2.dataset.CoordinateAxis1D;
import ucar.nc2.units.DateRange;
import ucar.nc2.units.DateType;
import ucar.ma2.Range;
import ucar.ma2.InvalidRangeException;
/**
* _more_
*
* @author edavis
* @since 4.0
*/
public class GetCoverage extends WcsRequest
{
private static org.slf4j.Logger log =
org.slf4j.LoggerFactory.getLogger( GetCoverage.class );
private WcsCoverage coverage;
private LatLonRect requestLatLonBBox;
private AxisSubset requestVertSubset;
private DateRange timeRange;
private List rangeSubset;
private Format format;
// Requests for GeoTIFF encoding must be for a single time, single vertical level, and single range field.
private boolean isSingleTimeRequest = false;
private boolean isSingleVerticalRequest = false;
private boolean isSingleRangeFieldRequest = false;
public GetCoverage( Operation operation, String version, WcsDataset dataset,
String coverageId, String crs, String responseCRS,
String bbox, String time, String rangeSubset, String format )
throws WcsException
{
super( operation, version, dataset);
// Validate coverage ID parameter.
if ( coverageId == null )
throw new WcsException( WcsException.Code.MissingParameterValue, "coverage", "Coverage identifier required." );
if ( !this.getDataset().isAvailableCoverageName( coverageId ) )
throw new WcsException( WcsException.Code.InvalidParameterValue, "coverage", "Unknown coverage identifier <" + coverageId + ">." );
this.coverage = this.getDataset().getAvailableCoverage( coverageId );
if ( this.coverage == null ) // Double check just in case.
throw new WcsException( WcsException.Code.InvalidParameterValue, "coverage", "Unknown coverage identifier <" + coverageId + ">." );
// Assign and validate request and response CRS parameters.
if ( crs == null )
throw new WcsException( WcsException.Code.MissingParameterValue, "CRS", "Request CRS required.");
if ( ! crs.equalsIgnoreCase( this.coverage.getDefaultRequestCrs() ) )
throw new WcsException( WcsException.Code.InvalidParameterValue, "CRS", "Request CRS <" + crs + "> not allowed <" + this.coverage.getDefaultRequestCrs() + ">." );
String nativeCRS = EPSG_OGC_CF_Helper.getWcs1_0CrsId( coverage.getCoordinateSystem().getProjection() );
if ( nativeCRS == null )
throw new WcsException( WcsException.Code.CoverageNotDefined, "", "Coverage not in recognized CRS. (???)");
// Response CRS not required if data is in latLon ("OGC:CRS84"). Default is request CRS.
if ( responseCRS == null )
{
if ( ! nativeCRS.equalsIgnoreCase( this.coverage.getDefaultRequestCrs()))
throw new WcsException( WcsException.Code.MissingParameterValue, "Response_CRS", "Response CRS required." );
}
else if ( ! responseCRS.equalsIgnoreCase( nativeCRS))
throw new WcsException( WcsException.Code.InvalidParameterValue, "response_CRS", "Respnse CRS <" + responseCRS + "> not allowed <" + nativeCRS + ">." );
// Assign and validate BBOX and TIME parameters.
// -----
// WCS Spec says at least one of BBOX and TIME are required in a request.
// We will not require, default is everything.
//
// if ( bbox == null && time == null )
// throw new WcsException( WcsException.Code.MissingParameterValue, "BBOX", "BBOX and/or TIME required.");
// -----
if ( bbox != null && ( ! bbox.equals( "" ) ) )
{
String[] bboxSplit = splitBoundingBox( bbox);
requestLatLonBBox = genRequestLatLonBoundingBox( bboxSplit, coverage.getCoordinateSystem());
CoordinateAxis1D vertAxis = this.coverage.getCoordinateSystem().getVerticalAxis();
if ( vertAxis != null )
requestVertSubset = genRequestVertSubset( bboxSplit, vertAxis );
}
if ( time != null && ( ! time.equals( "" )) )
timeRange = parseTime( time);
// WIDTH, HEIGHT, DEPTH parameters not needed since the only interpolation method is "NONE".
// RESX, RESY, RESZ parameters not needed since the only interpolation method is "NONE".
// Assign and validate RangeSubset parameter.
this.rangeSubset = parseRangeSubset( rangeSubset);//, coverage.getRange());
// Assign and validate FORMAT parameter.
if ( format == null || format.equals( "" ))
{
log.error( "GetCoverage(): FORMAT parameter required.");
throw new WcsException( WcsException.Code.InvalidParameterValue, "FORMAT", "FORMAT parameter required.");
}
try
{
this.format = Format.valueOf( format.trim());
}
catch ( IllegalArgumentException e )
{
String msg = "Unknown format value [" + format + "].";
log.error( "GetCoverage(): " + msg );
throw new WcsException( WcsException.Code.InvalidParameterValue, "FORMAT", msg );
}
if ( ! this.coverage.isSupportedCoverageFormat( this.format ))
{
String msg = "Unsupported format value [" + format + "].";
log.error( "GetCoverage(): " + msg );
throw new WcsException( WcsException.Code.InvalidParameterValue, "FORMAT", msg );
}
if ( this.format == WcsRequest.Format.GeoTIFF || this.format == WcsRequest.Format.GeoTIFF_Float)
{
// Check that request is for one time and one vertical level and one range field
// since that is all we support for GeoTIFF[-Float].
if ( ! this.isSingleTimeRequest &&
! this.isSingleVerticalRequest &&
! this.isSingleRangeFieldRequest )
{
StringBuffer msgB = new StringBuffer( "GeoTIFF supported only for requests at a single time [");
if ( time != null )
msgB.append( time);
msgB.append( "] and a single vertical level [");
if ( bbox != null )
msgB.append( bbox);
msgB.append( "] and a single range field [");
if ( rangeSubset != null )
msgB.append( rangeSubset );
msgB.append( "].");
log.error( "GetCoverage(): " + msgB );
throw new WcsException( WcsException.Code.InvalidParameterValue, "FORMAT", msgB.toString() );
}
}
}
public Format getFormat() { return format; }
public File writeCoverageDataToFile()
throws WcsException
{
return this.coverage.writeCoverageDataToFile( this.format,
this.requestLatLonBBox,
this.requestVertSubset,
this.rangeSubset,
this.timeRange);
}
private String[] splitBoundingBox( String bbox)
throws WcsException
{
if ( bbox == null || bbox.equals( "" ) )
return null;
String[] bboxSplit = bbox.split( "," );
if ( bboxSplit.length != 4 && bboxSplit.length != 6 )
{
log.error( "splitBoundingBox(): BBOX <" + bbox + "> must be \"minx,miny,maxx,maxy[,minz,maxz]\"." );
throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", "BBOX <" + bbox + "> not in expected format \"minx,miny,maxx,maxy[,minz,maxz]\"." );
}
return bboxSplit;
}
private LatLonRect genRequestLatLonBoundingBox( String[] bboxSplit, GridCoordSystem gcs)
throws WcsException
{
if ( bboxSplit == null || gcs == null )
return null;
if ( bboxSplit.length < 4 )
throw new IllegalArgumentException( "BBOX contains fewer than four items \"" + bboxSplit.toString() + "\".");
double minx = 0;
double miny = 0;
double maxx = 0;
double maxy = 0;
try
{
minx = Double.parseDouble( bboxSplit[0] );
miny = Double.parseDouble( bboxSplit[1] );
maxx = Double.parseDouble( bboxSplit[2] );
maxy = Double.parseDouble( bboxSplit[3] );
}
catch ( NumberFormatException e )
{
String message = "BBOX item(s) have incorrect number format [not double] <" + bboxSplit.toString() + ">.";
log.error( "genRequestLatLonBoundingBox(): " + message + " - " + e.getMessage());
throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", message );
}
LatLonPointImpl minll = new LatLonPointImpl( miny, minx );
LatLonPointImpl maxll = new LatLonPointImpl( maxy, maxx );
LatLonRect requestLatLonRect = new LatLonRect( minll, maxll );
LatLonRect covLatLonRect = gcs.getLatLonBoundingBox();
// if ( ! requestLatLonRect.containedIn( covLatLonRect))
// {
// log.error( "genRequestLatLonBoundingBox(): BBOX <" + bbox + "> not contained in coverage BBOX <"+ covLatLonRect.toString2()+">.");
// throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", "BBOX <" + bbox + "> not contained in coverage.");
// }
return requestLatLonRect;
}
private AxisSubset genRequestVertSubset( String[] bboxSplit, CoordinateAxis1D vertAxis )
throws WcsException
{
// Check if no vertical range request.
if ( bboxSplit == null || bboxSplit.length == 4 )
{
// If there is no vertical axis (or only one level), still a single level request.
if ( vertAxis == null || vertAxis.getShape(0) == 1 )
this.isSingleVerticalRequest = true;
return null;
}
if ( bboxSplit.length != 6 )
{
String message = "BBOX must have 4 or 6 items [" + bboxSplit.toString() + "].";
log.error( "genRequestVertSubset(): " + message );
throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", message );
}
// If there is no vertical axis (or only one level), still a single level request.
if ( vertAxis == null || vertAxis.getShape(0) == 1 )
{
this.isSingleVerticalRequest = true;
return null;
}
double minz = 0;
double maxz = 0;
try
{
minz = Double.parseDouble( bboxSplit[4] );
maxz = Double.parseDouble( bboxSplit[5] );
}
catch ( NumberFormatException e )
{
String message = "BBOX item(s) have incorrect number format (not double) [" + bboxSplit.toString() + "].";
log.error( "genRequestVertSubset(): " + message + " - " + e.getMessage() );
throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", message );
}
AxisSubset axisSubset = new AxisSubset( vertAxis, minz, maxz, 1 );
Range range = null;
try
{
range = axisSubset.getRange();
}
catch ( InvalidRangeException e )
{
String message = "BBOX results in invalid array index range [" + bboxSplit.toString() + "].";
log.error( "genRequestVertSubset(): " + message + " - " + e.getMessage() );
throw new WcsException( WcsException.Code.InvalidParameterValue, "BBOX", message );
}
if ( range.length() == 1 )
{
// Check whether vertical range results in a single level.
this.isSingleVerticalRequest = true;
return null;
}
return axisSubset;
}
private DateRange parseTime( String time )
throws WcsException
{
if ( time == null || time.equals( ""))
return null;
DateRange dateRange;
try
{
if ( time.indexOf( ",") != -1 )
{
log.error( "parseTime(): Unsupported time parameter (list) <" + time + ">.");
throw new WcsException( WcsException.Code.InvalidParameterValue, "TIME",
"Not currently supporting time list." );
//String[] timeList = time.split( "," );
//dateRange = new DateRange( date, date, null, null );
}
else if ( time.indexOf( "/") != -1 )
{
String[] timeRange = time.split( "/" );
if ( timeRange.length != 2)
{
log.error( "parseTime(): Unsupported time parameter (time range with resolution) <" + time + ">.");
throw new WcsException( WcsException.Code.InvalidParameterValue, "TIME", "Not currently supporting time range with resolution.");
}
dateRange = new DateRange( new DateType( timeRange[0], null, null ),
new DateType( timeRange[1], null, null ), null, null );
}
else
{
DateType date = new DateType( time, null, null );
dateRange = new DateRange( date, date, null, null );
this.isSingleTimeRequest = true;
}
}
catch ( ParseException e )
{
log.error( "parseTime(): Failed to parse time parameter <" + time + ">: " + e.getMessage() );
throw new WcsException( WcsException.Code.InvalidParameterValue, "TIME",
"Invalid time format <" + time + ">." );
}
return dateRange;
}
private List parseRangeSubset( String rangeSubset)
throws WcsException
{
List response = new ArrayList();
// Default is to return all fields.
if ( rangeSubset == null || rangeSubset.equals( "" ) )
{
response.addAll( this.coverage.getRangeFieldNames() );
if ( response.size() == 1 )
this.isSingleRangeFieldRequest = true;
return response;
}
// Split the rangeSubset request into fieldSubset requests.
String[] fieldSubsetArray;
if ( rangeSubset.indexOf( ";") == -1 )
{
fieldSubsetArray = new String[1];
fieldSubsetArray[0] = rangeSubset;
}
else
{
fieldSubsetArray = rangeSubset.split( ";" );
}
for ( String curFieldSubset : fieldSubsetArray )
{
if ( this.coverage.isRangeFieldName( curFieldSubset) )
response.add( curFieldSubset );
else
{
String message = "Requested range field <" + curFieldSubset + "> not available.";
log.warn( "parseRangeSubset(): " + message );
throw new WcsException( WcsException.Code.InvalidParameterValue, "RangeSubset", message );
}
}
if ( response.size() == 1 )
this.isSingleRangeFieldRequest = true;
return response;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy