Skip to content

Commit

Permalink
[GEOS-11377] RAT module: allow to reload/recompute the RAT
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed May 6, 2024
1 parent 3fa0b6f commit 062f846
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 10 deletions.
31 changes: 30 additions & 1 deletion doc/en/api/1.0.0/rat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,33 @@ paths:
404:
description: No PAM dataset found
400:
description: Invalid parameters used (e.g., band or classification not found)
description: Invalid parameters used (e.g., band or classification not found)
/workspaces/{workspace}/coveragestores/{store}/coverages/{coverage}/pam/reload:
post:
operationId: reloadPAMDataset
summary: Reloads/recomputes the PAM dataset
description: The PAM is often cached, this operation forces the source to reload it, eventually recomputing it, if for example it's a mosaic with a summary PAM dataset obtained from all its sources
tags:
- RasterAttributeTable
parameters:
- name: workspace
in: path
description: The name of the workspace
required: true
type: string
- name: store
in: path
description: The name of the coverage datastore
required: true
type: string
- name: coverage
in: path
description: The name of the coverage
required: true
type: string
responses:
200:
description: OK
404:
description: No PAM dataset found

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
import org.geoserver.rest.RestBaseController;
import org.geoserver.rest.RestException;
import org.geoserver.rest.catalog.AbstractCatalogController;
import org.geotools.api.data.ResourceInfo;
import org.geotools.api.style.Style;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.coverage.grid.io.PAMResourceInfo;
import org.geotools.util.logging.Logging;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -68,6 +71,20 @@ public String getRasterAttributeTable(

private CoverageRATs getRATSupport(
String workspaceName, String storeName, String coverageName) {
CoverageInfo coverage = getCoverageInfo(workspaceName, storeName, coverageName);

CoverageRATs rats = new CoverageRATs(catalog, coverage);
if (rats.getPAMDataset() == null) {
throw new ResourceNotFoundException(
format(
"No PAMDataset found for coverage: '%s:%s'",
workspaceName, coverageName));
}
return rats;
}

private CoverageInfo getCoverageInfo(
String workspaceName, String storeName, String coverageName) {
WorkspaceInfo wsInfo = catalog.getWorkspaceByName(workspaceName);
if (wsInfo == null) {
// could not find the namespace associated with the desired workspace
Expand All @@ -88,15 +105,7 @@ private CoverageRATs getRATSupport(
throw new ResourceNotFoundException(
format("No such coverage: '%s' in store '%s'", coverageName, storeName));
}

CoverageRATs rats = new CoverageRATs(catalog, coverage);
if (rats.getPAMDataset() == null) {
throw new ResourceNotFoundException(
format(
"No PAMDataset found for coverage: '%s:%s'",
workspaceName, coverageName));
}
return rats;
return coverage;
}

@PostMapping
Expand Down Expand Up @@ -161,4 +170,30 @@ public ResponseEntity create(
return new ResponseEntity<>(
"", headers, exists ? HttpStatus.SEE_OTHER : HttpStatus.CREATED);
}

@PostMapping(path = "/reload")
public void reload(
@PathVariable String workspaceName,
@PathVariable String storeName,
@PathVariable String coverageName)
throws IOException {
CoverageInfo ci = getCoverageInfo(workspaceName, storeName, coverageName);
GridCoverage2DReader reader =
(GridCoverage2DReader) ci.getStore().getGridCoverageReader(null, null);
ResourceInfo resourceInfo = reader.getInfo(ci.getNativeCoverageName());
if (!(resourceInfo instanceof PAMResourceInfo)) {
throw new RestException(
format(
"No Raster Attribute Table found for coverage '%s:%s'",
workspaceName, coverageName),
HttpStatus.BAD_REQUEST);
}
PAMResourceInfo pamInfo = (PAMResourceInfo) resourceInfo;
// if the reload does not work, a clear should help (e.g. with GeoTIFF)
// as the PAM is normally cached in memory. The mosaic is the odd case that
// needs the full reload, as it caches the summary PAM from all its sources
if (!pamInfo.reloadPAMDataset()) {
catalog.getResourcePool().clear(ci);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,44 @@ public void testGetPAMDataset() throws Exception {
"1", "count(/PAMDataset/PAMRasterBand/GDALRasterAttributeTable)", doc);
}

@Test
public void testReloadPAMDataset() throws Exception {
MockHttpServletResponse response =
getAsServletResponse(
"rest/workspaces/cite/coveragestores/rat/coverages/rat/pam.xml");
assertEquals(200, response.getStatus());
assertThat(response.getContentType(), Matchers.startsWith("application/xml"));
Document doc = dom(getBinaryInputStream(response));
// check the first entry has green color
assertXpathEvaluatesTo(
"green",
"/PAMDataset/PAMRasterBand/GDALRasterAttributeTable/Row[@index=0]/F[3]",
doc);

// copy over a RAT with a different color
GeoServerDataDirectory dd = getDataDirectory();
Resource aux = dd.get("rat", "rat.tiff.aux.xml");
Class<RasterAttributeTableConfigTest> clazz = RasterAttributeTableConfigTest.class;
try (InputStream is = clazz.getResourceAsStream("rat.tiff.aux2.xml");
OutputStream os = aux.out()) {
IOUtils.copy(is, os);
os.close();
}

// force reload
response =
postAsServletResponse(
"rest/workspaces/cite/coveragestores/rat/coverages/rat/pam/reload", "");
assertEquals(200, response.getStatus());

// grab again and check color
doc = getAsDOM("rest/workspaces/cite/coveragestores/rat/coverages/rat/pam.xml");
assertXpathEvaluatesTo(
"olive",
"/PAMDataset/PAMRasterBand/GDALRasterAttributeTable/Row[@index=0]/F[3]",
doc);
}

@Test
public void testCreateStyle() throws Exception {
String createCommand =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<PAMDataset>
<PAMRasterBand band="1">
<Description>Elevation</Description>
<UnitType>m</UnitType>
<GDALRasterAttributeTable tableType="thematic">
<FieldDefn index="0">
<Name>con_min</Name>
<Type>1</Type>
<Usage>3</Usage>
</FieldDefn>
<FieldDefn index="1">
<Name>con_max</Name>
<Type>1</Type>
<Usage>4</Usage>
</FieldDefn>
<FieldDefn index="2">
<Name>test</Name>
<Type>2</Type>
<Usage>0</Usage>
</FieldDefn>
<Row index="0">
<F>1.000000023841858</F>
<F>1.200000023841858</F>
<F>olive</F>
</Row>
<Row index="1">
<F>1.4</F>
<F>1.6</F>
<F>white</F>
</Row>
<Row index="2">
<F>2.4</F>
<F>2.6</F>
<F>gold</F>
</Row>
<Row index="3">
<F>5.099999809265137</F>
<F>5.299999809265136</F>
<F>blue</F>
</Row>
<Row index="4">
<F>7.200000190734864</F>
<F>7.400000190734863</F>
<F>red</F>
</Row>
<Row index="5">
<F>9.000000381469727</F>
<F>9.200000381469726</F>
<F>orange</F>
</Row>
<Row index="6">
<F>11.00000038146973</F>
<F>11.20000038146973</F>
<F>black</F>
</Row>
<Row index="7">
<F>12.09999980926514</F>
<F>12.29999980926514</F>
<F>purple</F>
</Row>
</GDALRasterAttributeTable>
<Metadata>
<MDI key="STATISTICS_MAXIMUM">12.199999809265</MDI>
<MDI key="STATISTICS_MEAN">6.2500000745058</MDI>
<MDI key="STATISTICS_MINIMUM">1.1000000238419</MDI>
<MDI key="STATISTICS_STDDEV">4.0681691852786</MDI>
<MDI key="STATISTICS_VALID_PERCENT">100</MDI>
</Metadata>
</PAMRasterBand>
</PAMDataset>

0 comments on commit 062f846

Please sign in to comment.