.append(request).toString());
}
WCSInfo wcs = getServiceInfo();
CoverageInfo meta = null;
GridCoverage2D coverage = null;
try {
CodeType identifier = request.getIdentifier();
if (identifier == null)
throw new WcsException("Internal error, the coverage identifier must not be null",
InvalidParameterValue, "identifier");
meta = catalog.getCoverageByName(identifier.getValue());
if (meta == null) {
throw new WcsException("No such coverage: " + request.getIdentifier().getValue());
}
// first let's run some sanity checks on the inputs
checkDomainSubset(meta, request.getDomainSubset(), wcs);
checkRangeSubset(meta, request.getRangeSubset());
checkOutput(meta, request.getOutput());
// grab the format, the reader using the default params
final GridCoverage2DReader reader = (GridCoverage2DReader) meta.getGridCoverageReader(
null, WCSUtils.getReaderHints(wcs));
// handle spatial domain subset, if needed
final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
final BoundingBoxType bbox = request.getDomainSubset().getBoundingBox();
final CoordinateReferenceSystem nativeCRS = originalEnvelope
.getCoordinateReferenceSystem();
final GeneralEnvelope requestedEnvelopeInNativeCRS;
final GeneralEnvelope requestedEnvelope;
if (bbox != null) {
// first off, parse the envelope corners
double[] lowerCorner = new double[bbox.getLowerCorner().size()];
double[] upperCorner = new double[bbox.getUpperCorner().size()];
for (int i = 0; i < lowerCorner.length; i++) {
lowerCorner[i] = (Double) bbox.getLowerCorner().get(i);
upperCorner[i] = (Double) bbox.getUpperCorner().get(i);
}
requestedEnvelope = new GeneralEnvelope(lowerCorner, upperCorner);
// grab the native crs
// if no crs has beens specified, the native one is assumed
if (bbox.getCrs() == null) {
requestedEnvelope.setCoordinateReferenceSystem(nativeCRS);
requestedEnvelopeInNativeCRS = requestedEnvelope;
} else {
// otherwise we need to transform
final CoordinateReferenceSystem bboxCRS = CRS.decode(bbox.getCrs());
requestedEnvelope.setCoordinateReferenceSystem(bboxCRS);
if (!CRS.equalsIgnoreMetadata(bboxCRS, nativeCRS)) {
CoordinateOperationFactory of = CRS.getCoordinateOperationFactory(true);
CoordinateOperation co = of.createOperation(bboxCRS, nativeCRS);
requestedEnvelopeInNativeCRS = CRS.transform(co, requestedEnvelope);
} else {
requestedEnvelopeInNativeCRS = new GeneralEnvelope(requestedEnvelope);
}
}
} else {
requestedEnvelopeInNativeCRS = reader.getOriginalEnvelope();
requestedEnvelope = requestedEnvelopeInNativeCRS;
}
final GridCrsType gridCRS = request.getOutput().getGridCRS();
// Compute the crs that the final coverage will be served into
final CoordinateReferenceSystem targetCRS;
if (gridCRS == null) {
targetCRS = reader.getOriginalEnvelope().getCoordinateReferenceSystem();
} else {
targetCRS = CRS.decode(gridCRS.getGridBaseCRS());
}
//
// Raster destination size
//
int elevationLevels = 0;
double[] elevations = null;
// grab the grid to world transformation
MathTransform gridToCRS = reader.getOriginalGridToWorld(PixelInCell.CELL_CENTER);
//
// TIME Values
//
final List<Date> timeValues = new LinkedList<Date>();
TimeSequenceType temporalSubset = request.getDomainSubset().getTemporalSubset();
if (temporalSubset != null && temporalSubset.getTimePosition() != null
&& temporalSubset.getTimePosition().size() > 0) {
for (Iterator it = temporalSubset.getTimePosition().iterator(); it.hasNext();) {
Date tp = (Date) it.next();
timeValues.add(tp);
}
} else if (temporalSubset != null && temporalSubset.getTimePeriod() != null
&& temporalSubset.getTimePeriod().size() > 0) {
for (Iterator it = temporalSubset.getTimePeriod().iterator(); it.hasNext();) {
TimePeriodType tp = (TimePeriodType) it.next();
Date beginning = (Date) tp.getBeginPosition();
Date ending = (Date) tp.getEndPosition();
timeValues.add(beginning);
timeValues.add(ending);
}
}
// now we have enough info to read the coverage, grab the parameters
// and add the grid geometry info
final GeneralEnvelope intersectionEnvelopeInSourceCRS = new GeneralEnvelope(
requestedEnvelopeInNativeCRS);
intersectionEnvelopeInSourceCRS.intersect(originalEnvelope);
final GridGeometry2D requestedGridGeometry = new GridGeometry2D(
PixelInCell.CELL_CENTER, gridToCRS, intersectionEnvelopeInSourceCRS, null);
final ParameterValueGroup readParametersDescriptor = reader.getFormat()
.getReadParameters();
GeneralParameterValue[] readParameters = CoverageUtils.getParameters(
readParametersDescriptor, meta.getParameters());
readParameters = (readParameters != null ? readParameters
: new GeneralParameterValue[0]);
//
// Setting coverage reading params.
//
final ParameterValue requestedGridGeometryParam = new DefaultParameterDescriptor(
AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString(),
GeneralGridGeometry.class, null, requestedGridGeometry).createValue();
/*
* Test if the parameter "TIME" is present in the WMS request, and by the way in the reading parameters. If it is the case, one can adds
* it to the request. If an exception is thrown, we have nothing to do.
*/
final List<GeneralParameterDescriptor> parameterDescriptors = readParametersDescriptor
.getDescriptor().descriptors();
ParameterValue time = null;
boolean hasTime = timeValues.size() > 0;
ParameterValue elevation = null;
boolean hasElevation = elevations != null && !Double.isNaN(elevations[0]);
if (hasElevation || hasTime) {
for (GeneralParameterDescriptor pd : parameterDescriptors) {
final String code = pd.getName().getCode();
//
// TIME
//
if (code.equalsIgnoreCase("TIME")) {
time = (ParameterValue) pd.createValue();
time.setValue(timeValues);
}
//
// ELEVATION
//
if (code.equalsIgnoreCase("ELEVATION")) {
elevation = (ParameterValue) pd.createValue();
elevation.setValue(elevations[0]);
}
// leave?
if ((hasElevation && elevation != null && hasTime && time != null)
|| !hasElevation && hasTime && time != null || hasElevation
&& elevation != null && !hasTime)
break;
}
}
//
// add read parameters
//
int addedParams = 1 + (hasTime ? 1 : 0) + (hasElevation ? 1 : 0);
// add to the list
GeneralParameterValue[] readParametersClone = new GeneralParameterValue[readParameters.length
+ addedParams--];
System.arraycopy(readParameters, 0, readParametersClone, 0, readParameters.length);
readParametersClone[readParameters.length + addedParams--] = requestedGridGeometryParam;
if (hasTime)
readParametersClone[readParameters.length + addedParams--] = time;
if (hasElevation)
readParametersClone[readParameters.length + addedParams--] = elevation;
readParameters = readParametersClone;
// Check we're not being requested to read too much data from input (first check,
// guesses the grid size using the information contained in CoverageInfo)
WCSUtils.checkInputLimits(wcs, meta, reader, requestedGridGeometry);
//
// Check if we have a filter among the params
//
Filter filter = WCSUtils.getRequestFilter();
if (filter != null) {
readParameters = CoverageUtils.mergeParameter(parameterDescriptors, readParameters,
filter, "FILTER", "Filter");
}
//
// make sure we work in streaming mode
//
// work in streaming fashion when JAI is involved
readParameters = WCSUtils.replaceParameter(readParameters, Boolean.FALSE,
AbstractGridFormat.USE_JAI_IMAGEREAD);
//
// perform Read ...
//
coverage = (GridCoverage2D) reader.read(readParameters);
if ((coverage == null) || !(coverage instanceof GridCoverage2D)) {
throw new IOException("The requested coverage could not be found.");
}
// now that we have read the coverage double check the input size
WCSUtils.checkInputLimits(wcs, coverage);
// some raster sources do not really read less data (arcgrid for example), we may need to crop
if (!intersectionEnvelopeInSourceCRS.contains(coverage.getEnvelope2D(), true)) {
coverage = WCSUtils.crop(coverage, intersectionEnvelopeInSourceCRS);
}
/**
* Band Select (works on just one field)
*/
GridCoverage2D bandSelectedCoverage = coverage;
String interpolationType = null;
if (request.getRangeSubset() != null) {
if (request.getRangeSubset().getFieldSubset().size() > 1) {
throw new WcsException("Multi field coverages are not supported yet");
}
FieldSubsetType field = (FieldSubsetType) request.getRangeSubset().getFieldSubset()
.get(0);
interpolationType = field.getInterpolationType();
// handle axis subset
if (field.getAxisSubset().size() > 1) {
throw new WcsException("Multi axis coverages are not supported yet");
}
if (field.getAxisSubset().size() == 1) {
// prepare a support structure to quickly get the band index
// of a
// key
List<CoverageDimensionInfo> dimensions = meta.getDimensions();
Map<String, Integer> dimensionMap = new HashMap<String, Integer>();
for (int i = 0; i < dimensions.size(); i++) {
String keyName = dimensions.get(i).getName().replace(' ', '_');
dimensionMap.put(keyName, i);
}