Map<String, Boolean> hasProcessedPrefixMap = new HashMap<String, Boolean>();
Class<?> targetType = binder.getTarget().getClass();
ServletRequest servletRequest = prepareServletRequest(binder.getTarget(), request, parameter);
WebDataBinder simpleBinder = binderFactory.createBinder(request, null, null);
if (Collection.class.isAssignableFrom(targetType)) {//bind collection or array
Type type = parameter.getGenericParameterType();
Class<?> componentType = Object.class;
Collection target = (Collection) binder.getTarget();
List targetList = new ArrayList(target);
if (type instanceof ParameterizedType) {
componentType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
if (parameter.getParameterType().isArray()) {
componentType = parameter.getParameterType().getComponentType();
}
for (Object key : servletRequest.getParameterMap().keySet()) {
String prefixName = getPrefixName((String) key);
//每个prefix 只处理一次
if (hasProcessedPrefixMap.containsKey(prefixName)) {
continue;
} else {
hasProcessedPrefixMap.put(prefixName, Boolean.TRUE);
}
if (isSimpleComponent(prefixName)) { //bind simple type
Map<String, Object> paramValues = WebUtils.getParametersStartingWith(servletRequest, prefixName);
Matcher matcher = INDEX_PATTERN.matcher(prefixName);
if(!matcher.matches()) { //处理如 array=1&array=2的情况
for (Object value : paramValues.values()) {
targetList.add(simpleBinder.convertIfNecessary(value, componentType));
}
} else { //处理如 array[0]=1&array[1]=2的情况
int index = Integer.valueOf(matcher.group(1));
if (targetList.size() <= index) {
growCollectionIfNecessary(targetList, index);
}
targetList.set(index, simpleBinder.convertIfNecessary(paramValues.values(), componentType));
}
} else { //处理如 votes[1].title=votes[1].title&votes[0].title=votes[0].title&votes[0].id=0&votes[1].id=1
Object component = null;
//先查找老的 即已经在集合中的数据(而不是新添加一个)
Matcher matcher = INDEX_PATTERN.matcher(prefixName);
if(!matcher.matches()) {
throw new IllegalArgumentException("bind collection error, need integer index, key:" + key);
}
int index = Integer.valueOf(matcher.group(1));
if (targetList.size() <= index) {
growCollectionIfNecessary(targetList, index);
}
Iterator iterator = targetList.iterator();
for (int i = 0; i < index; i++) {
iterator.next();
}
component = iterator.next();
if(component == null) {
component = BeanUtils.instantiate(componentType);
}
WebDataBinder componentBinder = binderFactory.createBinder(request, component, null);
component = componentBinder.getTarget();
if (component != null) {
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(servletRequest, prefixName, "");
componentBinder.bind(pvs);
validateIfApplicable(componentBinder, parameter);
if (componentBinder.getBindingResult().hasErrors()) {
if (isBindExceptionRequired(componentBinder, parameter)) {
throw new BindException(componentBinder.getBindingResult());
}
}
targetList.set(index, component);
}
}
target.clear();
target.addAll(targetList);
}
} else if (MapWapper.class.isAssignableFrom(targetType)) {
Type type = parameter.getGenericParameterType();
Class<?> keyType = Object.class;
Class<?> valueType = Object.class;
if (type instanceof ParameterizedType) {
keyType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
valueType = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[1];
}
MapWapper mapWapper = ((MapWapper) binder.getTarget());
Map target = mapWapper.getInnerMap();
if(target == null) {
target = new HashMap();
mapWapper.setInnerMap(target);
}
for (Object key : servletRequest.getParameterMap().keySet()) {
String prefixName = getPrefixName((String) key);
//每个prefix 只处理一次
if (hasProcessedPrefixMap.containsKey(prefixName)) {
continue;
} else {
hasProcessedPrefixMap.put(prefixName, Boolean.TRUE);
}
Object keyValue = simpleBinder.convertIfNecessary(getMapKey(prefixName), keyType);
if (isSimpleComponent(prefixName)) { //bind simple type
Map<String, Object> paramValues = WebUtils.getParametersStartingWith(servletRequest, prefixName);
for (Object value : paramValues.values()) {
target.put(keyValue, simpleBinder.convertIfNecessary(value, valueType));
}
} else {
Object component = target.get(keyValue);
if(component == null) {
component = BeanUtils.instantiate(valueType);
}
WebDataBinder componentBinder = binderFactory.createBinder(request, component, null);
component = componentBinder.getTarget();
if (component != null) {
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(servletRequest, prefixName, "");
componentBinder.bind(pvs);
validateComponent(componentBinder, parameter);
target.put(keyValue, component);
}