in solr/solrj/src/java/org/apache/solr/common/util/JsonRecordReader.java [312:448]
private void handleObjectStart(
final JSONParser parser,
final Handler handler,
final Map<String, Object> values,
final ArrayDeque<Set<String>> stack,
boolean recordStarted,
MethodFrameWrapper frameWrapper)
throws IOException {
final boolean isRecordStarted = recordStarted || isRecord;
Set<String> valuesAddedInThisFrame = null;
if (isRecord || !recordStarted) {
// This Node is a match for an PATH from a forEach attribute,
// prepare for the cleanup that will occur when the record
// is emitted after its END_ELEMENT is matched
valuesAddedInThisFrame = new HashSet<>();
stack.push(valuesAddedInThisFrame);
} else if (recordStarted) {
// This node is a child of some parent which matched against forEach
// attribute. Continue to add values to an existing record.
valuesAddedInThisFrame = stack.peek();
}
class Wrapper extends MethodFrameWrapper {
Wrapper(Node node, MethodFrameWrapper parent, String name) {
this.node = node;
this.parent = parent;
this.name = name;
}
@Override
public void walk(int event) throws IOException {
if (event == OBJECT_START) {
walkObject();
} else if (event == ARRAY_START) {
for (; ; ) {
event = parser.nextEvent();
if (event == ARRAY_END) {
// ensure that the value is of type List
final Object val = values.get(name);
if (val != null && !(val instanceof List)) {
final ArrayList<Object> listVal = new ArrayList<>(1);
listVal.add(val);
values.put(name, listVal);
}
break;
}
if (event == OBJECT_START) {
walkObject();
}
}
}
}
void walkObject() throws IOException {
if (node.isChildRecord) {
node.handleObjectStart(
parser,
(record, path) -> addChildDoc2ParentDoc(record, values, getPathSuffix(path)),
new LinkedHashMap<>(),
new ArrayDeque<>(),
true,
this);
} else {
node.handleObjectStart(parser, handler, values, stack, isRecordStarted, this);
}
}
}
try {
for (; ; ) {
int event = parser.nextEvent();
if (event == OBJECT_END) {
if (isRecord()) {
handler.handle(values, splitPath);
}
return;
}
assert event == STRING;
assert parser.wasKey();
String name = parser.getString();
Node node = childNodes.get(name);
if (node == null) node = wildCardChild;
if (node == null) node = recursiveWildCardChild;
if (node != null) {
if (node.isLeaf) { // this is a leaf. Collect data here
event = parser.nextEvent();
String nameInRecord =
node.fieldName == null
? getNameInRecord(name, frameWrapper, node)
: node.fieldName;
MethodFrameWrapper runnable = null;
if (event == OBJECT_START || event == ARRAY_START) {
if (node.recursiveWildCardChild != null)
runnable = new Wrapper(node, frameWrapper, name);
}
Object val = parseSingleFieldValue(event, parser, runnable);
if (val != null) {
putValue(values, nameInRecord, val);
valuesAddedInThisFrame.add(nameInRecord);
}
} else {
event = parser.nextEvent();
new Wrapper(node, frameWrapper, name).walk(event);
}
} else {
// this is not something we are interested in. Skip it
event = parser.nextEvent();
if (event == STRING
|| event == LONG
|| event == NUMBER
|| event == BIGNUMBER
|| event == BOOLEAN
|| event == NULL) {
continue;
}
if (event == ARRAY_START) {
consumeTillMatchingEnd(parser, 0, 1);
continue;
}
if (event == OBJECT_START) {
consumeTillMatchingEnd(parser, 1, 0);
continue;
} else throw new RuntimeException("unexpected token " + event);
}
}
} finally {
if ((isRecord() || !isRecordStarted)) {
for (String fld : valuesAddedInThisFrame) {
values.remove(fld);
}
}
}
}