Package thredds.wcs.v1_0_0_Plus

Source Code of thredds.wcs.v1_0_0_Plus.GetCoverage

/*
* 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<String> 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<String> parseRangeSubset( String rangeSubset)
          throws WcsException
  {
    List<String> response = new ArrayList<String>();

    // 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;
  }

}
TOP

Related Classes of thredds.wcs.v1_0_0_Plus.GetCoverage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.