@@ -329,7 +329,7 @@ private void bindWithRequestAndPropertyValues(ServletRequest request, MutablePro
329329
330330 if (request instanceof MultipartHttpServletRequest ) {
331331 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest ) request ;
332- bindMultipartFiles (multipartRequest .getFileMap (), mpvs );
332+ bindMultipart (multipartRequest .getMultiFileMap (), mpvs );
333333 }
334334 doBind (mpvs );
335335 }
@@ -886,60 +886,107 @@ private boolean isStructured(PropertyValue propertyValue) {
886886
887887 /**
888888 * Checks for structured properties. Structured properties are properties with a name
889- * containg a "_"
889+ * containg a "_".
890890 *
891891 * @param propertyValues
892892 */
893- @ SuppressWarnings ("unchecked" )
894893 private void checkStructuredProperties (MutablePropertyValues propertyValues ) {
895- PropertyValue [] pvs = propertyValues .getPropertyValues ();
896- for (PropertyValue propertyValue : pvs ) {
894+ Map <String , PropertyValue > valuesByName = new HashMap <String , PropertyValue >();
895+ List <String > valueNames = new ArrayList <String >();
896+ mapPropertyValues (propertyValues .getPropertyValues (), valuesByName , valueNames );
897+
898+ while (!valueNames .isEmpty ()) {
899+ String name = valueNames .remove (0 );
900+ PropertyValue propertyValue = valuesByName .get (name );
901+
897902 if (!isStructured (propertyValue )) {
898903 continue ;
899904 }
905+
900906 String propertyName = getNameOf (propertyValue );
901907 Class <?> type = bean .getPropertyType (propertyName );
902- if (type != null ) {
903- PropertyEditor editor = findCustomEditor (type , propertyName );
904- if (null != editor && StructuredPropertyEditor .class .isAssignableFrom (editor .getClass ())) {
905- StructuredPropertyEditor structuredEditor = (StructuredPropertyEditor ) editor ;
906- List fields = new ArrayList ();
907- fields .addAll (structuredEditor .getRequiredFields ());
908- fields .addAll (structuredEditor .getOptionalFields ());
909- Map <String , String > fieldValues = new HashMap <String , String >();
910- try {
911- for (Object fld : fields ) {
912- String field = (String ) fld ;
913- PropertyValue partialStructValue = propertyValues .getPropertyValue (propertyName + STRUCTURED_PROPERTY_SEPERATOR + field );
914- if (partialStructValue == null && structuredEditor .getRequiredFields ().contains (field )) {
915- throw new MissingPropertyException ("Required structured property is missing [" + field + "]" );
916- }
917- else if (partialStructValue == null ) {
918- continue ;
919- }
920- fieldValues .put (field , getStringValue (partialStructValue ));
921- }
922- try {
923- Object value = structuredEditor .assemble (type , fieldValues );
924- for (Object fld : fields ) {
925- String field = (String ) fld ;
926- PropertyValue partialStructValue = propertyValues .getPropertyValue (propertyName + STRUCTURED_PROPERTY_SEPERATOR + field );
927- if (null != partialStructValue ) {
928- partialStructValue .setConvertedValue (getStringValue (partialStructValue ));
929- }
930- }
931- propertyValues .addPropertyValue (new PropertyValue (propertyName , value ));
932- }
933- catch (IllegalArgumentException iae ) {
934- LOG .warn ("Unable to parse structured date from request for date [" + propertyName + "]" , iae );
935- }
908+ if (type == null ) {
909+ continue ;
910+ }
911+
912+ PropertyEditor editor = findCustomEditor (type , propertyName );
913+ if (null == editor || !StructuredPropertyEditor .class .isAssignableFrom (editor .getClass ())) {
914+ continue ;
915+ }
916+
917+ StructuredPropertyEditor structuredEditor = (StructuredPropertyEditor ) editor ;
918+ processStructuredProperty (structuredEditor , propertyName , type , valueNames , propertyValues );
919+ }
920+ }
921+
922+ @ SuppressWarnings ("unchecked" )
923+ private void processStructuredProperty (StructuredPropertyEditor structuredEditor , String propertyName , Class <?> type ,
924+ List <String > valueNames , MutablePropertyValues propertyValues ) {
925+
926+ List requiredFields = structuredEditor .getRequiredFields ();
927+ List <String > fields = new ArrayList <String >();
928+ fields .addAll (requiredFields );
929+ fields .addAll (structuredEditor .getOptionalFields ());
930+
931+ Map <String , String > fieldValues = new HashMap <String , String >();
932+ try {
933+
934+ String firstRequiredField = null ;
935+ for (String field : fields ) {
936+ String fullName = propertyName + STRUCTURED_PROPERTY_SEPERATOR + field ;
937+
938+ // don't re-process related properties
939+ valueNames .remove (fullName );
940+
941+ if (firstRequiredField != null ) {
942+ continue ;
943+ }
944+
945+ PropertyValue partialStructValue = propertyValues .getPropertyValue (fullName );
946+ if (partialStructValue == null ) {
947+ if (requiredFields .contains (field )) {
948+ firstRequiredField = field ;
936949 }
937- catch (InvalidPropertyException ipe ) {
938- // ignore
950+ }
951+ else {
952+ fieldValues .put (field , getStringValue (partialStructValue ));
953+ }
954+ }
955+
956+ // set to null since it either won't be created because of problem, or will be overwritten
957+ propertyValues .removePropertyValue (propertyName );
958+
959+ if (firstRequiredField != null ) {
960+ throw new MissingPropertyException (
961+ "Required structured property is missing [" + firstRequiredField + "]" );
962+ }
963+
964+ try {
965+ Object value = structuredEditor .assemble (type , fieldValues );
966+ for (String field : fields ) {
967+ PropertyValue partialStructValue = propertyValues .getPropertyValue (
968+ propertyName + STRUCTURED_PROPERTY_SEPERATOR + field );
969+ if (null != partialStructValue ) {
970+ partialStructValue .setConvertedValue (getStringValue (partialStructValue ));
939971 }
940972 }
973+ propertyValues .addPropertyValue (new PropertyValue (propertyName , value ));
974+ }
975+ catch (IllegalArgumentException e ) {
976+ LOG .warn ("Unable to parse structured date from request for date [" + propertyName + "]" , e );
941977 }
942978 }
979+ catch (InvalidPropertyException ignored ) {
980+ // ignored
981+ }
982+ }
983+
984+ private void mapPropertyValues (PropertyValue [] pvs ,
985+ Map <String , PropertyValue > valuesByName , List <String > valueNames ) {
986+ for (PropertyValue pv : pvs ) {
987+ valuesByName .put (pv .getName (), pv );
988+ valueNames .add (pv .getName ());
989+ }
943990 }
944991
945992 private String getStringValue (PropertyValue yearProperty ) {
0 commit comments