Case-Insensitive Property Transfer Between Objects
Mapping properties between objects with different naming conventions can be tedious. The following utility enables property copying while ignoring case differences in field names.
public <T> T mapPropertiesIgnoreCase(Object source, Class<T> targetClass) {
T target = null;
try {
if (source != null && !"".equals(source)) {
target = targetClass.newInstance();
Map<String, Field> fieldMap = new HashMap<>();
for (Field field : targetClass.getDeclaredFields()) {
fieldMap.put(field.getName().toLowerCase(), field);
}
for (Field sourceField : source.getClass().getDeclaredFields()) {
Field destField = fieldMap.get(sourceField.getName().toLowerCase());
if (destField != null) {
destField.setAccessible(true);
sourceField.setAccessible(true);
if (destField.getType() == String.class) {
destField.set(target, sourceField.get(source));
} else if (destField.getType() == LocalDateTime.class) {
Object value = sourceField.get(source);
if (value != null) {
destField.set(target, parseToLocalDateTime(value.toString()));
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return target;
}
Parsing Non-Standard Date Strings to LocalDateTime
The date string format "5/2/2017 4:48:49 PM" requires special handling since it uses 12-hour format with AM/PM indicators.
public static LocalDateTime parseToLocalDateTime(String dateStr) {
Date parsed = convertStringToDate(dateStr);
return LocalDateTimeUtils.parseDataToLocalDateTime(parsed);
}
private static Date convertStringToDate(String dateStr) {
String trimmed = dateStr.trim();
SimpleDateFormat format;
boolean hasSlash = trimmed.indexOf("/") > -1;
boolean hasPeriod = trimmed.contains("AM") || trimmed.contains("PM");
if (hasSlash && hasPeriod) {
format = new SimpleDateFormat("MM/dd/yyyy KK:mm:ss a", Locale.ENGLISH);
} else {
format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss z");
}
ParsePosition position = new ParsePosition(0);
return format.parse(trimmed, position);
}
Key Implementation Details
The field mapping process first collects all target class fields into a map using lowercase keys. During the transfer loop, source fields are matched against this map using case-insensitive comparison. String and LocalDateTime types receive special handling to ensure correct data transformation for these common field types.