diff --git a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/dynamo/DynamoSpaceConfigClient.java b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/dynamo/DynamoSpaceConfigClient.java index 503e13fdef..e01f44d16d 100644 --- a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/dynamo/DynamoSpaceConfigClient.java +++ b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/dynamo/DynamoSpaceConfigClient.java @@ -390,7 +390,7 @@ private Future> getSpacesWithFullAccess(SpaceSelectionCondition sele if (propsQuery != null) { valueMap.put(":typeValue", "SPACE"); valueMap.put(":contentUpdatedAtValue", propsQuery.get(0).get(0).getValues().get(0)); - String operator = QueryOperation.getOperation(propsQuery.get(0).get(0).getOperation()); + String operator = QueryOperation.getOutputRepresentation(propsQuery.get(0).get(0).getOperation()); spaces.getIndex("type-contentUpdatedAt-index") .query(new QuerySpec() @@ -580,7 +580,7 @@ private Future filterByContentUpdatedAt(PropertiesQuery propsQuery, Set valueMap = new HashMap<>(); valueMap.put(":typeValue", "SPACE"); valueMap.put(":contentUpdatedAtValue", propsQuery.get(0).get(0).getValues().get(0)); - String operator = QueryOperation.getOperation(propsQuery.get(0).get(0).getOperation()); + String operator = QueryOperation.getOutputRepresentation(propsQuery.get(0).get(0).getOperation()); var contentUpdatedAtSpaceIds = new HashSet(); spaces.getIndex("type-contentUpdatedAt-index").query(new QuerySpec() .withKeyConditionExpression("#type = :typeValue and contentUpdatedAt " + operator + " :contentUpdatedAtValue") diff --git a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/jdbc/JDBCSpaceConfigClient.java b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/jdbc/JDBCSpaceConfigClient.java index 542fc91ea6..fc554b9a79 100644 --- a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/jdbc/JDBCSpaceConfigClient.java +++ b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/jdbc/JDBCSpaceConfigClient.java @@ -128,7 +128,7 @@ protected Future> getSelectedSpaces(Marker marker, SpaceAuthorizatio List contentUpdatedAtConjunctions = new ArrayList<>(); conjunctions.forEach(conj -> { conj.getValues().forEach(v -> { - contentUpdatedAtConjunctions.add("(cast(config->>'contentUpdatedAt' AS TEXT) "+ QueryOperation.getOperation(conj.getOperation()) + "'" +v + "' )"); + contentUpdatedAtConjunctions.add("(cast(config->>'contentUpdatedAt' AS TEXT) "+ QueryOperation.getOutputRepresentation(conj.getOperation()) + "'" +v + "' )"); }); }); whereConjunctions.add(String.join(" OR ", contentUpdatedAtConjunctions)); diff --git a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/memory/InMemSpaceConfigClient.java b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/memory/InMemSpaceConfigClient.java index c0b7fec1c7..80c97d7f63 100644 --- a/xyz-hub-service/src/main/java/com/here/xyz/hub/config/memory/InMemSpaceConfigClient.java +++ b/xyz-hub-service/src/main/java/com/here/xyz/hub/config/memory/InMemSpaceConfigClient.java @@ -91,7 +91,7 @@ protected Future> getSelectedSpaces(Marker marker, SpaceAuthorizatio propsQuery.forEach(conjunctions -> { conjunctions.forEach(conj -> { conj.getValues().forEach(v -> { - String operator = QueryOperation.getOperation(conj.getOperation()); + String operator = QueryOperation.getOutputRepresentation(conj.getOperation()); contentUpdatedAtList.add(operator); contentUpdatedAtList.add(v.toString()); }); diff --git a/xyz-hub-service/src/main/java/com/here/xyz/hub/rest/ApiParam.java b/xyz-hub-service/src/main/java/com/here/xyz/hub/rest/ApiParam.java index 5fbfb52735..ea36343e41 100644 --- a/xyz-hub-service/src/main/java/com/here/xyz/hub/rest/ApiParam.java +++ b/xyz-hub-service/src/main/java/com/here/xyz/hub/rest/ApiParam.java @@ -195,24 +195,6 @@ public static class Query { static final String DRY_RUN = "dryRun"; - private static Map operators = new HashMap() {{ - put("!=", QueryOperation.NOT_EQUALS); - put(">=", QueryOperation.GREATER_THAN_OR_EQUALS); - put("=gte=", QueryOperation.GREATER_THAN_OR_EQUALS); - put("<=", QueryOperation.LESS_THAN_OR_EQUALS); - put("=lte=", QueryOperation.LESS_THAN_OR_EQUALS); - put(">", QueryOperation.GREATER_THAN); - put("=gt=", QueryOperation.GREATER_THAN); - put("<", QueryOperation.LESS_THAN); - put("=lt=", QueryOperation.LESS_THAN); - put("=", QueryOperation.EQUALS); - put("@>", QueryOperation.CONTAINS); - put("=cs=", QueryOperation.CONTAINS); - }}; - - private static List shortOperators = new ArrayList<>(operators.keySet()); - - /** * Get access to the custom parsed query parameters. Used as a temporary replacement for context.queryParam until * https://github.com/vert-x3/issues/issues/380 is resolved. @@ -376,8 +358,8 @@ static PropertiesQuery getPropertiesQuery(RoutingContext context) { } /** - * Returns the first property found in the query string in the format of key-operator-value(s) - * @param query the query part in the url without the '?' symbol + * Returns the first property found in the query string in the format of: ` ` + * @param query the query part in the url without the '?' or '&' symbol * @param key the property to be searched * @param multiValue when true, checks for comma separated values, otherwise return the first value found * @return null in case none is found @@ -393,12 +375,12 @@ static PropertyQuery getPropertyQuery(String query, String key, boolean multiVal return null; } - int startIndex; - if ((startIndex=query.indexOf(key)) != -1) { + int startIndex = query.indexOf(key); + if (startIndex != -1) { String opValue = query.substring(startIndex + key.length()); // e.g. =eq=head - String operation = shortOperators + String operation = QueryOperation.inputRepresentations() .stream() - .sorted(Comparator.comparingInt(k->k.length() * -1)) // reverse a sorted list because u want to get the longer ops first. + .sorted(Comparator.comparingInt(k -> k.length() * -1)) // reverse a sorted list because u want to get the longer ops first. .filter(opValue::startsWith) // e.g. in case of key=eq=val, 2 ops will be filtered in: '=eq=' and '='. .findFirst() // The reversed sort plus the findFirst makes sure the =eq= is the one you are looking for. .orElse(null); // e.g. anything different from the allowed operators @@ -413,7 +395,7 @@ static PropertyQuery getPropertyQuery(String query, String key, boolean multiVal return new PropertyQuery() .withKey(key) - .withOperation(operators.get(operation)) + .withOperation(QueryOperation.fromInputRepresentation(operation)) .withValues(values); } @@ -442,8 +424,8 @@ public static PropertiesQuery parsePropertiesQuery(String query, String property int position=0; String op=null; - /** store "main" operator. Needed for such cases foo=bar-->test*/ - for (String shortOperator : shortOperators) { + //store "main" operator. Needed for such cases foo=bar-->test + for (String shortOperator : QueryOperation.inputRepresentations()) { int currentPositionOfOp = keyValuePair.indexOf(shortOperator); if (currentPositionOfOp != -1) { if( @@ -458,23 +440,23 @@ public static PropertiesQuery parsePropertiesQuery(String query, String property } } - if(op != null){ - String[] keyVal = new String[]{keyValuePair.substring(0, position).replaceAll(operatorComma,","), - keyValuePair.substring(position + op.length()) - }; - /** Cut from API-Gateway appended "=" */ - if ((">".equals(op) || "<".equals(op)) && keyVal[1].endsWith("=")) { + if (op != null) { + String[] keyVal = new String[] { + keyValuePair.substring(0, position).replaceAll(operatorComma,","), + keyValuePair.substring(position + op.length()) + }; + //Cut from API-Gateway appended "=" + if ((">".equals(op) || "<".equals(op)) && keyVal[1].endsWith("=")) keyVal[1] = keyVal[1].substring(0, keyVal[1].length() - 1); - } propertyQuery.setKey(spaceProperties ? keyVal[0] : getConvertedKey(keyVal[0])); - propertyQuery.setOperation(operators.get(op)); - String[] rawValues = keyVal[1].split( operatorComma ); + propertyQuery.setOperation(QueryOperation.fromInputRepresentation(op)); + String[] rawValues = keyVal[1].split(operatorComma); ArrayList values = new ArrayList<>(); - for (String rawValue : rawValues) { + for (String rawValue : rawValues) values.add(getConvertedValue(rawValue)); - } + propertyQuery.setValues(values); pql.add(propertyQuery); } diff --git a/xyz-models/src/main/java/com/here/xyz/events/PropertyQuery.java b/xyz-models/src/main/java/com/here/xyz/events/PropertyQuery.java index 6e29d4887e..7656f13791 100644 --- a/xyz-models/src/main/java/com/here/xyz/events/PropertyQuery.java +++ b/xyz-models/src/main/java/com/here/xyz/events/PropertyQuery.java @@ -21,7 +21,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonTypeName; +import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeName(value = "PropertyQuery") @@ -80,36 +83,41 @@ public PropertyQuery withValues(List values) { } public enum QueryOperation { - EQUALS, - NOT_EQUALS, - LESS_THAN, - GREATER_THAN, - LESS_THAN_OR_EQUALS, - GREATER_THAN_OR_EQUALS, - CONTAINS; - - public static String getOperation(QueryOperation op) { + EQUALS("=", "="), + NOT_EQUALS("!=", "<>"), + LESS_THAN(Set.of("<", "=lt="), "<"), + GREATER_THAN(Set.of(">", "=gt="), ">"), + LESS_THAN_OR_EQUALS(Set.of("<=", "=lte="), "<="), + GREATER_THAN_OR_EQUALS(Set.of(">=", "=gte="), ">="), + CONTAINS(Set.of("@>", "=cs="), "@>"); + + public final Set inputRepresentations; + public final String outputRepresentation; + + QueryOperation (Set inputRepresentations, String outputRepresentation) { + this.inputRepresentations = inputRepresentations; + this.outputRepresentation = outputRepresentation; + } + + QueryOperation (String inputRepresentation, String outputRepresentation) { + this(Set.of(inputRepresentation), outputRepresentation); + } + + public static String getOutputRepresentation(QueryOperation op) { if (op == null) throw new NullPointerException("op is required"); + return op.outputRepresentation; + } + + public static QueryOperation fromInputRepresentation(String inputRepresentation) { + for (QueryOperation op : values()) + if (op.inputRepresentations.contains(inputRepresentation)) + return op; + return null; + } - switch (op) { - case EQUALS: - return "="; - case NOT_EQUALS: - return "<>"; - case LESS_THAN: - return "<"; - case GREATER_THAN: - return ">"; - case LESS_THAN_OR_EQUALS: - return "<="; - case GREATER_THAN_OR_EQUALS: - return ">="; - case CONTAINS: - return "@>"; - } - - return ""; + public static Set inputRepresentations() { + return Arrays.stream(values()).flatMap(operator -> operator.inputRepresentations.stream()).collect(Collectors.toSet()); } } } diff --git a/xyz-psql-connector/src/main/java/com/here/xyz/psql/query/SearchForFeatures.java b/xyz-psql-connector/src/main/java/com/here/xyz/psql/query/SearchForFeatures.java index 57b5e468e7..76ef125149 100644 --- a/xyz-psql-connector/src/main/java/com/here/xyz/psql/query/SearchForFeatures.java +++ b/xyz-psql-connector/src/main/java/com/here/xyz/psql/query/SearchForFeatures.java @@ -195,7 +195,7 @@ protected static SQLQuery generatePropertiesQuery(SearchForFeaturesEvent event) else { predicateQuery = new SQLQuery("${{keyPath}} ${{operation}} ${{value}}") .withQueryFragment("keyPath", keyPath) - .withQueryFragment("operation", QueryOperation.getOperation(op)) + .withQueryFragment("operation", QueryOperation.getOutputRepresentation(op)) .withQueryFragment("value", value == null ? "" : value); namedParams.put(paramName, v); }