Skip to content

Commit

Permalink
Merge branch 'filter-on-object'
Browse files Browse the repository at this point in the history
  • Loading branch information
wanglingsong committed Dec 19, 2022
2 parents e029cdd + b48fae7 commit 5ce7747
Show file tree
Hide file tree
Showing 22 changed files with 338 additions and 130 deletions.
19 changes: 19 additions & 0 deletions jsurfer-all/src/test/java/org/jsfr/json/JsonSurferTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
Expand Down Expand Up @@ -1048,4 +1049,22 @@ public void testFilterWithDoubleQuote() throws Exception {
assertEquals("The Lord of the Rings", box1.get());
}

@Test
public void testFilterOnObjects() throws Exception {
Collector collector = surfer.collector(read("sample_filter3.json"));
ValueBox<Collection<Map>> boxes = collector.collectAll("$..[?(@.letter=='X')]", Map.class);
collector.exec();
Collection<Map> filtered = boxes.get();
System.out.println(filtered);
assertEquals(3, filtered.size());
Iterator<Map> itr = filtered.iterator();
Map first = itr.next();
Map second = itr.next();
Map third = itr.next();

assertEquals(1.1, first.get("number"));
assertEquals(1.2, second.get("number"));
assertEquals(1.3, third.get("number"));
}

}
24 changes: 12 additions & 12 deletions jsurfer-all/src/test/java/org/jsfr/json/path/JsonPathTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,18 +83,18 @@ public void shallEnsureJsonPathCapacity() throws Exception {
assertEquals(41, path.size);
}

@Test
public void shallMatch() throws Exception {
JsonPath path1 = compile("$..store..book..book[?(@.category=='fiction')]..title");
JsonPath path2 = compile("$..store..book.store.book[?(@.category=='fiction')]..title");
JsonPath path3 = compile("$..store..book.store[?(@.category=='fiction')]..title");
JsonPath path4 = compile("$..book..book..book..store.book[?(@.category=='fiction')]..title");
JsonPath position = compile("$.book.store.book.store.book[1].volumes[1].title");
assertTrue(path1.matchWithDeepScan(position));
assertTrue(path2.matchWithDeepScan(position));
assertFalse(path3.matchWithDeepScan(position));
assertFalse(path4.matchWithDeepScan(position));
}
// @Test
// public void shallMatch() throws Exception {
// JsonPath path1 = compile("$..store..book..book[?(@.category=='fiction')]..title");
// JsonPath path2 = compile("$..store..book.store.book[?(@.category=='fiction')]..title");
// JsonPath path3 = compile("$..store..book.store[?(@.category=='fiction')]..title");
// JsonPath path4 = compile("$..book..book..book..store.book[?(@.category=='fiction')]..title");
// JsonPath position = compile("$.book.store.book.store.book[1].volumes[1].title");
// assertTrue(path1.matchWithDeepScan(position));
// assertTrue(path2.matchWithDeepScan(position));
// assertFalse(path3.matchWithDeepScan(position));
// assertFalse(path4.matchWithDeepScan(position));
// }

@Test
public void testJsonPathFilterMatchRegexInputMismatch() throws Exception {
Expand Down
6 changes: 6 additions & 0 deletions jsurfer-all/src/test/resources/sample_filter3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{"letter" : "A", "number": 1, "boolean": true},
{"letter" : "B", "number": 2, "boolean": false, "next": {"letter" : "X", "number": 1.1, "boolean": true } },
{"letter" : "C", "number": 3, "boolean": true, "next": {"letter" : "X", "number": 1.2, "boolean": false } },
{"letter" : "D", "number": 4, "boolean": true, "next": {"letter" : "X", "number": 1.3, "boolean": true } }
]
8 changes: 8 additions & 0 deletions jsurfer-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
10 changes: 10 additions & 0 deletions jsurfer-core/src/main/java/org/jsfr/json/ContentDispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public int size() {
return this.receiver.size();
}

protected void onRemove(JsonSaxHandler item) {

}

