|
3 | 3 | */ |
4 | 4 | package com.marklogic.client.datamovement.filter; |
5 | 5 |
|
| 6 | +import com.fasterxml.jackson.core.JsonPointer; |
6 | 7 | import com.marklogic.client.datamovement.DocumentWriteSetFilter; |
7 | 8 | import com.marklogic.client.document.DocumentWriteOperation; |
8 | 9 | import com.marklogic.client.document.DocumentWriteSet; |
9 | 10 | import com.marklogic.client.impl.DocumentWriteOperationImpl; |
10 | 11 | import com.marklogic.client.impl.HandleAccessor; |
| 12 | +import com.marklogic.client.impl.XmlFactories; |
11 | 13 | import com.marklogic.client.io.BaseHandle; |
12 | 14 | import com.marklogic.client.io.DocumentMetadataHandle; |
13 | 15 | import com.marklogic.client.io.Format; |
|
16 | 18 | import org.slf4j.Logger; |
17 | 19 | import org.slf4j.LoggerFactory; |
18 | 20 |
|
| 21 | +import javax.xml.xpath.XPath; |
| 22 | +import javax.xml.xpath.XPathExpressionException; |
19 | 23 | import java.io.IOException; |
20 | 24 | import java.nio.charset.StandardCharsets; |
21 | 25 | import java.time.Instant; |
@@ -114,11 +118,53 @@ public Builder xmlExclusions(String... xpathExpressions) { |
114 | 118 | } |
115 | 119 |
|
116 | 120 | public IncrementalWriteFilter build() { |
| 121 | + validateJsonExclusions(); |
| 122 | + validateXmlExclusions(); |
117 | 123 | if (useEvalQuery) { |
118 | 124 | return new IncrementalWriteEvalFilter(hashKeyName, timestampKeyName, canonicalizeJson, skippedDocumentsConsumer, jsonExclusions, xmlExclusions); |
119 | 125 | } |
120 | 126 | return new IncrementalWriteOpticFilter(hashKeyName, timestampKeyName, canonicalizeJson, skippedDocumentsConsumer, jsonExclusions, xmlExclusions); |
121 | 127 | } |
| 128 | + |
| 129 | + private void validateJsonExclusions() { |
| 130 | + if (jsonExclusions == null) { |
| 131 | + return; |
| 132 | + } |
| 133 | + for (String jsonPointer : jsonExclusions) { |
| 134 | + if (jsonPointer == null || jsonPointer.trim().isEmpty()) { |
| 135 | + throw new IllegalArgumentException( |
| 136 | + "Empty JSON Pointer expression is not valid for excluding content from incremental write hash calculation; " + |
| 137 | + "it would exclude the entire document. JSON Pointer expressions must start with '/'."); |
| 138 | + } |
| 139 | + try { |
| 140 | + JsonPointer.compile(jsonPointer); |
| 141 | + } catch (IllegalArgumentException e) { |
| 142 | + throw new IllegalArgumentException( |
| 143 | + String.format("Invalid JSON Pointer expression '%s' for excluding content from incremental write hash calculation. " + |
| 144 | + "JSON Pointer expressions must start with '/'; cause: %s", jsonPointer, e.getMessage()), e); |
| 145 | + } |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + private void validateXmlExclusions() { |
| 150 | + if (xmlExclusions == null) { |
| 151 | + return; |
| 152 | + } |
| 153 | + XPath xpath = XmlFactories.getXPathFactory().newXPath(); |
| 154 | + for (String xpathExpression : xmlExclusions) { |
| 155 | + if (xpathExpression == null || xpathExpression.trim().isEmpty()) { |
| 156 | + throw new IllegalArgumentException( |
| 157 | + "Empty XPath expression is not valid for excluding content from incremental write hash calculation."); |
| 158 | + } |
| 159 | + try { |
| 160 | + xpath.compile(xpathExpression); |
| 161 | + } catch (XPathExpressionException e) { |
| 162 | + throw new IllegalArgumentException( |
| 163 | + String.format("Invalid XPath expression '%s' for excluding content from incremental write hash calculation; cause: %s", |
| 164 | + xpathExpression, e.getMessage()), e); |
| 165 | + } |
| 166 | + } |
| 167 | + } |
122 | 168 | } |
123 | 169 |
|
124 | 170 | protected final String hashKeyName; |
|
0 commit comments