d, Field>[] fields, String prefix) {
+ this.d = d;
+ this.f = new Field[fields.length];
+
+ String dotted = prefix + ".";
+ for (int i = 0; i < fields.length; i++)
+ if (fields[i].getName().startsWith(dotted))
+ f[i] = field(name(fields[i].getName().substring(dotted.length() + 1)), fields[i].getDataType());
+ }
+
+ @Override
+ public Object map(R record) {
+ AbstractRecord copy = (AbstractRecord) DSL.using(configuration).newRecord(f);
+
+ for (int i = 0; i < f.length; i++)
+ if (f[i] != null)
+ copy.setValue(i, record.getValue(i));
+
+ return d.map(record);
+ }
+ }
+
/**
* Convert a record into a mutable POJO type
*
@@ -440,32 +491,86 @@ public final AbstractRecord map(R record) {
*/
private class MutablePOJOMapper implements RecordMapper {
- private final Constructor extends E> constructor;
- private final boolean useAnnotations;
- private final List[] members;
- private final List[] methods;
+ private final Constructor extends E> constructor;
+ private final boolean useAnnotations;
+ private final List[] members;
+ private final List[] methods;
+ private final Map>> nested;
MutablePOJOMapper(Constructor extends E> constructor) {
this.constructor = accessible(constructor);
this.useAnnotations = hasColumnAnnotations(configuration, type);
this.members = new List[fields.length];
this.methods = new List[fields.length];
+ this.nested = new HashMap>>();
+ Map[]> nestedFields = new HashMap[]>();
for (int i = 0; i < fields.length; i++) {
Field> field = fields[i];
+ String name = field.getName();
// Annotations are available and present
if (useAnnotations) {
- members[i] = getAnnotatedMembers(configuration, type, field.getName());
- methods[i] = getAnnotatedSetters(configuration, type, field.getName());
+ members[i] = getAnnotatedMembers(configuration, type, name);
+ methods[i] = getAnnotatedSetters(configuration, type, name);
}
// No annotations are present
else {
- members[i] = getMatchingMembers(configuration, type, field.getName());
- methods[i] = getMatchingSetters(configuration, type, field.getName());
+ int dot = name.indexOf('.');
+
+ // A nested mapping is applied
+ if (dot > -1) {
+ String prefix = name.substring(0, dot);
+
+ Field>[] f = nestedFields.get(prefix);
+ if (f == null) {
+ f = nCopies(fields.length, field("")).toArray(new Field[fields.length]);
+ nestedFields.put(prefix, f);
+ }
+
+ f[i] = field(name(name.substring(prefix.length() + 1)), field.getDataType());
+
+ members[i] = Collections.emptyList();
+ methods[i] = Collections.emptyList();
+ }
+
+ // A top-level mapping is applied
+ else {
+ members[i] = getMatchingMembers(configuration, type, name);
+ methods[i] = getMatchingSetters(configuration, type, name);
+ }
}
}
+
+ for (Entry[]> entry : nestedFields.entrySet()) {
+ String prefix = entry.getKey();
+ List> list = new ArrayList>();
+
+ for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
+ list.add(new RemovingPrefixRecordMapper(
+ new DefaultRecordMapper(
+ new Fields(entry.getValue()),
+ member.getType(),
+ instance,
+ configuration
+ ), fields, prefix
+ ));
+ }
+
+ for (Method method : getMatchingSetters(configuration, type, prefix)) {
+ list.add(new RemovingPrefixRecordMapper(
+ new DefaultRecordMapper(
+ new Fields(entry.getValue()),
+ method.getParameterTypes()[0],
+ instance,
+ configuration
+ ), fields, prefix
+ ));
+ }
+
+ nested.put(prefix, list);
+ }
}
@Override
@@ -487,6 +592,26 @@ public final E map(R record) {
}
}
+ for (Entry>> entry : nested.entrySet()) {
+ String prefix = entry.getKey();
+
+ for (RecordMapper mapper : entry.getValue()) {
+ Object value = mapper.map(record);
+
+ for (java.lang.reflect.Field member : getMatchingMembers(configuration, type, prefix)) {
+
+ // [#935] Avoid setting final fields
+ if ((member.getModifiers() & Modifier.FINAL) == 0) {
+ map(value, result, member);
+ }
+ }
+
+ for (Method method : getMatchingSetters(configuration, type, prefix)) {
+ method.invoke(result, value);
+ }
+ }
+ }
+
return result;
}
catch (Exception e) {
@@ -499,32 +624,66 @@ private final void map(Record record, Object result, java.lang.reflect.Field mem
if (mType.isPrimitive()) {
if (mType == byte.class) {
- member.setByte(result, record.getValue(index, byte.class));
+ map(record.getValue(index, byte.class), result, member);
+ }
+ else if (mType == short.class) {
+ map(record.getValue(index, short.class), result, member);
+ }
+ else if (mType == int.class) {
+ map(record.getValue(index, int.class), result, member);
+ }
+ else if (mType == long.class) {
+ map(record.getValue(index, long.class), result, member);
+ }
+ else if (mType == float.class) {
+ map(record.getValue(index, float.class), result, member);
+ }
+ else if (mType == double.class) {
+ map(record.getValue(index, double.class), result, member);
+ }
+ else if (mType == boolean.class) {
+ map(record.getValue(index, boolean.class), result, member);
+ }
+ else if (mType == char.class) {
+ map(record.getValue(index, char.class), result, member);
+ }
+ }
+ else {
+ map(record.getValue(index, mType), result, member);
+ }
+ }
+
+ private final void map(Object value, Object result, java.lang.reflect.Field member) throws IllegalAccessException {
+ Class> mType = member.getType();
+
+ if (mType.isPrimitive()) {
+ if (mType == byte.class) {
+ member.setByte(result, (Byte) value);
}
else if (mType == short.class) {
- member.setShort(result, record.getValue(index, short.class));
+ member.setShort(result, (Short) value);
}
else if (mType == int.class) {
- member.setInt(result, record.getValue(index, int.class));
+ member.setInt(result, (Integer) value);
}
else if (mType == long.class) {
- member.setLong(result, record.getValue(index, long.class));
+ member.setLong(result, (Long) value);
}
else if (mType == float.class) {
- member.setFloat(result, record.getValue(index, float.class));
+ member.setFloat(result, (Float) value);
}
else if (mType == double.class) {
- member.setDouble(result, record.getValue(index, double.class));
+ member.setDouble(result, (Double) value);
}
else if (mType == boolean.class) {
- member.setBoolean(result, record.getValue(index, boolean.class));
+ member.setBoolean(result, (Boolean) value);
}
else if (mType == char.class) {
- member.setChar(result, record.getValue(index, char.class));
+ member.setChar(result, (Character) value);
}
}
else {
- member.set(result, record.getValue(index, mType));
+ member.set(result, value);
}
}
}