11/* 
2-  * Copyright 2002-2014  the original author or authors. 
2+  * Copyright 2002-2015  the original author or authors. 
33 * 
44 * Licensed under the Apache License, Version 2.0 (the "License"); 
55 * you may not use this file except in compliance with the License. 
2222import  java .sql .SQLException ;
2323import  java .util .HashMap ;
2424import  java .util .HashSet ;
25+ import  java .util .Locale ;
2526import  java .util .Map ;
2627import  java .util .Set ;
2728
@@ -136,9 +137,51 @@ public void setMappedClass(Class<T> mappedClass) {
136137		}
137138	}
138139
140+ 	/** 
141+ 	 * Get the class that we are mapping to. 
142+ 	 */ 
143+ 	public  final  Class <T > getMappedClass () {
144+ 		return  this .mappedClass ;
145+ 	}
146+ 
147+ 	/** 
148+ 	 * Set whether we're strictly validating that all bean properties have been mapped 
149+ 	 * from corresponding database fields. 
150+ 	 * <p>Default is {@code false}, accepting unpopulated properties in the target bean. 
151+ 	 */ 
152+ 	public  void  setCheckFullyPopulated (boolean  checkFullyPopulated ) {
153+ 		this .checkFullyPopulated  = checkFullyPopulated ;
154+ 	}
155+ 
156+ 	/** 
157+ 	 * Return whether we're strictly validating that all bean properties have been 
158+ 	 * mapped from corresponding database fields. 
159+ 	 */ 
160+ 	public  boolean  isCheckFullyPopulated () {
161+ 		return  this .checkFullyPopulated ;
162+ 	}
163+ 
164+ 	/** 
165+ 	 * Set whether we're defaulting Java primitives in the case of mapping a null value 
166+ 	 * from corresponding database fields. 
167+ 	 * <p>Default is {@code false}, throwing an exception when nulls are mapped to Java primitives. 
168+ 	 */ 
169+ 	public  void  setPrimitivesDefaultedForNullValue (boolean  primitivesDefaultedForNullValue ) {
170+ 		this .primitivesDefaultedForNullValue  = primitivesDefaultedForNullValue ;
171+ 	}
172+ 
173+ 	/** 
174+ 	 * Return whether we're defaulting Java primitives in the case of mapping a null value 
175+ 	 * from corresponding database fields. 
176+ 	 */ 
177+ 	public  boolean  isPrimitivesDefaultedForNullValue () {
178+ 		return  this .primitivesDefaultedForNullValue ;
179+ 	}
180+ 
181+ 
139182	/** 
140183	 * Initialize the mapping metadata for the given class. 
141- 	 * @param mappedClass the mapped class.  
184+ 	 * @param mappedClass the mapped class 
142185	 */ 
143186	protected  void  initialize (Class <T > mappedClass ) {
144187		this .mappedClass  = mappedClass ;
@@ -147,9 +190,9 @@ protected void initialize(Class<T> mappedClass) {
147190		PropertyDescriptor [] pds  = BeanUtils .getPropertyDescriptors (mappedClass );
148191		for  (PropertyDescriptor  pd  : pds ) {
149192			if  (pd .getWriteMethod () != null ) {
150- 				this .mappedFields .put (pd .getName (). toLowerCase ( ), pd );
193+ 				this .mappedFields .put (lowerCaseName ( pd .getName ()), pd );
151194				String  underscoredName  = underscoreName (pd .getName ());
152- 				if  (!pd .getName (). toLowerCase ( ).equals (underscoredName )) {
195+ 				if  (!lowerCaseName ( pd .getName ()).equals (underscoredName )) {
153196					this .mappedFields .put (underscoredName , pd );
154197				}
155198				this .mappedProperties .add (pd .getName ());
@@ -160,18 +203,20 @@ protected void initialize(Class<T> mappedClass) {
160203	/** 
161204	 * Convert a name in camelCase to an underscored name in lower case. 
162205	 * Any upper case letters are converted to lower case with a preceding underscore. 
163- 	 * @param name the string containing  original name 
206+ 	 * @param name the original name 
164207	 * @return the converted name 
208+ 	 * @since 4.2 
209+ 	 * @see #lowerCaseName 
165210	 */ 
166- 	private  String  underscoreName (String  name ) {
211+ 	protected  String  underscoreName (String  name ) {
167212		if  (!StringUtils .hasLength (name )) {
168213			return  "" ;
169214		}
170215		StringBuilder  result  = new  StringBuilder ();
171- 		result .append (name .substring (0 , 1 ). toLowerCase ( ));
216+ 		result .append (lowerCaseName ( name .substring (0 , 1 )));
172217		for  (int  i  = 1 ; i  < name .length (); i ++) {
173218			String  s  = name .substring (i , i  + 1 );
174- 			String  slc  = s . toLowerCase ( );
219+ 			String  slc  = lowerCaseName ( s );
175220			if  (!s .equals (slc )) {
176221				result .append ("_" ).append (slc );
177222			}
@@ -183,45 +228,14 @@ private String underscoreName(String name) {
183228	}
184229
185230	/** 
186- 	 * Get the class that we are mapping to. 
187- 	 */ 
188- 	public  final  Class <T > getMappedClass () {
189- 		return  this .mappedClass ;
190- 	}
191- 
192- 	/** 
193- 	 * Set whether we're strictly validating that all bean properties have been 
194- 	 * mapped from corresponding database fields. 
195- 	 * <p>Default is {@code false}, accepting unpopulated properties in the 
196- 	 * target bean. 
197- 	 */ 
198- 	public  void  setCheckFullyPopulated (boolean  checkFullyPopulated ) {
199- 		this .checkFullyPopulated  = checkFullyPopulated ;
200- 	}
201- 
202- 	/** 
203- 	 * Return whether we're strictly validating that all bean properties have been 
204- 	 * mapped from corresponding database fields. 
205- 	 */ 
206- 	public  boolean  isCheckFullyPopulated () {
207- 		return  this .checkFullyPopulated ;
208- 	}
209- 
210- 	/** 
211- 	 * Set whether we're defaulting Java primitives in the case of mapping a null value 
212- 	 * from corresponding database fields. 
213- 	 * <p>Default is {@code false}, throwing an exception when nulls are mapped to Java primitives. 
214- 	 */ 
215- 	public  void  setPrimitivesDefaultedForNullValue (boolean  primitivesDefaultedForNullValue ) {
216- 		this .primitivesDefaultedForNullValue  = primitivesDefaultedForNullValue ;
217- 	}
218- 
219- 	/** 
220- 	 * Return whether we're defaulting Java primitives in the case of mapping a null value 
221- 	 * from corresponding database fields. 
231+ 	 * Convert the given name to lower case. 
232+ 	 * By default, conversions will happen within the US locale. 
233+ 	 * @param name the original name 
234+ 	 * @return the converted name 
235+ 	 * @since 4.2 
222236	 */ 
223- 	public   boolean   isPrimitivesDefaultedForNullValue ( ) {
224- 		return  primitivesDefaultedForNullValue ;
237+ 	protected   String   lowerCaseName ( String   name ) {
238+ 		return  name . toLowerCase ( Locale . US ) ;
225239	}
226240
227241
@@ -243,7 +257,7 @@ public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
243257
244258		for  (int  index  = 1 ; index  <= columnCount ; index ++) {
245259			String  column  = JdbcUtils .lookupColumnName (rsmd , index );
246- 			PropertyDescriptor  pd  = this .mappedFields .get (column .replaceAll (" " , "" ). toLowerCase ( ));
260+ 			PropertyDescriptor  pd  = this .mappedFields .get (lowerCaseName ( column .replaceAll (" " , "" )));
247261			if  (pd  != null ) {
248262				try  {
249263					Object  value  = getColumnValue (rs , index , pd );
@@ -254,15 +268,14 @@ public T mapRow(ResultSet rs, int rowNumber) throws SQLException {
254268					try  {
255269						bw .setPropertyValue (pd .getName (), value );
256270					}
257- 					catch  (TypeMismatchException  e ) {
258- 						if  (value  == null  && primitivesDefaultedForNullValue ) {
259- 							logger .debug ("Intercepted TypeMismatchException for row "  + rowNumber  +
260- 									" and column '"  + column  + "' with value "  + value  +
261- 									" when setting property '"  + pd .getName () + "' of type "  + pd .getPropertyType () +
262- 									" on object: "  + mappedObject );
271+ 					catch  (TypeMismatchException  ex ) {
272+ 						if  (value  == null  && this .primitivesDefaultedForNullValue ) {
273+ 							logger .debug ("Intercepted TypeMismatchException for row "  + rowNumber  + " and column '"  +
274+ 									column  + "' with null value when setting property '"  + pd .getName () +
275+ 									"' of type "  + pd .getPropertyType () + " on object: "  + mappedObject );
263276						}
264277						else  {
265- 							throw  e ;
278+ 							throw  ex ;
266279						}
267280					}
268281					if  (populatedProperties  != null ) {
0 commit comments