Skip to content

Commit 519eb0d

Browse files
authored
Merge pull request #679 from Esri/Stac_Fixes
Fixed Dcat request
2 parents 811e352 + 5f4b265 commit 519eb0d

File tree

15 files changed

+256
-135
lines changed

15 files changed

+256
-135
lines changed

geoportal-search/src/main/resources/gs/base/Request.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,10 @@
6363

6464
getSortOptions: {writable:true,value:function() {
6565
// &sortField=title,modified&sortOrder=desc,asc // Portal syntax
66-
// &sort={"title.keyword":{"order":"asc","unmapped_type":"keyword"}} // Elasticsearch syntax
66+
// &sort=title:desc&sort=modified:asc // Elasticsearch syntax
6767
// &sortBy=title:D,modified:A // CSW syntax
6868
var idx, sortField, sortOrder, sortOptions = null;
6969
var values = this.getParameterValues("sort");
70-
if(values!== null)
71-
{
72-
return values; //For ElasticSearch, it will be handled in ElasticTarget
73-
}
7470
if (values === null || values.length === 0) {
7571
values = this.getParameterValues("sortBy");
7672
}

geoportal-search/src/main/resources/gs/context/nashorn/NashornContext.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,7 @@
219219
},
220220

221221
sendHttpRequest: function(url, data, dataContentType, options) {
222-
// print("url",url);
223-
// print("data",data);
222+
//print("url",url);
224223
var result = null;
225224
var br = null, br2 = null, wr = null;
226225
var sw = new java.io.StringWriter();
@@ -230,7 +229,7 @@
230229
var u = new java.net.URL(url);
231230

232231
var client = com.esri.geoportal.lib.elastic.http.ElasticClient.newClient();;
233-
//print(u);
232+
//print("data ",data);
234233
if(options && options.useHttps)
235234
{
236235
var ssl_ctx = javax.net.ssl.SSLContext.getInstance("TLS");

geoportal-search/src/main/resources/gs/target/elastic/ElasticTarget.js

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -357,26 +357,64 @@
357357
}},
358358

359359
prepareSort: {writable:true,value:function(task,targetRequest) {
360-
var sortables = this.schema.sortables;
361-
if (!sortables) return;
362-
363-
var sort = [], sortOptions = task.request.getSortOptions();
364-
//print("sortOptions",sortOptions);
365-
if (Array.isArray(sortOptions)) {
366-
sortOptions.forEach(function(sortOption){
367-
//print("sortOption ",sortOption);
368-
369-
try {
370-
sort = JSON.parse(sortOption);
371-
} catch (e) {
372-
sort = sortOption;
373-
}
374-
});
375-
}
376-
if (sort) {
377-
targetRequest.searchCriteria["sort"] = sort;
360+
var sortables = this.schema.sortables;
361+
if (!sortables) return;
362+
print("sortables ",JSON.stringify(sortables));
363+
var getField = function(v) {
364+
v = v.toLowerCase();
365+
for (var k in sortables) {
366+
if (sortables.hasOwnProperty(k)) {
367+
if (v === k.toLowerCase()) {
368+
return sortables[k];
369+
}
370+
}
378371
}
379-
}},
372+
return null;
373+
};
374+
375+
var sort = [], sortOptions = task.request.getSortOptions();
376+
//print("ElasticTarget sortOptions ",JSON.stringify(sortOptions));
377+
if (Array.isArray(sortOptions)) {
378+
sortOptions.forEach(function(sortOption){
379+
var field = getField(sortOption.field);
380+
//print("sort field ",field);
381+
if (typeof field === "string" && field.length > 0) {
382+
var option = {};
383+
if (sortOption.order === "asc") {
384+
if(field ==='title')
385+
{
386+
//print("sort field title asc");
387+
option['title.keyword']={"order": "asc", "unmapped_type": "keyword"}
388+
}
389+
else{
390+
//print("sort field not title");
391+
option[field] = "asc";
392+
}
393+
394+
395+
} else if (sortOption.order === "desc") {
396+
if(field ==='title')
397+
{
398+
//print("sort field title desc");
399+
option['title.keyword']={"order": "desc", "unmapped_type": "keyword"}
400+
}
401+
else{
402+
//print("sort field not title desc");
403+
option[field] = "desc";
404+
}
405+
406+
} else {
407+
option = field;
408+
}
409+
sort = option;
410+
}
411+
});
412+
}
413+
if (sort) {
414+
targetRequest.searchCriteria["sort"] = sort;
415+
//console.log("final sort ", JSON.stringify(targetRequest.searchCriteria["sort"]));
416+
}
417+
}},
380418

