Bit more work on filtering parser, getting close to working for the simplest use case
diff --git a/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java b/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java
index 3e22fbf..ae57e63 100644
--- a/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java
+++ b/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java
@@ -215,7 +215,7 @@
if (ctxt != null) {
while (true) {
- JsonToken t = _exposedContext.nextTokenToRead();
+ JsonToken t = ctxt.nextTokenToRead();
if (t != null) {
_currToken = t;
return t;
@@ -223,10 +223,17 @@
// all done with buffered stuff?
if (ctxt == _headContext) {
_exposedContext = null;
+ // Almost! Most likely still have the current token;
+ // with the sole exception of
+ t = delegate.getCurrentToken();
+ if (t != JsonToken.FIELD_NAME) {
+ _currToken = t;
+ return t;
+ }
break;
}
// If not, traverse down the context chain
- ctxt = _exposedContext.findChildOf(_exposedContext);
+ ctxt = _exposedContext.findChildOf(ctxt);
_exposedContext = ctxt;
if (ctxt == null) { // should never occur
throw _constructError("Unexpected problem: chain of filtered context broken");
@@ -318,6 +325,7 @@
case ID_FIELD_NAME:
{
final String name = delegate.getCurrentName();
+ // note: this will also set 'needToHandleName'
f = _headContext.setFieldName(name);
if (f == TokenFilter.INCLUDE_ALL) {
_itemFilter = f;
@@ -334,15 +342,12 @@
delegate.skipChildren();
break;
}
+ _itemFilter = f;
if (f == TokenFilter.INCLUDE_ALL) {
- _itemFilter = f;
return (_currToken = t);
}
- // !!! TODO: still not decided if to include, so...
-
- _itemFilter = f;
+ return _nextTokenWithBuffering(_headContext);
}
- break;
default: // scalar value
if (_itemFilter == TokenFilter.INCLUDE_ALL) {
@@ -455,23 +460,20 @@
if (f == null) { // filter out the value
delegate.nextToken();
delegate.skipChildren();
- break;
+ continue main_loop;
}
f = f.includeProperty(name);
if (f == null) { // filter out the value
delegate.nextToken();
delegate.skipChildren();
- break;
+ continue main_loop;
}
+ _itemFilter = f;
if (f == TokenFilter.INCLUDE_ALL) {
- _itemFilter = f;
return (_currToken = t);
}
- // !!! TODO: still not decided if to include, so...
-
- _itemFilter = f;
}
- continue main_loop;
+ return _nextTokenWithBuffering(_headContext);
default: // scalar value
if (_itemFilter == TokenFilter.INCLUDE_ALL) {
@@ -486,10 +488,12 @@
/**
* Method called when a new potentially included context is found.
*/
- protected final JsonToken _nextTokenWithBuffering(TokenFilterContext buffRoot) throws IOException
+ protected final JsonToken _nextTokenWithBuffering(final TokenFilterContext buffRoot)
+ throws IOException
{
_exposedContext = _headContext;
+ main_loop:
while (true) {
JsonToken t = delegate.nextToken();
@@ -498,22 +502,16 @@
}
TokenFilter f;
+ // One simplification here: we know for a fact that the item filter is
+ // neither null nor 'include all', for most cases; the only exception
+ // being FIELD_NAME handling
+
switch (t.id()) {
case ID_START_ARRAY:
- f = _itemFilter;
- if (f == TokenFilter.INCLUDE_ALL) {
- _headContext = _headContext.createChildArrayContext(f, true);
- return (_currToken = t);
- }
- if (f == null) { // does this occur?
- delegate.skipChildren();
- break;
- }
- // Otherwise still iffy, need to check
- f = _headContext.checkValue(f);
+ f = _headContext.checkValue(_itemFilter);
if (f == null) {
delegate.skipChildren();
- break;
+ continue main_loop;
}
if (f != TokenFilter.INCLUDE_ALL) {
f = f.filterStartArray();
@@ -521,9 +519,9 @@
_itemFilter = f;
_headContext = _headContext.createChildArrayContext(f, true);
if (f == TokenFilter.INCLUDE_ALL) {
- return (_currToken = t);
+ return _nextBuffered();
}
- break;
+ continue main_loop;
case ID_START_OBJECT:
f = _itemFilter;
@@ -533,13 +531,13 @@
}
if (f == null) { // does this occur?
delegate.skipChildren();
- break;
+ continue main_loop;
}
// Otherwise still iffy, need to check
f = _headContext.checkValue(f);
if (f == null) {
delegate.skipChildren();
- break;
+ continue main_loop;
}
if (f != TokenFilter.INCLUDE_ALL) {
f = f.filterStartObject();
@@ -547,25 +545,28 @@
_itemFilter = f;
_headContext = _headContext.createChildObjectContext(f, true);
if (f == TokenFilter.INCLUDE_ALL) {
- return (_currToken = t);
+ return _nextBuffered();
}
- break;
+ continue main_loop;
case ID_END_ARRAY:
case ID_END_OBJECT:
{
- boolean returnEnd = _headContext.isStartHandled();
+ // Unlike with other loops, here we know that content was NOT
+ // included (won't get this far otherwise)
f = _headContext.getFilter();
if ((f != null) && (f != TokenFilter.INCLUDE_ALL)) {
f.filterFinishArray();
}
_headContext = _headContext.getParent();
_itemFilter = _headContext.getFilter();
- if (returnEnd) {
- return (_currToken = t);
+
+ if (_headContext == buffRoot) {
+ // !!! TBI
+ throw _constructError("Internal error: end of possible inclusion -- TBI");
}
}
- break;
+ continue main_loop;
case ID_FIELD_NAME:
{
@@ -573,38 +574,65 @@
f = _headContext.setFieldName(name);
if (f == TokenFilter.INCLUDE_ALL) {
_itemFilter = f;
- return (_currToken = t);
+ return _nextBuffered();
}
if (f == null) { // filter out the value
delegate.nextToken();
delegate.skipChildren();
- break;
+ continue main_loop;
}
f = f.includeProperty(name);
if (f == null) { // filter out the value
delegate.nextToken();
delegate.skipChildren();
- break;
+ continue main_loop;
}
- if (f == TokenFilter.INCLUDE_ALL) {
- _itemFilter = f;
- return (_currToken = t);
- }
- // !!! TODO: still not decided if to include, so...
-
_itemFilter = f;
+ if (f == TokenFilter.INCLUDE_ALL) {
+ return _nextBuffered();
+ }
}
- break;
+ continue main_loop;
default: // scalar value
if (_itemFilter == TokenFilter.INCLUDE_ALL) {
- return (_currToken = t);
+ return _nextBuffered();
}
// Otherwise not included (leaves must be explicitly included)
- break;
}
}
- }
+ }
+
+ private JsonToken _nextBuffered() throws IOException
+ {
+ TokenFilterContext ctxt = _exposedContext;
+ JsonToken t = ctxt.nextTokenToRead();
+ if (t != null) {
+ _currToken = t;
+ return t;
+ }
+ while (true) {
+ // all done with buffered stuff?
+ if (ctxt == _headContext) {
+ throw _constructError("Internal error: failed to locate expected buffered tokens");
+ /*
+ _exposedContext = null;
+ break;
+ */
+ }
+ // If not, traverse down the context chain
+ ctxt = _exposedContext.findChildOf(ctxt);
+ _exposedContext = ctxt;
+ if (ctxt == null) { // should never occur
+ throw _constructError("Unexpected problem: chain of filtered context broken");
+ }
+ t = _exposedContext.nextTokenToRead();
+ if (t != null) {
+ _currToken = t;
+ return t;
+ }
+ }
+ }
@Override
public JsonToken nextValue() throws IOException {