in google-http-client/src/main/java/com/google/api/client/http/UrlEncodedParser.java [127:212]
public static void parse(Reader reader, Object data) throws IOException {
Class<?> clazz = data.getClass();
ClassInfo classInfo = ClassInfo.of(clazz);
List<Type> context = Arrays.<Type>asList(clazz);
GenericData genericData = GenericData.class.isAssignableFrom(clazz) ? (GenericData) data : null;
@SuppressWarnings("unchecked")
Map<Object, Object> map = Map.class.isAssignableFrom(clazz) ? (Map<Object, Object>) data : null;
ArrayValueMap arrayValueMap = new ArrayValueMap(data);
StringWriter nameWriter = new StringWriter();
StringWriter valueWriter = new StringWriter();
boolean readingName = true;
mainLoop: while (true) {
int read = reader.read();
switch (read) {
case -1:
// falls through
case '&':
// parse name/value pair
String name = CharEscapers.decodeUri(nameWriter.toString());
if (name.length() != 0) {
String stringValue = CharEscapers.decodeUri(valueWriter.toString());
// get the field from the type information
FieldInfo fieldInfo = classInfo.getFieldInfo(name);
if (fieldInfo != null) {
Type type =
Data.resolveWildcardTypeOrTypeVariable(context, fieldInfo.getGenericType());
// type is now class, parameterized type, or generic array type
if (Types.isArray(type)) {
// array that can handle repeating values
Class<?> rawArrayComponentType =
Types.getRawArrayComponentType(context, Types.getArrayComponentType(type));
arrayValueMap.put(fieldInfo.getField(), rawArrayComponentType,
parseValue(rawArrayComponentType, context, stringValue));
} else if (Types.isAssignableToOrFrom(
Types.getRawArrayComponentType(context, type), Iterable.class)) {
// iterable that can handle repeating values
@SuppressWarnings("unchecked")
Collection<Object> collection = (Collection<Object>) fieldInfo.getValue(data);
if (collection == null) {
collection = Data.newCollectionInstance(type);
fieldInfo.setValue(data, collection);
}
Type subFieldType = type == Object.class ? null : Types.getIterableParameter(type);
collection.add(parseValue(subFieldType, context, stringValue));
} else {
// parse into a field that assumes it is a single value
fieldInfo.setValue(data, parseValue(type, context, stringValue));
}
} else if (map != null) {
// parse into a map: store as an ArrayList of values
@SuppressWarnings("unchecked")
ArrayList<String> listValue = (ArrayList<String>) map.get(name);
if (listValue == null) {
listValue = new ArrayList<String>();
if (genericData != null) {
genericData.set(name, listValue);
} else {
map.put(name, listValue);
}
}
listValue.add(stringValue);
}
}
// ready to read next name/value pair
readingName = true;
nameWriter = new StringWriter();
valueWriter = new StringWriter();
if (read == -1) {
break mainLoop;
}
break;
case '=':
// finished with name, now read value
readingName = false;
break;
default:
// read one more character
if (readingName) {
nameWriter.write(read);
} else {
valueWriter.write(read);
}
}
}
arrayValueMap.setValues();
}