Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GEOS-11377] RAT module: allow to reload/recompute the RAT #7583

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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>