Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GEOS-6809] WCS 2.0 DescribeCoverage should be able to handle single …
…granules
- Loading branch information
1 parent
494a23a
commit d480277
Showing
9 changed files
with
417 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
223 changes: 223 additions & 0 deletions
223
...s2_0-eo/core/src/main/java/org/geoserver/wcs2_0/eo/response/GranuleCoverageExtension.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved | ||
* This code is licensed under the GPL 2.0 license, available at the root | ||
* application directory. | ||
*/ | ||
package org.geoserver.wcs2_0.eo.response; | ||
|
||
import java.io.IOException; | ||
import java.io.Serializable; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import org.geoserver.catalog.CoverageInfo; | ||
import org.geoserver.catalog.DimensionInfo; | ||
import org.geoserver.catalog.ResourceInfo; | ||
import org.geoserver.config.GeoServer; | ||
import org.geoserver.wcs.WCSInfo; | ||
import org.geoserver.wcs2_0.eo.EOCoverageResourceCodec; | ||
import org.geoserver.wcs2_0.eo.WCSEOMetadata; | ||
import org.geoserver.wcs2_0.eo.response.DescribeEOCoverageSetTransformer.CoverageGranules; | ||
import org.geoserver.wcs2_0.exception.WCS20Exception; | ||
import org.geoserver.wcs2_0.util.WCS20DescribeCoverageExtension; | ||
import org.geotools.coverage.grid.io.DimensionDescriptor; | ||
import org.geotools.coverage.grid.io.GranuleSource; | ||
import org.geotools.coverage.grid.io.StructuredGridCoverage2DReader; | ||
import org.geotools.data.Query; | ||
import org.geotools.data.simple.SimpleFeatureCollection; | ||
import org.geotools.data.simple.SimpleFeatureIterator; | ||
import org.geotools.factory.GeoTools; | ||
import org.geotools.util.logging.Logging; | ||
import org.opengis.feature.simple.SimpleFeature; | ||
|
||
/** | ||
* Extension point implementing {@link WCS20DescribeCoverageExtension} that handles the granules for Structured Coverages | ||
* | ||
* @author Nicola Lagomarsini - GeoSolutions | ||
* | ||
*/ | ||
public class GranuleCoverageExtension implements WCS20DescribeCoverageExtension { | ||
/** Constant used as separator for the granule definition */ | ||
private static final String GRANULE_SEPARATOR = "_granule_"; | ||
|
||
private static final Logger LOGGER = Logging.getLogger(GranuleCoverageExtension.class); | ||
|
||
/** Parser used for decoding the coverageId parameter */ | ||
private EOCoverageResourceCodec codec; | ||
|
||
/** GeoServer instance used for checking if the EO extension is enabled */ | ||
private GeoServer geoserver; | ||
|
||
public GranuleCoverageExtension(GeoServer geoServer, EOCoverageResourceCodec codec) { | ||
this.codec = codec; | ||
this.geoserver = geoServer; | ||
} | ||
|
||
@Override | ||
public String handleCoverageId(String coverageId) { | ||
if (isEOEnabled()) { | ||
CoverageInfo granuleCoverage = codec.getGranuleCoverage(coverageId); | ||
if (granuleCoverage != null && codec.isValidDataset(granuleCoverage)) { | ||
return getCoverageId(coverageId); | ||
} | ||
return coverageId; | ||
} | ||
|
||
return coverageId; | ||
} | ||
|
||
@Override | ||
public String handleEncodedId(String encodedId, String coverageId) { | ||
if (isEOEnabled()) { | ||
CoverageInfo granuleCoverage = codec.getGranuleCoverage(coverageId); | ||
if (granuleCoverage != null && codec.isValidDataset(granuleCoverage)) { | ||
return codec.getGranuleId(granuleCoverage, getGranuleId(coverageId)); | ||
} | ||
return coverageId; | ||
} | ||
|
||
return coverageId; | ||
} | ||
|
||
@Override | ||
public CoverageInfo handleCoverageInfo(String coverageId, CoverageInfo ci) { | ||
CoverageInfo info = null; | ||
if (isEOEnabled()) { | ||
if (codec.getGranuleCoverage(coverageId) != null && codec.isValidDataset(ci)) { | ||
SimpleFeatureIterator it = null; | ||
try { | ||
// Getting the structured coverage reader | ||
StructuredGridCoverage2DReader reader = (StructuredGridCoverage2DReader) ci | ||
.getGridCoverageReader(null, GeoTools.getDefaultHints()); | ||
String name; | ||
// Getting the coverage name | ||
name = codec.getCoverageName(ci); | ||
// Query the reader | ||
GranuleSource source = reader.getGranules(name, true); | ||
Query q = new Query(); | ||
SimpleFeatureCollection collection = source.getGranules(q); | ||
|
||
// create a GranuleCoverageInfo object for the single granule | ||
if (!collection.isEmpty()) { | ||
List<DimensionDescriptor> descriptors = getActiveDimensionDescriptor(ci, | ||
reader, name); | ||
it = collection.features(); | ||
if (it.hasNext()) { | ||
SimpleFeature feature = it.next(); | ||
info = new GranuleCoverageInfo(ci, feature, descriptors); | ||
} | ||
} | ||
if (info == null) { | ||
if (LOGGER.isLoggable(Level.FINE)) { | ||
LOGGER.log(Level.FINE, "No granule found for the granuleId: " | ||
+ getGranuleId(coverageId)); | ||
} | ||
} | ||
} catch (IOException e) { | ||
if (LOGGER.isLoggable(Level.SEVERE)) { | ||
LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||
} | ||
throw new WCS20Exception(e); | ||
} finally { | ||
if (it != null) { | ||
try { | ||
it.close(); | ||
} catch (Exception e) { | ||
if (LOGGER.isLoggable(Level.SEVERE)) { | ||
LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (info == null) { | ||
info = ci; | ||
} | ||
return info; | ||
} | ||
|
||
/** | ||
* CHecks if the EO extension is enabled globally | ||
* | ||
* @return true if the EO extension is enabled | ||
*/ | ||
public boolean isEOEnabled() { | ||
WCSInfo wcs = geoserver.getService(WCSInfo.class); | ||
Boolean enabled = wcs.getMetadata().get(WCSEOMetadata.ENABLED.key, Boolean.class); | ||
return Boolean.TRUE.equals(enabled); | ||
} | ||
|
||
/** | ||
* Returns the coverage identifier related to the specified coverageId, or null if the syntax is incorrect | ||
* | ||
* @return the coverageId related to the following coverageId parameter (with the _granule_ extension) | ||
*/ | ||
public String getCoverageId(String coverageId) { | ||
// does it have the expected lexical structure? | ||
if (!coverageId.contains(GRANULE_SEPARATOR)) { | ||
return null; | ||
} | ||
String[] splitted = coverageId.split(GRANULE_SEPARATOR); | ||
if (splitted.length != 2) { | ||
return null; | ||
} else { | ||
return splitted[0]; | ||
} | ||
} | ||
|
||
/** | ||
* Returns the coverage identifier related to the specified coverageId, or null if the syntax is incorrect | ||
* | ||
* @return the coverageId related to the following coverageId parameter (with the _granule_ extension) | ||
*/ | ||
public String getGranuleId(String coverageId) { | ||
// does it have the expected lexical structure? | ||
if (!coverageId.contains(GRANULE_SEPARATOR)) { | ||
return null; | ||
} | ||
String[] splitted = coverageId.split(GRANULE_SEPARATOR); | ||
if (splitted.length != 2) { | ||
return null; | ||
} else { | ||
return splitted[1]; | ||
} | ||
} | ||
|
||
/** | ||
* This method returns the active dimensions | ||
*/ | ||
private List<DimensionDescriptor> getActiveDimensionDescriptor(CoverageInfo ci, | ||
StructuredGridCoverage2DReader reader, String name) throws IOException { | ||
// map the source descriptors for easy retrieval | ||
Map<String, DimensionDescriptor> sourceDescriptors = new HashMap<String, DimensionDescriptor>(); | ||
for (DimensionDescriptor dimensionDescriptor : reader.getDimensionDescriptors(name)) { | ||
sourceDescriptors.put(dimensionDescriptor.getName().toUpperCase(), dimensionDescriptor); | ||
} | ||
// select only those that have been activated vai the GeoServer GUI | ||
List<DimensionDescriptor> enabledDescriptors = new ArrayList<DimensionDescriptor>(); | ||
for (Entry<String, Serializable> entry : ci.getMetadata().entrySet()) { | ||
if (entry.getValue() instanceof DimensionInfo) { | ||
DimensionInfo di = (DimensionInfo) entry.getValue(); | ||
if (di.isEnabled()) { | ||
String dimensionName = entry.getKey(); | ||
if (dimensionName.startsWith(ResourceInfo.CUSTOM_DIMENSION_PREFIX)) { | ||
dimensionName = dimensionName | ||
.substring(ResourceInfo.CUSTOM_DIMENSION_PREFIX.length()); | ||
} | ||
DimensionDescriptor selected = sourceDescriptors.get(dimensionName | ||
.toUpperCase()); | ||
if (selected != null) { | ||
enabledDescriptors.add(selected); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return enabledDescriptors; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
...on/wcs2_0-eo/core/src/test/java/org/geoserver/wcs2_0/eo/GranuleCoverageExtensionTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved | ||
* This code is licensed under the GPL 2.0 license, available at the root | ||
* application directory. | ||
*/ | ||
package org.geoserver.wcs2_0.eo; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertTrue; | ||
|
||
import java.io.IOException; | ||
|
||
import org.geoserver.catalog.Catalog; | ||
import org.geoserver.catalog.CoverageInfo; | ||
import org.geoserver.platform.GeoServerExtensions; | ||
import org.geoserver.wcs2_0.eo.response.GranuleCoverageExtension; | ||
import org.geoserver.wcs2_0.eo.response.GranuleCoverageInfo; | ||
import org.geoserver.wcs2_0.eo.response.SingleGranuleGridCoverageReader; | ||
import org.junit.Test; | ||
import org.opengis.coverage.grid.GridCoverageReader; | ||
|
||
/** | ||
* This class is used for testing the {@link GranuleCoverageExtensionTest} class. | ||
* | ||
* @author Nicola Lagomarsini | ||
*/ | ||
public class GranuleCoverageExtensionTest extends WCSEOTestSupport { | ||
|
||
@Test | ||
public void testDecodeGranule() { | ||
String qualifiedName = "sf__timeranges_granule_timeranges.1"; | ||
// Getting the extension | ||
GranuleCoverageExtension gce = GeoServerExtensions.bean(GranuleCoverageExtension.class); | ||
// Ensure it is enabled the EO extension | ||
assertTrue(gce.isEOEnabled()); | ||
// Handling the id | ||
String coverageId = gce.handleCoverageId(qualifiedName); | ||
assertEquals("sf__timeranges", coverageId); | ||
String granuleId = gce.getGranuleId(qualifiedName); | ||
assertEquals("timeranges.1", granuleId); | ||
String covId = gce.getCoverageId(qualifiedName); | ||
assertEquals("sf__timeranges", covId); | ||
} | ||
|
||
@Test | ||
public void testEncodeCoverage() throws IOException { | ||
// Getting the extension | ||
GranuleCoverageExtension gce = GeoServerExtensions.bean(GranuleCoverageExtension.class); | ||
// Getting the Catalog | ||
Catalog catalog = getCatalog(); | ||
|
||
// Get the coverage for the watertemp layer | ||
CoverageInfo ci = catalog.getCoverageByName("sf:timeranges"); | ||
// Ensure it is enabled the EO extension | ||
assertTrue(gce.isEOEnabled()); | ||
|
||
// Get the CoverageInfo for the single Granule | ||
String granuleId = "sf__timeranges_granule_timeranges.1"; | ||
CoverageInfo coverageInfo = gce.handleCoverageInfo(granuleId, ci); | ||
assertTrue(coverageInfo instanceof GranuleCoverageInfo); | ||
GridCoverageReader gridCoverageReader = coverageInfo.getGridCoverageReader(null, null); | ||
assertTrue(gridCoverageReader instanceof SingleGranuleGridCoverageReader); | ||
} | ||
} |
Oops, something went wrong.