Skip to content

Commit

Permalink
[GEOS-8838] Allow update of products by PUTting ZIP file too in OpenS…
Browse files Browse the repository at this point in the history
…earch EO REST API
  • Loading branch information
aaime committed Jul 10, 2018
1 parent a1e9e57 commit b6037c9
Show file tree
Hide file tree
Showing 9 changed files with 705 additions and 89 deletions.
7 changes: 6 additions & 1 deletion doc/en/user/source/community/opensearch-eo/automation.rst
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ A collection.zip, sent as a PUT request to ``rest/collections`` would contain th
Product components Product components
`````````````````` ``````````````````


A product.zip, sent as a PUT request to ``rest/collections/<theCollection>/products`` would contain the following files: A product.zip, sent as a POST request to ``rest/collections/<theCollection>/products`` would contain the following files:


.. list-table:: .. list-table::
:widths: 10 10 80 :widths: 10 10 80
Expand Down Expand Up @@ -91,6 +91,11 @@ A product.zip, sent as a PUT request to ``rest/collections/<theCollection>/produ
Could be a single file, a list of files split by area, or a list of files representing the Could be a single file, a list of files split by area, or a list of files representing the
various bands of a multispectral product. various bands of a multispectral product.


It is also possible to send the zip file on the ``rest/collections/<theCollection>/products/<theProduct>``
resource as a PUT request, it will update an existing product by replacing the parts contained
in the file. Parts missing from the file will be kept unchanged, to remove them run an explicit
DELETE request on their respective REST resources.

Template variable expansion Template variable expansion
--------------------------- ---------------------------


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -349,12 +349,19 @@ public void putProductJson(
// check the product exists // check the product exists
queryProduct(collection, product, q -> {}); queryProduct(collection, product, q -> {});


runTransactionOnProductStore(fs -> updateProductInternal(collection, product, feature, fs));
}

private void updateProductInternal(
String collection, String product, SimpleFeature feature, FeatureStore fs)
throws IOException {
// prepare the update, need to convert each field into a Name/Value couple // prepare the update, need to convert each field into a Name/Value couple
Feature productFeature = simpleToComplex(feature, getProductSchema(), PRODUCT_HREFS); Feature productFeature = simpleToComplex(feature, getProductSchema(), PRODUCT_HREFS);
List<Name> names = new ArrayList<>(); List<Name> names = new ArrayList<>();
List<Object> values = new ArrayList<>(); List<Object> values = new ArrayList<>();
for (Property p : productFeature.getProperties()) { for (Property p : productFeature.getProperties()) {
// skip over the large/complex attributes that are being modified via separate calls // skip over the large/complex attributes that are being modified via
// separate calls
final Name propertyName = p.getName(); final Name propertyName = p.getName();
if (OpenSearchAccess.METADATA_PROPERTY_NAME.equals(propertyName) if (OpenSearchAccess.METADATA_PROPERTY_NAME.equals(propertyName)
|| OpenSearchAccess.OGC_LINKS_PROPERTY_NAME.equals(propertyName) || OpenSearchAccess.OGC_LINKS_PROPERTY_NAME.equals(propertyName)
Expand All @@ -367,8 +374,8 @@ public void putProductJson(
Name[] attributeNames = (Name[]) names.toArray(new Name[names.size()]); Name[] attributeNames = (Name[]) names.toArray(new Name[names.size()]);
Object[] attributeValues = (Object[]) values.toArray(); Object[] attributeValues = (Object[]) values.toArray();
Filter filter = getProductFilter(collection, product); Filter filter = getProductFilter(collection, product);
runTransactionOnProductStore(
fs -> fs.modifyFeatures(attributeNames, attributeValues, filter)); fs.modifyFeatures(attributeNames, attributeValues, filter);
} }


@DeleteMapping(path = "{product:.+}") @DeleteMapping(path = "{product:.+}")
Expand Down Expand Up @@ -746,4 +753,109 @@ FeatureType getProductSchema() throws IOException {
final FeatureType schema = productSource.getSchema(); final FeatureType schema = productSource.getSchema();
return schema; return schema;
} }

@PutMapping(path = "{product:.+}", consumes = MediaTypeExtensions.APPLICATION_ZIP_VALUE)
public void putProductZip(
@PathVariable(name = "collection", required = true) String collection,
@PathVariable(name = "product", required = true) String product,
HttpServletRequest request,
InputStream body)
throws IOException, URISyntaxException {
// check the collection and product actually exist
queryCollection(collection, q -> {});
queryProduct(collection, product, q -> {});

// grab and process the parts
Map<ProductPart, byte[]> parts = parsePartsFromZip(body, ProductPart.values());

// process the product part
final byte[] productPayload = parts.get(ProductPart.Product);
SimpleFeature jsonFeature;
if (productPayload != null) {
jsonFeature = parseGeoJSONFeature("product.json", productPayload);
// get the JSON and check consistency
String jsonProductId = (String) jsonFeature.getAttribute("eop:identifier");
String jsonParentId = (String) jsonFeature.getAttribute("eop:parentIdentifier");
if (!collection.equals(jsonParentId)) {
throw new RestException(
"product.json file refers to parentId "
+ jsonParentId
+ " but the HTTP resource refers to "
+ collection,
HttpStatus.BAD_REQUEST);
}
if (!product.equals(jsonProductId)) {
throw new RestException(
"product.json file refers to product "
+ jsonProductId
+ " but the HTTP resource refers to "
+ product,
HttpStatus.BAD_REQUEST);
}
} else {
jsonFeature = null;
}

// grab the other parts
byte[] description = parts.get(ProductPart.Description);
byte[] metadata = parts.get(ProductPart.Metadata);
byte[] thumbnail = parts.get(ProductPart.Thumbnail);
byte[] rawLinks = parts.get(ProductPart.OwsLinks);
SimpleFeatureCollection linksCollection;
if (rawLinks != null) {
OgcLinks links = parseJSON(OgcLinks.class, rawLinks);
linksCollection = beansToLinksCollection(links);
} else {
linksCollection = null;
}
byte[] rawGranules = parts.get(ProductPart.Granules);
SimpleFeatureCollection granulesCollection;
if (rawGranules != null) {
granulesCollection = parseGeoJSONFeatureCollection("granules.json", rawGranules);
} else {
granulesCollection = null;
}

// update the feature and accessory bits
runTransactionOnProductStore(
fs -> {
if (jsonFeature != null) {
updateProductInternal(collection, product, jsonFeature, fs);
}

final String nsURI = fs.getSchema().getName().getNamespaceURI();
Filter filter = getProductFilter(collection, product);

if (description != null) {
String descriptionString = new String(description);
fs.modifyFeatures(
new NameImpl(nsURI, OpenSearchAccess.DESCRIPTION),
descriptionString,
filter);
}

if (metadata != null) {
String descriptionString = new String(metadata);
fs.modifyFeatures(
OpenSearchAccess.METADATA_PROPERTY_NAME, descriptionString, filter);
}

if (linksCollection != null) {
fs.modifyFeatures(
OpenSearchAccess.OGC_LINKS_PROPERTY_NAME, linksCollection, filter);
}

if (thumbnail != null) {
fs.modifyFeatures(
OpenSearchAccess.QUICKLOOK_PROPERTY_NAME, thumbnail, filter);
}

if (granulesCollection != null) {
fs.modifyFeatures(
new NameImpl(nsURI, OpenSearchAccess.GRANULES),
granulesCollection,
filter);
}
});
}
} }

0 comments on commit b6037c9

Please sign in to comment.