Skip to content

Commit 75d4fb8

Browse files
committed
Inner fields of arbitrary depth are now supported for index fields. Fixed two NullPointerExceptions by skipping cases where the attribute or matcher of an index field do not exist in the model.
1 parent 19f7047 commit 75d4fb8

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

src/main/java/io/zentity/model/IndexField.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,28 @@ public class IndexField {
1313
Arrays.asList("attribute")
1414
);
1515
private static final Pattern REGEX_EMPTY = Pattern.compile("^\\s*$");
16+
private static final Pattern REGEX_PERIOD = Pattern.compile("\\.");
1617

1718
private final String index;
1819
private final String name;
20+
private String path;
21+
private String pathParent;
1922
private String attribute;
2023
private String matcher;
2124

2225
public IndexField(String index, String name, JsonNode json) throws ValidationException {
2326
validateName(name);
2427
this.index = index;
2528
this.name = name;
29+
this.nameToPaths(name);
2630
this.deserialize(json);
2731
}
2832

2933
public IndexField(String index, String name, String json) throws ValidationException, IOException {
3034
validateName(name);
3135
this.index = index;
3236
this.name = name;
37+
this.nameToPaths(name);
3338
this.deserialize(json);
3439
}
3540

@@ -41,6 +46,14 @@ public String name() {
4146
return this.name;
4247
}
4348

49+
public String path() {
50+
return this.path;
51+
}
52+
53+
public String pathParent() {
54+
return this.pathParent;
55+
}
56+
4457
public String attribute() {
4558
return this.attribute;
4659
}
@@ -59,6 +72,13 @@ public void matcher(JsonNode value) throws ValidationException {
5972
this.matcher = value.textValue();
6073
}
6174

75+
private void nameToPaths(String name) {
76+
String[] parts = REGEX_PERIOD.split(name);
77+
this.path = "/" + String.join("/", parts);
78+
if (parts.length > 1)
79+
this.pathParent = "/" + String.join("/", Arrays.copyOf(parts, parts.length - 1));
80+
}
81+
6282
private void validateName(String value) throws ValidationException {
6383
if (REGEX_EMPTY.matcher(value).matches())
6484
throw new ValidationException("'indices." + this.index + "' has a field with an empty name.");

src/main/java/io/zentity/resolution/Job.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@ private String jsonStringFormat(String value) {
169169
return jsonStringQuote(jsonStringEscape(value));
170170
}
171171

172+
private boolean indexFieldHasMatcher(String indexName, String indexFieldName) {
173+
String matcherName = this.model.indices().get(indexName).fields().get(indexFieldName).matcher();
174+
if (matcherName == null)
175+
return false;
176+
if (this.model.matchers().get(matcherName) == null)
177+
return false;
178+
return true;
179+
}
180+
172181
/**
173182
* Determine if we can construct a query for a given resolver on a given index with a given input.
174183
* Each attribute of the resolver must be mapped to a field of the index and have a matcher defined for it.
@@ -199,7 +208,7 @@ private boolean canQuery(String indexName, String resolverName) {
199208
// The index field must have a matcher defined for it.
200209
boolean hasMatcher = false;
201210
for (String indexFieldName : this.model.indices().get(indexName).attributeIndexFieldsMap().get(attributeName).keySet()) {
202-
if (this.model.indices().get(indexName).fields().get(indexFieldName).matcher() != null) {
211+
if (this.indexFieldHasMatcher(indexName, indexFieldName)) {
203212
hasMatcher = true;
204213
break;
205214
}
@@ -280,8 +289,7 @@ private void traverse() throws IOException, ValidationException {
280289
for (String indexFieldName : this.model.indices().get(indexName).attributeIndexFieldsMap().get(attributeName).keySet()) {
281290

282291
// Can we use this index field?
283-
boolean hasMatcher = this.model.indices().get(indexName).fields().get(indexFieldName).matcher() != null;
284-
if (!hasMatcher)
292+
if (!this.indexFieldHasMatcher(indexName, indexFieldName))
285293
continue;
286294

287295
// Construct a clause for each input value for this attribute.
@@ -381,20 +389,24 @@ private void traverse() throws IOException, ValidationException {
381389
TreeMap<String, JsonNode> docAttributes = new TreeMap<>();
382390
for (String indexFieldName : this.model.indices().get(indexName).fields().keySet()) {
383391
String attributeName = this.model.indices().get(indexName).fields().get(indexFieldName).attribute();
392+
if (this.model.attributes().get(attributeName) == null)
393+
continue;
384394
String attributeType = this.model.attributes().get(attributeName).type();
395+
if (!nextInputAttributes.containsKey(attributeName))
396+
nextInputAttributes.put(attributeName, new HashSet<>());
385397
// The index field name might not refer to the _source property.
386398
// If it's not in the _source, remove the last part of the index field name from the dot notation.
387399
// Index field names can reference multi-fields, which are not returned in the _source.
388-
if (!nextInputAttributes.containsKey(attributeName))
389-
nextInputAttributes.put(attributeName, new HashSet<>());
390-
if (!doc.get("_source").has(indexFieldName))
391-
indexFieldName = indexFieldName.split("\\.")[0];
392-
if (doc.get("_source").has(indexFieldName)) {
393-
JsonNode valueNode = doc.get("_source").get(indexFieldName);
394-
docAttributes.put(attributeName, valueNode);
395-
Object value = Attribute.convertType(attributeType, valueNode);
396-
nextInputAttributes.get(attributeName).add(value);
397-
}
400+
String path = this.model.indices().get(indexName).fields().get(indexFieldName).path();
401+
String pathParent = this.model.indices().get(indexName).fields().get(indexFieldName).pathParent();
402+
JsonNode valueNode = doc.get("_source").at(path);
403+
if (valueNode.isMissingNode())
404+
valueNode = doc.get("_source").at(pathParent);
405+
if (valueNode.isMissingNode())
406+
continue;
407+
docAttributes.put(attributeName, valueNode);
408+
Object value = Attribute.convertType(attributeType, valueNode);
409+
nextInputAttributes.get(attributeName).add(value);
398410
}
399411

400412
// Modify doc metadata.

0 commit comments

Comments
 (0)