/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 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 java.util.Collections;
import java.util.logging.Logger;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.DimensionInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.platform.ServiceException;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geotools.coverage.grid.io.StructuredGridCoverage2DReader;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.util.logging.Logging;
import org.opengis.coverage.grid.GridCoverageReader;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
/**
* Utility class that maps the coverage data sets and child coverage names
*
* @author Andrea Aime - GeoSolutions
*
*/
public class EOCoverageResourceCodec {
private static Logger LOGGER = Logging.getLogger(EOCoverageResourceCodec.class);
private static FilterFactory FF = CommonFactoryFinder.getFilterFactory2();
private static final String DATASET_SUFFIX = "_dss";
private static final String GRANULE_SEPARATOR = "_granule_";
private Catalog catalog;
public EOCoverageResourceCodec(Catalog catalog) {
this.catalog = catalog;
}
public String getDatasetName(CoverageInfo ci) {
if (!isValidDataset(ci)) {
throw new IllegalArgumentException("Specified covearge " + ci.prefixedName()
+ " is not a valid EO dataset");
}
return NCNameResourceCodec.encode(ci) + DATASET_SUFFIX;
}
/**
* Checks if the specified coverage is a valid dataset, e.g., it has the dataset flag enabled
* and time dimension, and has a structured grid coverage reader backing it
*
* @param ci
*
*/
public boolean isValidDataset(CoverageInfo ci) {
Boolean dataset = ci.getMetadata().get(WCSEOMetadata.DATASET.key, Boolean.class);
DimensionInfo time = ci.getMetadata().get(ResourceInfo.TIME, DimensionInfo.class);
try {
GridCoverageReader reader = ci.getGridCoverageReader(null, GeoTools.getDefaultHints());
boolean structured = reader instanceof StructuredGridCoverage2DReader;
return dataset != null && dataset && time != null && time.isEnabled()
&& structured;
} catch (IOException e) {
throw new ServiceException("Failed to locate the grid coverage reader for coverage " + ci.prefixedName());
}
}
/**
* Returns the coverage backed by the provided datasetId
*
* @param datasetId
* @return the coverage, or null if not found, or if not a coverage
*/
public CoverageInfo getDatasetCoverage(String datasetId) {
if (!datasetId.endsWith(DATASET_SUFFIX)) {
LOGGER.fine("Invalid dataset id " + datasetId + " it does not end with "
+ DATASET_SUFFIX);
return null;
}
String coverageName = datasetId.substring(0, datasetId.length() - DATASET_SUFFIX.length());
LayerInfo layer = NCNameResourceCodec.getCoverage(catalog, coverageName);
if (layer == null) {
LOGGER.fine("Invalid dataset id " + datasetId + " does not match any published dataset");
return null;
}
CoverageInfo ci = (CoverageInfo) layer.getResource();
if (!isValidDataset(ci)) {
LOGGER.fine("Invalid dataset id " + datasetId + " does not match any published dataset");
return null;
}
return ci;
}
/**
* Builds the identifier for a granule inside a coverage
*
*/
public String getGranuleId(CoverageInfo coverage, String featureId) {
return NCNameResourceCodec.encode(coverage) + GRANULE_SEPARATOR + featureId;
}
/**
* Returns the coverage containing the specified coverage, or null if the syntax is incorrect,
* the coverage does not exist, or it's not a dataset
*/
public CoverageInfo getGranuleCoverage(String granuleId) {
// does it have the expected lexical structure?
if(!granuleId.contains(GRANULE_SEPARATOR)) {
return null;
}
String[] splitted = granuleId.split(GRANULE_SEPARATOR);
if(splitted.length != 2) {
return null;
}
// do we have the coverage?
LayerInfo li = NCNameResourceCodec.getCoverage(catalog, splitted[0]);
if(li == null) {
return null;
}
// is it a EO dataset?
CoverageInfo ci = (CoverageInfo) li.getResource();
if(isValidDataset(ci)) {
return ci;
} else {
return null;
}
}
/**
* Given a valid granule id returns a Filter to extract it from the structured grid coverage reader
* @param coverageId
*
*/
public Filter getGranuleFilter(String granuleId) {
// does it have the expected lexical structure?
if(!granuleId.contains(GRANULE_SEPARATOR)) {
throw new IllegalArgumentException("Not a valid granule id: " + granuleId);
}
String[] splitted = granuleId.split(GRANULE_SEPARATOR);
if(splitted.length != 2) {
throw new IllegalArgumentException("Not a valid granule id: " + granuleId);
}
return FF.id(Collections.singleton(FF.featureId(splitted[1])));
}
public String getCoverageName(CoverageInfo ci) throws IOException {
return ci.getNativeCoverageName() != null ? ci.getNativeCoverageName()
: ci.getGridCoverageReader(null, null).getGridCoverageNames()[0];
}
}