@Override
public boolean startJSON() {
if (receiver.isEmpty()) {
Expand Down Expand Up @@ -71,6 +75,7 @@ public boolean startObject() {
JsonSaxHandler observer = itr.next();
if (!observer.startObject()) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand All @@ -86,6 +91,7 @@ public boolean endObject() {
JsonSaxHandler observer = itr.next();
if (!observer.endObject()) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand All @@ -101,6 +107,7 @@ public boolean startObjectEntry(String key) {
JsonSaxHandler observer = itr.next();
if (!observer.startObjectEntry(key)) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand All @@ -116,6 +123,7 @@ public boolean startArray() {
JsonSaxHandler observer = itr.next();
if (!observer.startArray()) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand All @@ -131,6 +139,7 @@ public boolean endArray() {
JsonSaxHandler observer = itr.next();
if (!observer.endArray()) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand All @@ -146,6 +155,7 @@ public boolean primitive(PrimitiveHolder primitiveHolder) {
JsonSaxHandler observer = itr.next();
if (!observer.primitive(primitiveHolder)) {
itr.remove();
onRemove(observer);
}
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,67 @@

package org.jsfr.json;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class FilterVerifierDispatcher extends ContentDispatcher {

private Map<SurfingConfiguration.Binding, JsonFilterVerifier> verifiers = new HashMap<>();
private final Map<SurfingConfiguration.Binding, List<JsonFilterVerifier>> verifiers = new HashMap<>();

public void addVerifier(SurfingConfiguration.Binding binding, JsonFilterVerifier verifier) {
this.addReceiver(verifier);
this.verifiers.put(binding, verifier);
if (binding.dependency != null) {
List<JsonFilterVerifier> dependencies = this.verifiers.get(binding.dependency);
if (dependencies != null) {
List<JsonFilterVerifier> filtered = dependencies.stream().filter(d -> d.getStartDepth() < verifier.getStartDepth()).collect(Collectors.toList());
verifier.setDependencies(filtered);
}
}
this.verifiers.compute(binding, (binding1, prev) -> {
List<JsonFilterVerifier> verifiers;
if (prev == null) {
verifiers = new ArrayList<>();
} else {
verifiers = prev;
}
verifiers.add(verifier);
return verifiers;
});
// this.verifiers.put(binding, verifier);
}

public JsonFilterVerifier getVerifier(SurfingConfiguration.Binding binding) {
return this.verifiers.get(binding);
public List<JsonPathListener> dispatch(JsonPosition jsonPosition, SurfingConfiguration.Binding binding) {
int pathDepth = jsonPosition.pathDepth();
SurfingConfiguration.Binding dependency = binding.dependency;
JsonPathListener[] listeners = binding.getListeners();
// TODO match relative path after dependency according to dependency start path and dispatch
List<JsonPathListener> rst = new ArrayList<>();
List<JsonFilterVerifier> dependencies = this.verifiers.get(dependency);
if (dependencies != null) {
for (JsonFilterVerifier verifier : dependencies) {
if (binding.jsonPath.matchFilterPathUntilDepth(jsonPosition, verifier.getStartDepth())) {
if (verifier.getStartDepth() <= pathDepth) {
for (JsonPathListener listener : listeners) {
rst.add(verifier.addListener(listener));
}
}
}
}
}
return rst;
}

@Override
protected void onRemove(JsonSaxHandler item) {
for (Map.Entry<SurfingConfiguration.Binding, List<JsonFilterVerifier>> entry : this.verifiers.entrySet()) {
entry.getValue().remove(item);
}
}
// public JsonFilterVerifier getVerifier(SurfingConfiguration.Binding binding) {
// return this.verifiers.get(binding);
// }

}
31 changes: 23 additions & 8 deletions jsurfer-core/src/main/java/org/jsfr/json/JsonFilterVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,53 @@

package org.jsfr.json;

import org.jsfr.json.filter.CloneableJsonPathFilter;
import org.jsfr.json.filter.JsonPathFilter;

import java.util.ArrayList;
import java.util.Collection;

public class JsonFilterVerifier implements JsonSaxHandler {

private final int startDepth;
private SurfingConfiguration config;
private SurfingConfiguration.Binding binding;
private JsonPathFilter jsonPathFilter;
private Collection<BufferedListener> bufferedListeners;
private JsonFilterVerifier dependency;
private Collection<JsonFilterVerifier> dependencies;
private JsonPosition currentPosition;
private boolean verified = false;
private int stackDepth = 0;

public JsonFilterVerifier(JsonPosition currentPosition, SurfingConfiguration config, JsonPathFilter jsonPathFilter, JsonFilterVerifier dependency) {
public JsonFilterVerifier(JsonPosition currentPosition, SurfingConfiguration config, SurfingConfiguration.Binding binding) {
this.currentPosition = currentPosition;
this.startDepth = currentPosition.pathDepth();
this.config = config;
this.jsonPathFilter = jsonPathFilter;
this.dependency = dependency;
this.binding = binding;
this.jsonPathFilter = (JsonPathFilter) ((CloneableJsonPathFilter) binding.filter).cloneMe();
// this.dependency = dependency;
this.bufferedListeners = new ArrayList<>();
}

public int getStartDepth() {
return startDepth;
}

public void setDependencies(Collection<JsonFilterVerifier> dependencies) {
this.dependencies = dependencies;
}

public JsonPathListener addListener(JsonPathListener listener) {
BufferedListener newListener = new BufferedListener(this.config, listener);
this.bufferedListeners.add(newListener);
return newListener;
}

private void invokeBuffer() {
if (dependency != null) {
dependency.bufferedListeners.addAll(this.bufferedListeners);
if (dependencies != null) {
for (JsonFilterVerifier dependency : dependencies) {
dependency.bufferedListeners.addAll(this.bufferedListeners);
}
} else {
for (BufferedListener buffer : this.bufferedListeners) {
buffer.invokeBufferedValue();
Expand All @@ -81,7 +96,7 @@ public boolean startObject() {

@Override
public boolean startObjectEntry(String key) {
if (!this.verified && this.jsonPathFilter.apply(this.currentPosition, null, this.config.getJsonProvider())) {
if (!this.verified && this.jsonPathFilter.apply(this.currentPosition, this.startDepth, null, this.config.getJsonProvider())) {
this.verified = true;
}
return true;
Expand Down Expand Up @@ -116,7 +131,7 @@ private boolean endObjectOrArray() {

@Override
public boolean primitive(PrimitiveHolder primitiveHolder) {
if (!this.verified && this.jsonPathFilter.apply(this.currentPosition, primitiveHolder, this.config.getJsonProvider())) {
if (!this.verified && this.jsonPathFilter.apply(this.currentPosition, this.startDepth, primitiveHolder, this.config.getJsonProvider())) {
this.verified = true;
}
return true;
Expand Down
Loading

0 comments on commit 5ce7747

Please sign in to comment.