diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..21a0cfd
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,20 @@
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+charset = utf-8
+end_of_line = lf
+
+[*.java]
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+max_line_length = 120
+ij_continuation_indent_size = 8
+ij_java_wrap_long_lines = true
+ij_java_wrap_comments = true
+ij_java_method_call_chain_wrap = normal
+ij_java_blank_lines_after_class_header = 1
+ij_java_class_count_to_use_import_on_demand = 10
+ij_java_names_count_to_use_import_on_demand = 10
\ No newline at end of file
diff --git a/src/main/java/com/aerospike/documentapi/DocumentApiException.java b/src/main/java/com/aerospike/documentapi/DocumentApiException.java
index 6dec4ab..68df530 100644
--- a/src/main/java/com/aerospike/documentapi/DocumentApiException.java
+++ b/src/main/java/com/aerospike/documentapi/DocumentApiException.java
@@ -25,8 +25,8 @@ public static DocumentApiException wrapAerospikeException(AerospikeException ae)
}
/**
- * Utility method to wrap an Exception.
- * {@link AerospikeException} is processed separately to display its result code name.
+ * Utility method to wrap an Exception. {@link AerospikeException} is processed separately to display its result
+ * code name.
*
* @param e the original exception.
* @return a DocumentApiException wrapping the original exception.
@@ -41,6 +41,7 @@ public static DocumentApiException toDocumentException(Exception e) {
* Exception to be thrown in case of invalid json prefix.
*/
public static class JsonPrefixException extends DocumentApiException {
+
public JsonPrefixException(String jsonString) {
super(String.format("'%s' should start with either a '$.' or '$['", jsonString));
}
@@ -50,6 +51,7 @@ public JsonPrefixException(String jsonString) {
* Exception to be thrown in case of invalid json path.
*/
public static class JsonPathException extends DocumentApiException {
+
public JsonPathException(String jsonString) {
super(String.format("'%s' does not match JSONPath format", jsonString));
}
@@ -59,6 +61,7 @@ public JsonPathException(String jsonString) {
* Exception to be thrown in case of invalid appending to json.
*/
public static class JsonAppendException extends DocumentApiException {
+
public JsonAppendException(String jsonString) {
super(String.format("Cannot append to '%s'", jsonString));
}
@@ -68,6 +71,7 @@ public JsonAppendException(String jsonString) {
* Exception to be thrown in case of invalid json path.
*/
public static class JsonPathParseException extends DocumentApiException {
+
public JsonPathParseException(String jsonPathPart) {
super(String.format("Unable to parse '%s' as JSONPath token", jsonPathPart));
}
diff --git a/src/main/java/com/aerospike/documentapi/IAerospikeDocumentClient.java b/src/main/java/com/aerospike/documentapi/IAerospikeDocumentClient.java
index e4e4231..8efb1d7 100644
--- a/src/main/java/com/aerospike/documentapi/IAerospikeDocumentClient.java
+++ b/src/main/java/com/aerospike/documentapi/IAerospikeDocumentClient.java
@@ -108,11 +108,11 @@ public interface IAerospikeDocumentClient {
/**
* Perform batch operations.
- *
- *
Operations order is preserved only for those 1-step operations
- * (with JSONPath that contains only array and/or map elements)
- * that have unique Aerospike keys within a batch.
+ * Operations order is preserved only for those 1-step operations (with JSONPath that contains only array and/or map
+ * elements) that have unique Aerospike keys within a batch.
+ *
+ * Every 2-step operation (with JSONPath containing wildcards, recursive descent, filters, functions, scripts)
* should have unique Aerospike key within a batch.
*
* @param batchOperations a list of batch operations to apply.
diff --git a/src/main/java/com/aerospike/documentapi/IAerospikeDocumentRepository.java b/src/main/java/com/aerospike/documentapi/IAerospikeDocumentRepository.java
index f842137..e7a775c 100644
--- a/src/main/java/com/aerospike/documentapi/IAerospikeDocumentRepository.java
+++ b/src/main/java/com/aerospike/documentapi/IAerospikeDocumentRepository.java
@@ -23,7 +23,8 @@ Map get(Policy readPolicy, Key key, Collection binNames,
void put(WritePolicy writePolicy, Key key, String binName, Map, ?> jsonMap);
- void put(WritePolicy writePolicy, Key key, Collection binNames, Object jsonObject, JsonPathObject jsonPathObject);
+ void put(WritePolicy writePolicy, Key key, Collection binNames, Object jsonObject,
+ JsonPathObject jsonPathObject);
void put(WritePolicy writePolicy, Key key, Map queryResults, JsonPathObject jsonPathObject);
diff --git a/src/main/java/com/aerospike/documentapi/batch/AppendBatchOperation.java b/src/main/java/com/aerospike/documentapi/batch/AppendBatchOperation.java
index ded0677..6d51bd9 100644
--- a/src/main/java/com/aerospike/documentapi/batch/AppendBatchOperation.java
+++ b/src/main/java/com/aerospike/documentapi/batch/AppendBatchOperation.java
@@ -40,14 +40,16 @@ public BatchRecord setSecondStepRecordAndGet() {
} else {
if (isRequiringJsonPathQuery()) {
// using the original object as the initially parsed one has already been changed within the 1st step
- final PathDetails pathDetails = getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
+ final PathDetails pathDetails =
+ getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
batchOps = firstStepQueryResults().entrySet().stream()
.map(entry -> toPutOperation(entry.getKey(), entry.getValue(), pathDetails))
.filter(Objects::nonNull)
.toArray(Operation[]::new);
} else {
// needs to be treated without modifying
- final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(), false);
+ final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(),
+ false);
batchOps = binNames.stream()
.map(binName -> toAppendOperation(binName, objToAppend, pathDetails))
.filter(Objects::nonNull)
diff --git a/src/main/java/com/aerospike/documentapi/batch/DeleteBatchOperation.java b/src/main/java/com/aerospike/documentapi/batch/DeleteBatchOperation.java
index df1d4ba..4924fea 100644
--- a/src/main/java/com/aerospike/documentapi/batch/DeleteBatchOperation.java
+++ b/src/main/java/com/aerospike/documentapi/batch/DeleteBatchOperation.java
@@ -38,13 +38,15 @@ public BatchRecord setSecondStepRecordAndGet() {
} else {
if (isRequiringJsonPathQuery()) {
// using the original object as the initially parsed one has already been changed within the 1st step
- final PathDetails pathDetails = getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
+ final PathDetails pathDetails =
+ getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
batchOps = firstStepQueryResults().entrySet().stream()
.map(entry -> pathDetails.getFinalToken()
.toAerospikePutOperation(entry.getKey(), entry.getValue(), pathDetails.getCtxArray()))
.toArray(Operation[]::new);
} else {
- final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
+ final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(),
+ true);
batchOps = binNames.stream()
.map(binName -> pathDetails.getFinalToken()
.toAerospikeDeleteOperation(binName, pathDetails.getCtxArray()))
diff --git a/src/main/java/com/aerospike/documentapi/batch/PutBatchOperation.java b/src/main/java/com/aerospike/documentapi/batch/PutBatchOperation.java
index 871aae7..4553a75 100644
--- a/src/main/java/com/aerospike/documentapi/batch/PutBatchOperation.java
+++ b/src/main/java/com/aerospike/documentapi/batch/PutBatchOperation.java
@@ -42,13 +42,15 @@ public BatchRecord setSecondStepRecordAndGet() {
} else {
if (isRequiringJsonPathQuery()) {
// using the original object as the initially parsed one has already been changed within the 1st step
- final PathDetails pathDetails = getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
+ final PathDetails pathDetails =
+ getPathDetails(originalJsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
batchOps = firstStepQueryResults().entrySet().stream()
.map(entry -> toPutOperation(entry.getKey(), entry.getValue(), pathDetails))
.filter(Objects::nonNull)
.toArray(Operation[]::new);
} else {
- final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(), true);
+ final PathDetails pathDetails = getPathDetails(jsonPathObject.getTokensNotRequiringSecondStepQuery(),
+ true);
batchOps = binNames.stream()
.map(binName -> toPutOperation(binName, objToPut, pathDetails))
.filter(Objects::nonNull)
diff --git a/src/main/java/com/aerospike/documentapi/jsonpath/JsonPathParser.java b/src/main/java/com/aerospike/documentapi/jsonpath/JsonPathParser.java
index 8eac854..ebf725c 100644
--- a/src/main/java/com/aerospike/documentapi/jsonpath/JsonPathParser.java
+++ b/src/main/java/com/aerospike/documentapi/jsonpath/JsonPathParser.java
@@ -53,8 +53,8 @@ public static ContextAwareToken extractLastPathPartAndModifyList(List parseToList(String strPart) {
+ List list = new ArrayList<>();
+ Token token;
+
+ Matcher keyMatcher = PATH_PATTERN.matcher(strPart);
+ if ((!strPart.contains("[")) && (!strPart.contains("]"))) {
+ // ignoring * wildcard after a dot
+ if (!strPart.equals(String.valueOf(WILDCARD)) && !strPart.equals(String.valueOf(DOC_ROOT))) {
+ token = new MapToken(strPart);
+ list.add(token);
+ }
+ } else if (keyMatcher.find()) {
+ String key = keyMatcher.group(1);
+ if (!key.equals(String.valueOf(DOC_ROOT))
+ && key.length() > 0
+ && key.charAt(0) != OPEN_BRACKET && key.charAt(key.length() - 1) != CLOSE_BRACKET) {
+ token = new MapToken(key);
+ list.add(token);
+ }
+ }
+
+ Matcher indexMatcher = INDEX_PATTERN.matcher(strPart);
+ while (indexMatcher.find()) {
+ String res = indexMatcher.group(2);
+ if (res.equals("*")) {
+ token = new WildcardToken(res, true);
+ } else {
+ token = new ListToken(Integer.parseInt(res));
+ }
+ list.add(token);
+ }
+
+ return list;
+ }
public int getListPosition() {
return listPosition;
@@ -81,42 +119,4 @@ public Operation toAerospikeDeleteOperation(String binName, CTX[] contexts) {
public TokenType getType() {
return TokenType.LIST;
}
-
- // For reading a path part into a list of tokens (map, list or wildcard).
- // Appends parsed tokens to a list.
- // Expected form of path part is key[index1][index2].
- public static List parseToList(String strPart) {
- List list = new ArrayList<>();
- Token token;
-
- Matcher keyMatcher = PATH_PATTERN.matcher(strPart);
- if ((!strPart.contains("[")) && (!strPart.contains("]"))) {
- // ignoring * wildcard after a dot
- if (!strPart.equals(String.valueOf(WILDCARD)) && !strPart.equals(String.valueOf(DOC_ROOT))) {
- token = new MapToken(strPart);
- list.add(token);
- }
- } else if (keyMatcher.find()) {
- String key = keyMatcher.group(1);
- if (!key.equals(String.valueOf(DOC_ROOT))
- && key.length() > 0
- && key.charAt(0) != OPEN_BRACKET && key.charAt(key.length() - 1) != CLOSE_BRACKET) {
- token = new MapToken(key);
- list.add(token);
- }
- }
-
- Matcher indexMatcher = INDEX_PATTERN.matcher(strPart);
- while (indexMatcher.find()) {
- String res = indexMatcher.group(2);
- if (res.equals("*")) {
- token = new WildcardToken(res, true);
- } else {
- token = new ListToken(Integer.parseInt(res));
- }
- list.add(token);
- }
-
- return list;
- }
}
diff --git a/src/main/java/com/aerospike/documentapi/token/MapToken.java b/src/main/java/com/aerospike/documentapi/token/MapToken.java
index 8af909d..552ae19 100644
--- a/src/main/java/com/aerospike/documentapi/token/MapToken.java
+++ b/src/main/java/com/aerospike/documentapi/token/MapToken.java
@@ -21,6 +21,8 @@
*/
public class MapToken extends ContextAwareToken {
+ static final Pattern PATH_PATTERN = Pattern.compile("^([^\\[^\\]]*)(\\[(\\d+)\\])*$");
+
private final String key;
public MapToken(String key) {
@@ -28,7 +30,25 @@ public MapToken(String key) {
setString(key);
}
- static final Pattern PATH_PATTERN = Pattern.compile("^([^\\[^\\]]*)(\\[(\\d+)\\])*$");
+ public static Optional match(String strPart) {
+ Token token;
+ Matcher keyMatcher = PATH_PATTERN.matcher(strPart);
+ if ((!strPart.contains("[")) && (!strPart.contains("]"))) {
+ // ignoring * wildcard after a dot, it's the same as ending with a .path
+ if (!strPart.equals(String.valueOf(WILDCARD)) && !strPart.equals(String.valueOf(DOC_ROOT))) {
+ token = new MapToken(strPart);
+ return Optional.of(token);
+ }
+ } else if (keyMatcher.find()) {
+ String key = keyMatcher.group(1);
+ if (!key.equals(String.valueOf(DOC_ROOT))) {
+ token = new MapToken(strPart);
+ return Optional.of(token);
+ }
+ }
+
+ return Optional.empty();
+ }
public String getKey() {
return key;
@@ -78,25 +98,4 @@ public Operation toAerospikeDeleteOperation(String binName, CTX[] contexts) {
public TokenType getType() {
return TokenType.MAP;
}
-
- public static Optional match(String strPart) {
- Token token;
-
- Matcher keyMatcher = PATH_PATTERN.matcher(strPart);
- if ((!strPart.contains("[")) && (!strPart.contains("]"))) {
- // ignoring * wildcard after a dot, it's the same as ending with a .path
- if (!strPart.equals(String.valueOf(WILDCARD)) && !strPart.equals(String.valueOf(DOC_ROOT))) {
- token = new MapToken(strPart);
- return Optional.of(token);
- }
- } else if (keyMatcher.find()) {
- String key = keyMatcher.group(1);
- if (!key.equals(String.valueOf(DOC_ROOT))) {
- token = new MapToken(strPart);
- return Optional.of(token);
- }
- }
-
- return Optional.empty();
- }
}
diff --git a/src/main/java/com/aerospike/documentapi/token/Token.java b/src/main/java/com/aerospike/documentapi/token/Token.java
index 31d94b4..5bb653d 100644
--- a/src/main/java/com/aerospike/documentapi/token/Token.java
+++ b/src/main/java/com/aerospike/documentapi/token/Token.java
@@ -5,23 +5,23 @@ public abstract class Token {
private String string;
private String queryConcatString;
+ public String getString() {
+ return string;
+ }
+
protected void setString(String string) {
this.string = string;
this.queryConcatString = string;
}
- protected void setQueryConcatString(String queryConcatString) {
- this.queryConcatString = queryConcatString;
- }
-
- public String getString() {
- return string;
- }
-
public String getQueryConcatString() {
return queryConcatString;
}
+ protected void setQueryConcatString(String queryConcatString) {
+ this.queryConcatString = queryConcatString;
+ }
+
public abstract TokenType getType();
public boolean requiresJsonQuery() {
diff --git a/src/main/java/com/aerospike/documentapi/util/JsonConverters.java b/src/main/java/com/aerospike/documentapi/util/JsonConverters.java
index 15e754b..2617786 100644
--- a/src/main/java/com/aerospike/documentapi/util/JsonConverters.java
+++ b/src/main/java/com/aerospike/documentapi/util/JsonConverters.java
@@ -53,8 +53,8 @@ public static List