381419
prepareTimePeriod: {writable:true,value:function(task,targetRequest) {
382420
var period = task.request.getTimePeriod();

geoportal/src/main/java/com/esri/geoportal/dcat/DcatBuilder.java

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,7 @@ private String getSelfInfo() {
161161
try {
162162
JsonObjectBuilder access = Json.createObjectBuilder();
163163
access.add("supportsApprovalStatus",com.esri.geoportal.context.GeoportalContext.getInstance().getSupportsApprovalStatus());
164-
access.add("supportsGroupBasedAccess",com.esri.geoportal.context.GeoportalContext.getInstance().getSupportsGroupBasedAccess());
165-
com.esri.geoportal.context.AppUser user = null;
166-
if (user != null && user.getUsername() != null) {
167-
access.add("username",user.getUsername());
168-
access.add("isAdmin",user.isAdmin());
169-
if (com.esri.geoportal.context.GeoportalContext.getInstance().getSupportsGroupBasedAccess()) {
170-
JsonArrayBuilder jsaGroups = Json.createArrayBuilder();
171-
List<com.esri.geoportal.base.security.Group> groups = user.getGroups();
172-
if (groups != null) {
173-
for (com.esri.geoportal.base.security.Group group: groups) {
174-
jsaGroups.add(group.id);
175-
}
176-
}
177-
access.add("groups",jsaGroups);
178-
}
179-
}
164+
access.add("supportsGroupBasedAccess",com.esri.geoportal.context.GeoportalContext.getInstance().getSupportsGroupBasedAccess());
180165
elastic.add("access",access);
181166
} catch (Throwable t) {
182167
LOGGER.warn(String.format("Warning getting self info."), t);

geoportal/src/main/java/com/esri/geoportal/search/STACService.java

Lines changed: 99 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import java.util.logging.Level;
3535
import java.util.regex.Matcher;
3636
import java.util.regex.Pattern;
37+
import java.util.stream.Collectors;
38+
import java.util.stream.Stream;
3739

3840
import javax.json.JsonArray;
3941
import javax.json.JsonObject;
@@ -70,8 +72,10 @@
7072
import com.esri.geoportal.service.stac.Collection;
7173
import com.esri.geoportal.service.stac.GeometryServiceClient;
7274
import com.esri.geoportal.service.stac.StacContext;
75+
import com.jayway.jsonpath.Configuration;
7376
import com.jayway.jsonpath.DocumentContext;
7477
import com.jayway.jsonpath.JsonPath;
78+
import com.jayway.jsonpath.Option;
7579

7680
import net.minidev.json.JSONArray;
7781
import net.minidev.json.JSONObject;
@@ -495,7 +499,8 @@ public Response getItems(@Context HttpServletRequest hsr,
495499
else
496500
response = client.sendGet(url);
497501

498-
responseJSON = this.prepareResponse(response, hsr, bbox, limit, datetime, null, null, "metadataItems", collectionId,null);
502+
responseJSON = this.prepareResponse(response, hsr, bbox, limit, datetime, null, null, "metadataItems", collectionId,null,
503+
null,null,outCRS, null, null);
499504

500505
// if reprojecting STAC geometries is supported and a
501506
// geometry service has been configured, try projecting
@@ -835,7 +840,7 @@ public Response search(@Context HttpServletRequest hsr, @QueryParam("limit") int
835840
{
836841
responseJSON = this.prepareResponse(response, hsr, bbox, limit, datetime,
837842
idList, intersects, "search",
838-
listOfCollections,null);
843+
listOfCollections,null, updated, created, outCRS, itemStatus, filter);
839844

840845
// if re-projecting STAC geometries is supported and a
841846
// geometry service has been configured, try projecting from internal CRS (4326) to requested outCRS
@@ -884,7 +889,8 @@ public Response search(@Context HttpServletRequest hsr, @RequestBody String body
884889
JsonArray bboxJsonArr = (requestPayload.containsKey("bbox") ? requestPayload.getJsonArray("bbox") : null);
885890
JsonArray idArr = (requestPayload.containsKey("ids") ? requestPayload.getJsonArray("ids") : null);
886891
String outCRS = (requestPayload.containsKey("outCRS") ? requestPayload.getString("outCRS") : null);
887-
892+
search_after = (requestPayload.containsKey("search_after") ? requestPayload.getString("search_after") : search_after);
893+
888894
JsonArray collectionArr = (requestPayload.containsKey("collections")
889895
? requestPayload.getJsonArray("collections")
890896
: null);
@@ -971,14 +977,15 @@ public Response search(@Context HttpServletRequest hsr, @RequestBody String body
971977
queryMap.put("filterClause", filterClause); //filterQry);
972978
}
973979

974-
//Search request with outCRS is valid, if only one collection in collections param, otherwise 400
975-
if ((outCRS != null) && collectionArr!=null && collectionArr.size()>1)
976-
{
980+
//Search request with outCRS is valid, if only one collection in collections param, otherwise 400
981+
if ((outCRS != null) && collectionArr!=null && collectionArr.size()>1)
982+
{
977983
status = Response.Status.BAD_REQUEST;
978984
responseJSON = this.generateResponse("400", "Only one collection can be included in search param if search param includes outCRS ",null);
979985
return Response.status(status).header("Content-Type", "application/geo+json").entity(responseJSON).build();
980986

981-
}
987+
}
988+
982989
//Adding one extra so that next page can be figured out
983990
url = url + "/_search?size=" + (limit+1);
984991
query = StacHelper.prepareSearchQuery(queryMap, search_after);
@@ -1000,15 +1007,15 @@ public Response search(@Context HttpServletRequest hsr, @RequestBody String body
10001007
// if re-projecting STAC geometries is supported and a
10011008
// geometry service has been configured, try projecting
10021009
// from internal CRS (4326) to requested outCRS
1003-
if ((outCRS != null) && ("true".equals(sc.isCanStacGeomTransform())) && (!gc.getGeometryService().isEmpty())) {
1004-
LOGGER.debug("outCRS = " + outCRS + " - " + gc.getGeometryService());
1005-
1006-
JSONObject projectedResponseObj = projectSearchResults(responseJSON, "4326", outCRS);
1007-
responseJSON = projectedResponseObj.toString();
1008-
1009-
// done
1010-
LOGGER.debug("Project response -> " + responseJSON);
1011-
}
1010+
if ((outCRS != null) && ("true".equals(sc.isCanStacGeomTransform())) && (!gc.getGeometryService().isEmpty())) {
1011+
LOGGER.debug("outCRS = " + outCRS + " - " + gc.getGeometryService());
1012+
1013+
JSONObject projectedResponseObj = projectSearchResults(responseJSON, "4326", outCRS);
1014+
responseJSON = projectedResponseObj.toString();
1015+
1016+
// done
1017+
LOGGER.debug("Project response -> " + responseJSON);
1018+
}
10121019
}
10131020

10141021
} catch (InvalidParameterException e) {
@@ -1819,9 +1826,16 @@ private String prepareResponseSingleItem(String searchRes, String itemFileString
18191826
finalResponse = finalResponse.replaceAll("\\{collectionId\\}", collectionId);
18201827
return finalResponse;
18211828
}
1829+
1830+
private String prepareResponse(String searchRes, HttpServletRequest hsr, String bbox, int limit, String datetime,
1831+
String ids, String intersects, String requestType, String collectionId, String body ) {
1832+
return this.prepareResponse(searchRes, hsr, bbox, limit, datetime, ids, intersects, requestType, collectionId, body,
1833+
null, null, null, null, null);
1834+
}
18221835

18231836
private String prepareResponse(String searchRes, HttpServletRequest hsr, String bbox, int limit, String datetime,
1824-
String ids, String intersects, String requestType, String collectionId, String body) {
1837+
String ids, String intersects, String requestType, String collectionId, String body,
1838+
String updated,String created,String outCrs,String status,String filter) {
18251839

18261840
int numberMatched;
18271841
net.minidev.json.JSONArray items;
@@ -1898,18 +1912,15 @@ private String prepareResponse(String searchRes, HttpServletRequest hsr, String
18981912
}
18991913
String urlparam = "";
19001914
if (requestType.equalsIgnoreCase("searchPost")) {
1901-
JSONObject bodyObj =new JSONObject();
1902-
// In post request, search_after will be part of request body
1903-
if (body != null)
1904-
{
1905-
bodyObj = (JSONObject) JSONValue.parse(body);
1906-
if(search_after != null && search_after.length()>0)
1907-
bodyObj.appendField("search_after", search_after);
1908-
}
1915+
// Add search_after in urlparam
1916+
urlparam = (search_after != null ? "?search_after=" + search_after : "");
1917+
1918+
JSONObject bodyObj =new JSONObject();
19091919
if(nextLink)
19101920
linksContext.set("$.searchItem.links[1].body",(body != null ? bodyObj : ""));
19111921

19121922
} else {
1923+
// GET request, set everything as request parameters
19131924
if(nextLink)
19141925
{
19151926
linksContext.delete("$.searchItem.links[1].body");
@@ -1922,6 +1933,11 @@ private String prepareResponse(String searchRes, HttpServletRequest hsr, String
19221933
+ (search_after != null ? "&search_after=" + search_after : "")
19231934
+ (encodedIntersect != null ? "&intersects=" + encodedIntersect : "")
19241935
+ (ids != null ? "&ids=" + ids : "")
1936+
+ (updated != null ? "&updated=" + updated : "")
1937+
+ (created != null ? "&created=" + created : "")
1938+
+ (outCrs != null ? "&outCRS=" + outCrs : "")
1939+
+ (status != null ? "&status=" + status : "")
1940+
+ (filter != null ? "&filter=" + filter : "")
19251941
+((requestType.startsWith("search")) && collectionId != null ? "&collections=" + collectionId : "");
19261942
}
19271943
if (requestType.startsWith("metadataItems"))
@@ -1963,7 +1979,8 @@ private boolean populateFeature(DocumentContext featureContext, DocumentContext
19631979
featureContext.set("$.featurePropPath.id", searchItemCtx.read(val));
19641980

19651981
val = featureContext.read("$.featurePropPath.collection");
1966-
featureContext.set("$.featurePropPath.collection", searchItemCtx.read(val));
1982+
String collectionId = searchItemCtx.read(val).toString();
1983+
featureContext.set("$.featurePropPath.collection", collectionId);
19671984

19681985
// add bbox, geometry
19691986
this.setBbox(searchItemCtx, featureContext);
@@ -2027,26 +2044,69 @@ private boolean populateFeature(DocumentContext featureContext, DocumentContext
20272044
LOGGER.trace("No assets ($._source.assets) in this Stac record with id: " + recordId);
20282045

20292046
}
2030-
2031-
// Iterate properties, skip property if it is not available
2047+
2048+
//#680
2049+
//fill item with collection properties when not available in item, item property overrides default set in collection
2050+
Set<String> collectionPropKeySet = null;
2051+
JSONObject collectionPropObj = null;
2052+
ArrayList <String> propToBeAddedFromCollectionList = new ArrayList<String>();
2053+
2054+
Collection collection = new Collection(collectionId);
2055+
if(collection.getProperties() != null)
2056+
{
2057+
collectionPropObj = collection.getProperties();
2058+
if (collectionPropObj != null) {
2059+
collectionPropKeySet = collectionPropObj.keySet();
2060+
//Create a combined set of property keys from item and collection
2061+
Set<String> combinedPropSet = Stream.concat(propObjKeys.stream(), collectionPropKeySet.stream())
2062+
.collect(Collectors.toSet());
2063+
propObjKeys = combinedPropSet;
2064+
}
2065+
}
2066+
2067+
// Iterate properties, skip property if it is not available in item and collection
20322068
for (String propKey : propObjKeys) {
20332069
try {
2034-
propKeyVal = String.valueOf(propObj.get(propKey));
2035-
// If it is a json path, set values from search result
2036-
if (propKeyVal.startsWith("$")) {
2037-
if (searchItemCtx.read(propKeyVal) != null) {
2038-
featureContext.set("$.featurePropPath.properties." + propKey,
2039-
searchItemCtx.read(propKeyVal));
2070+
//it is item prop, try to fill from searched item
2071+
if(propObj.containsKey(propKey))
2072+
{
2073+
propKeyVal = String.valueOf(propObj.get(propKey));
2074+
// If it is a json path, set values from search result
2075+
if (propKeyVal.startsWith("$")) {
2076+
if (searchItemCtx.read(propKeyVal) != null) {
2077+
featureContext.set("$.featurePropPath.properties." + propKey,
2078+
searchItemCtx.read(propKeyVal));
2079+
}
20402080
}
20412081
}
2082+
//Not an Item prop, Collection prop
2083+
else
2084+
{
2085+
propToBeAddedFromCollectionList.add(propKey);
2086+
}
2087+
20422088
} catch (Exception e) {
2043-
// If json path not found or error in any property, remove this property in the
2044-
// end.
2045-
// if removed here, concurrentModificationException
2046-
propToBeRemovedList.add("$.featurePropPath.properties." + propKey);
2047-
LOGGER.trace("key: " + propKey + " could not be added. Reason : " + e.getMessage());
2089+
//item did not have this data, so check if it is available in collection prop. This will be added later from collection
2090+
if(collectionPropObj != null && collectionPropObj.containsKey(propKey))
2091+
{
2092+
propToBeAddedFromCollectionList.add(propKey);
2093+
}
2094+
// If json path not found in searchItemCtx.read(propKeyVal) or error in any property, remove this property in the
2095+
// end. if removed here, concurrentModificationException
2096+
else
2097+
{
2098+
propToBeRemovedList.add("$.featurePropPath.properties." + propKey);
2099+
LOGGER.trace("key: " + propKey + " could not be added. Reason : " + e.getMessage());
2100+
}
20482101
}
20492102
}
2103+
//Read updated item property object again and add keys from collection
2104+
HashMap<String, String> updatedPropObj = featureContext.read("$.featurePropPath.properties");
2105+
for(String prop: propToBeAddedFromCollectionList)
2106+
{
2107+
updatedPropObj.put(prop, collectionPropObj.getAsString(prop));
2108+
}
2109+
featureContext.set("$.featurePropPath.properties",updatedPropObj);
20502110

20512111
String linkSelfHref = featureContext.read("$.featurePropPath.links[0].href");
20522112
linkSelfHref = linkSelfHref.replaceAll("\\{itemId\\}", featureContext.read("$.featurePropPath.id").toString());

0 commit comments

Comments
 (0)