}
try {
while (eventQueue.isEmpty() || processAttributes) {
while (true) {
final JsonToken jsonToken = parser.nextToken();
final ProcessingInfo pi = processingStack.isEmpty() ? null : processingStack.peek();
if (jsonToken == null) {
return getCurrentNode();
}
switch (jsonToken) {
case FIELD_NAME:
final String fieldName = parser.getCurrentName();
if (isAttribute(fieldName)) {
// attribute
final QName attributeName = getAttributeQName(fieldName);
final String attributeValue = getPrimitiveFieldValue(parser.nextToken(), parser.getText());
eventQueue.peek().getAttributes().add(new JsonXmlEvent.Attribute(attributeName, attributeValue));
} else {
processAttributes = false;
// child event
if ("$".equals(fieldName)) {
// character event
final String value = getPrimitiveFieldValue(parser.nextToken(), parser.getText());
eventQueue.add(new CharactersEvent(value, new StaxLocation(parser.getCurrentLocation())));
} else {
// element event
final QName elementName = getElementQName(fieldName);
final JsonLocation currentLocation = parser.getCurrentLocation();
final boolean isRootEmpty = isEmptyElement(fieldName, true);
if (isRootEmpty) {
eventQueue.add(createStartElementEvent(elementName, new StaxLocation(currentLocation)));
eventQueue.add(createEndElementEvent(elementName, new StaxLocation(currentLocation)));
eventQueue.add(new EndDocumentEvent(new StaxLocation(parser.getCurrentLocation())));
} else {
if (!isEmptyArray() && !isEmptyElement(fieldName, false)) {
eventQueue.add(createStartElementEvent(elementName, new StaxLocation(currentLocation)));
processingStack.add(new ProcessingInfo(elementName, false, true));
}
if (!parser.hasMoreTokens()) {
eventQueue.add(new EndDocumentEvent(new StaxLocation(parser.getCurrentLocation())));
}
}
if (eventQueue.isEmpty()) {
continue;
}
return getCurrentNode();
}
}
break;
case START_OBJECT:
if (pi == null) {
eventQueue.add(new StartDocumentEvent(new StaxLocation(0, 0, 0)));
return getCurrentNode();
}
if (pi.isArray && !pi.isFirstElement) {
eventQueue.add(createStartElementEvent(pi.name, new StaxLocation(parser.getCurrentLocation())));
return getCurrentNode();
} else {
pi.isFirstElement = false;
}
break;
case END_OBJECT:
processAttributes = false;
// end tag
eventQueue.add(createEndElementEvent(pi.name, new StaxLocation(parser.getCurrentLocation())));
if (!pi.isArray) {
processingStack.pop();
}
if (processingStack.isEmpty()) {
eventQueue.add(new EndDocumentEvent(new StaxLocation(parser.getCurrentLocation())));
// Eat the last '}' and check whether there is another (unexpected) token.
final JsonToken nextToken = parser.nextToken();
if ((nextToken != null && nextToken != JsonToken.END_OBJECT)
|| parser.peek() != null) {
throw new RuntimeException("Unexpected token: " + parser.getText());
}
}