in xstream/src/java/com/thoughtworks/xstream/io/json/AbstractJsonWriter.java [311:598]
private int handleStateTransition(int currentState, final int requiredState, final String elementToAdd,
final String valueToAdd) {
final int size = stack.size();
final Class<?> currentType = stack.peek().type;
final boolean isArray = size > 1 && isArray(currentType);
final boolean isArrayElement = size > 1 && isArray(stack.get(size - 2).type);
switch (currentState) {
case STATE_ROOT:
if (requiredState == STATE_START_OBJECT) {
currentState = handleStateTransition(STATE_START_ELEMENTS, STATE_START_OBJECT, elementToAdd, null);
return requiredState;
}
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
case STATE_END_OBJECT:
switch (requiredState) {
case STATE_START_OBJECT:
currentState = handleStateTransition(currentState, STATE_NEXT_ELEMENT, null, null);
currentState = handleStateTransition(currentState, STATE_START_OBJECT, elementToAdd, null);
return requiredState;
case STATE_NEXT_ELEMENT:
nextElement();
return requiredState;
case STATE_ROOT:
if (((mode & DROP_ROOT_MODE) == 0 || size > 2) && (mode & EXPLICIT_MODE) == 0) {
endObject();
}
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
case STATE_START_OBJECT:
switch (requiredState) {
case STATE_SET_VALUE:
case STATE_START_OBJECT:
case STATE_ROOT:
case STATE_NEXT_ELEMENT:
if (!isArrayElement || (mode & EXPLICIT_MODE) != 0) {
currentState = handleStateTransition(currentState, STATE_START_ATTRIBUTES, null, null);
currentState = handleStateTransition(currentState, STATE_END_ATTRIBUTES, null, null);
}
currentState = STATE_START_ELEMENTS;
switch (requiredState) {
case STATE_SET_VALUE:
currentState = handleStateTransition(currentState, STATE_SET_VALUE, null, valueToAdd);
break;
case STATE_START_OBJECT:
currentState = handleStateTransition(currentState, STATE_START_OBJECT, elementToAdd, null);
break;
case STATE_ROOT:
case STATE_NEXT_ELEMENT:
currentState = handleStateTransition(currentState, STATE_SET_VALUE, null, null);
currentState = handleStateTransition(currentState, requiredState, null, null);
break;
}
return requiredState;
case STATE_START_ATTRIBUTES:
if ((mode & EXPLICIT_MODE) != 0) {
startArray();
}
return requiredState;
case STATE_NEXT_ATTRIBUTE:
if ((mode & EXPLICIT_MODE) != 0 || !isArray) {
currentState = handleStateTransition(currentState, STATE_START_ATTRIBUTES, null, null);
currentState = handleStateTransition(currentState, STATE_NEXT_ATTRIBUTE, elementToAdd, valueToAdd);
return requiredState;
} else {
return STATE_START_OBJECT;
}
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
case STATE_NEXT_ELEMENT:
switch (requiredState) {
case STATE_START_OBJECT:
nextElement();
if (!isArrayElement && (mode & EXPLICIT_MODE) == 0) {
addLabel(encodeNode(elementToAdd));
if ((mode & EXPLICIT_MODE) == 0 && isArray) {
startArray();
}
return requiredState;
}
break;
case STATE_ROOT:
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
currentState = handleStateTransition(currentState, STATE_ROOT, null, null);
return requiredState;
case STATE_NEXT_ELEMENT:
case STATE_END_OBJECT:
currentState = handleStateTransition(currentState, STATE_END_ELEMENTS, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
if ((mode & EXPLICIT_MODE) == 0 && !isArray) {
endObject();
}
return requiredState;
case STATE_END_ELEMENTS:
if ((mode & EXPLICIT_MODE) == 0 && isArray) {
endArray();
}
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
//$FALL-THROUGH$
case STATE_START_ELEMENTS:
switch (requiredState) {
case STATE_START_OBJECT:
if ((mode & DROP_ROOT_MODE) == 0 || size > 2) {
if (!isArrayElement || (mode & EXPLICIT_MODE) != 0) {
if (!"".equals(valueToAdd)) {
startObject();
}
addLabel(encodeNode(elementToAdd));
}
if ((mode & EXPLICIT_MODE) != 0) {
startArray();
}
}
if ((mode & EXPLICIT_MODE) == 0) {
if (isArray) {
startArray();
}
}
return requiredState;
case STATE_SET_VALUE:
if ((mode & STRICT_MODE) != 0 && size == 2) {
throw new ConversionException("Single value cannot be root element");
}
if (valueToAdd == null) {
if (currentType == Mapper.Null.class) {
addValue("null", Type.NULL);
} else if ((mode & EXPLICIT_MODE) == 0 && !isArray) {
startObject();
endObject();
}
} else {
if ((mode & IEEE_754_MODE) != 0 && (currentType == long.class || currentType == Long.class)) {
final long longValue = Long.parseLong(valueToAdd);
// JavaScript supports a maximum of 2^53
if (longValue > 9007199254740992L || longValue < -9007199254740992L) {
addValue(valueToAdd, Type.STRING);
} else {
addValue(valueToAdd, getType(currentType));
}
} else {
addValue(valueToAdd, getType(currentType));
}
}
return requiredState;
case STATE_END_ELEMENTS:
case STATE_NEXT_ELEMENT:
if ((mode & EXPLICIT_MODE) == 0) {
if (isArray) {
endArray();
} else {
endObject();
}
}
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
case STATE_END_ELEMENTS:
switch (requiredState) {
case STATE_END_OBJECT:
if ((mode & EXPLICIT_MODE) != 0) {
endArray();
endArray();
endObject();
}
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
case STATE_START_ATTRIBUTES:
switch (requiredState) {
case STATE_NEXT_ATTRIBUTE:
if (elementToAdd != null) {
final String name = ((mode & EXPLICIT_MODE) == 0 ? "@" : "") + elementToAdd;
startObject();
addLabel(encodeAttribute(name));
addValue(valueToAdd, Type.STRING);
}
return requiredState;
}
//$FALL-THROUGH$
case STATE_NEXT_ATTRIBUTE:
switch (requiredState) {
case STATE_END_ATTRIBUTES:
if ((mode & EXPLICIT_MODE) != 0) {
if (currentState == STATE_NEXT_ATTRIBUTE) {
endObject();
}
endArray();
nextElement();
startArray();
}
return requiredState;
case STATE_NEXT_ATTRIBUTE:
if (!isArray || (mode & EXPLICIT_MODE) != 0) {
nextElement();
final String name = ((mode & EXPLICIT_MODE) == 0 ? "@" : "") + elementToAdd;
addLabel(encodeAttribute(name));
addValue(valueToAdd, Type.STRING);
}
return requiredState;
case STATE_SET_VALUE:
case STATE_START_OBJECT:
currentState = handleStateTransition(currentState, STATE_END_ATTRIBUTES, null, null);
currentState = handleStateTransition(currentState, STATE_START_ELEMENTS, null, null);
switch (requiredState) {
case STATE_SET_VALUE:
if ((mode & EXPLICIT_MODE) == 0) {
addLabel(encodeNode("$"));
}
currentState = handleStateTransition(currentState, STATE_SET_VALUE, null, valueToAdd);
if ((mode & EXPLICIT_MODE) == 0) {
endObject();
}
break;
case STATE_START_OBJECT:
currentState = handleStateTransition(currentState, STATE_START_OBJECT, elementToAdd, (mode
& EXPLICIT_MODE) == 0 ? "" : null);
break;
case STATE_END_OBJECT:
currentState = handleStateTransition(currentState, STATE_SET_VALUE, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
break;
}
return requiredState;
case STATE_NEXT_ELEMENT:
currentState = handleStateTransition(currentState, STATE_END_ATTRIBUTES, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
return requiredState;
case STATE_ROOT:
currentState = handleStateTransition(currentState, STATE_END_ATTRIBUTES, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
currentState = handleStateTransition(currentState, STATE_ROOT, null, null);
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
case STATE_END_ATTRIBUTES:
switch (requiredState) {
case STATE_START_ELEMENTS:
if ((mode & EXPLICIT_MODE) == 0) {
nextElement();
}
break;
case STATE_END_OBJECT:
currentState = handleStateTransition(STATE_START_ELEMENTS, STATE_END_ELEMENTS, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
break;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
return requiredState;
case STATE_SET_VALUE:
switch (requiredState) {
case STATE_END_ELEMENTS:
if ((mode & EXPLICIT_MODE) == 0 && isArray) {
endArray();
}
return requiredState;
case STATE_NEXT_ELEMENT:
currentState = handleStateTransition(currentState, STATE_END_ELEMENTS, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
return requiredState;
case STATE_ROOT:
currentState = handleStateTransition(currentState, STATE_END_ELEMENTS, null, null);
currentState = handleStateTransition(currentState, STATE_END_OBJECT, null, null);
currentState = handleStateTransition(currentState, STATE_ROOT, null, null);
return requiredState;
default:
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}
}
throw new IllegalWriterStateException(currentState, requiredState, elementToAdd);
}