in juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java [412:535]
private <T> BeanMap<T> parseIntoBeanMap(UonReader r, BeanMap<T> m) throws IOException, ParseException, ExecutableException {
int c = r.peekSkipWs();
if (c == -1)
return m;
final int S1=1; // Looking for attrName start.
final int S2=2; // Found attrName end, looking for =.
final int S3=3; // Found =, looking for valStart.
final int S4=4; // Looking for , or }
boolean isInEscape = false;
int state = S1;
String currAttr = "";
mark();
try {
while (c != -1) {
c = r.read();
if (! isInEscape) {
if (state == S1) {
if (c == -1) {
return m;
}
r.unread();
mark();
currAttr = parseAttrName(r, true);
if (currAttr == null) // Value was '%00'
return null;
state = S2;
} else if (state == S2) {
if (c == '\u0002')
state = S3;
else if (c == -1 || c == '\u0001') {
m.put(currAttr, null);
if (c == -1)
return m;
state = S1;
}
} else if (state == S3) {
if (c == -1 || c == '\u0001') {
if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) {
BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
if (pMeta == null) {
onUnknownProperty(currAttr, m, null);
unmark();
} else {
unmark();
setCurrentProperty(pMeta);
// In cases of "&foo=", create an empty instance of the value if createable.
// Otherwise, leave it null.
ClassMeta<?> cm = pMeta.getClassMeta();
if (cm.canCreateNewInstance()) {
try {
pMeta.set(m, currAttr, cm.newInstance());
} catch (BeanRuntimeException e) {
onBeanSetterException(pMeta, e);
throw e;
}
}
setCurrentProperty(null);
}
}
if (c == -1)
return m;
state = S1;
} else {
if (! currAttr.equals(getBeanTypePropertyName(m.getClassMeta()))) {
BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
if (pMeta == null) {
onUnknownProperty(currAttr, m, parseAnything(object(), r.unread(), m.getBean(false), true, null));
unmark();
} else {
unmark();
setCurrentProperty(pMeta);
if (shouldUseExpandedParams(pMeta)) {
ClassMeta et = pMeta.getClassMeta().getElementType();
Object value = parseAnything(et, r.unread(), m.getBean(false), true, pMeta);
setName(et, value, currAttr);
try {
pMeta.add(m, currAttr, value);
} catch (BeanRuntimeException e) {
onBeanSetterException(pMeta, e);
throw e;
}
} else {
ClassMeta<?> cm = pMeta.getClassMeta();
Object value = parseAnything(cm, r.unread(), m.getBean(false), true, pMeta);
setName(cm, value, currAttr);
try {
pMeta.set(m, currAttr, value);
} catch (BeanRuntimeException e) {
onBeanSetterException(pMeta, e);
throw e;
}
}
setCurrentProperty(null);
}
}
state = S4;
}
} else if (state == S4) {
if (c == '\u0001')
state = S1;
else if (c == -1) {
return m;
}
}
}
isInEscape = (c == '\\' && ! isInEscape);
}
if (state == S1)
throw new ParseException(this, "Could not find attribute name on object.");
if (state == S2)
throw new ParseException(this, "Could not find '=' following attribute name on object.");
if (state == S3)
throw new ParseException(this, "Could not find value following '=' on object.");
if (state == S4)
throw new ParseException(this, "Could not find end of object.");
} finally {
unmark();
}
return null; // Unreachable.
}