/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wcs2_0.eo;
import java.io.IOException;
import net.opengis.wcs20.GetCoverageType;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.ows.AbstractDispatcherCallback;
import org.geoserver.ows.Request;
import org.geoserver.platform.Operation;
import org.geoserver.wcs2_0.exception.WCS20Exception;
import org.geoserver.wcs2_0.exception.WCS20Exception.WCS20ExceptionCode;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geotools.coverage.grid.io.GranuleSource;
import org.geotools.coverage.grid.io.StructuredGridCoverage2DReader;
import org.geotools.data.Query;
import org.geotools.factory.CommonFactoryFinder;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
/**
* Plugs into the GetCoverage request cycle and transforms a request for a single EO granule
* to one against the coverage, but with the filter to limit it to the specified granule
*
* @author Andrea Aime - GeoSolutions
*/
public class GetCoverageEOCallback extends AbstractDispatcherCallback {
private static FilterFactory FF = CommonFactoryFinder.getFilterFactory2();
private EOCoverageResourceCodec codec;
public GetCoverageEOCallback(EOCoverageResourceCodec codec) {
this.codec = codec;
}
@Override
public Operation operationDispatched(Request request, Operation operation) {
Object[] parameters = operation.getParameters();
if(parameters != null && parameters.length > 0 && parameters[0] instanceof GetCoverageType) {
// check we are going against a granule
GetCoverageType gc = (GetCoverageType) parameters[0];
String coverageId = gc.getCoverageId();
if(coverageId == null) {
throw new WCS20Exception("Required parameter coverageId is missing",
WCS20Exception.WCS20ExceptionCode.MissingParameterValue, "coverageId");
}
CoverageInfo coverage = codec.getGranuleCoverage(coverageId);
if(coverage != null) {
// set the actual coverage name
String actualCoverageId = NCNameResourceCodec.encode(coverage);
gc.setCoverageId(actualCoverageId);
// extract the granule filter
Filter granuleFilter = codec.getGranuleFilter(coverageId);
// check the filter actually matches one granule
if(!readerHasGranule(coverage, granuleFilter)) {
throw new WCS20Exception("Could not locate coverage " + coverageId, WCS20ExceptionCode.NoSuchCoverage, "coverageId");
}
// set and/or merge with the previous filter
Filter previous = gc.getFilter();
if(previous == null || previous == Filter.INCLUDE) {
gc.setFilter(granuleFilter);
} else {
gc.setFilter(FF.and(previous, granuleFilter));
}
}
}
return operation;
}
private boolean readerHasGranule(CoverageInfo ci, Filter granuleFilter) {
try {
StructuredGridCoverage2DReader reader = (StructuredGridCoverage2DReader) ci.getGridCoverageReader(null, null);
String coverageName = codec.getCoverageName(ci);
GranuleSource source = reader.getGranules(coverageName, true);
return source.getCount(new Query(coverageName, granuleFilter)) > 0;
} catch(IOException e) {
throw new WCS20Exception("Could not determine if the coverage has the specified granule", e);
}
}
}