Skip to content

Commit 0a5987a

Browse files
Resolved #36
Resolved #35
1 parent 67e88f0 commit 0a5987a

11 files changed

+165
-161
lines changed

src/main/java/io/beanmapper/BeanMapper.java

+17-16
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
import io.beanmapper.core.converter.collections.CollectionMapConverter;
1515
import io.beanmapper.core.converter.collections.CollectionSetConverter;
1616
import io.beanmapper.core.converter.impl.*;
17-
import io.beanmapper.core.rule.BeanMapperRule;
18-
import io.beanmapper.core.rule.ConstantMapperRule;
17+
import io.beanmapper.core.rule.MappableFields;
1918
import io.beanmapper.core.unproxy.BeanUnproxy;
2019
import io.beanmapper.core.unproxy.DefaultBeanUnproxy;
2120
import io.beanmapper.core.unproxy.SkippingBeanUnproxy;
@@ -135,7 +134,7 @@ public <S, T> T map(S source, Class<T> targetClass, BeanInitializer beanInitiali
135134
BeanMatch beanMatch = getBeanMatch(source.getClass(), targetClass);
136135
T target = beanInitializer.instantiate(targetClass, getConstructorArguments(source, beanMatch));
137136

138-
return processFields(source, target, beanMatch, new ConstantMapperRule(true));
137+
return processFields(source, target, beanMatch);
139138
}
140139

141140
/**
@@ -182,22 +181,21 @@ public <S, T> Collection<T> map(Collection<S> sourceItems, Class<T> targetClass,
182181
*/
183182
public <S, T> T map(S source, T target) {
184183
BeanMatch beanMatch = getBeanMatch(source.getClass(), target.getClass());
185-
return processFields(source, target, beanMatch, new ConstantMapperRule(true));
184+
return processFields(source, target, beanMatch);
186185
}
187186

188187
/**
189188
* Copies the values from the source object to an existing target instance
190189
* @param source source instance of the properties
191190
* @param target target instance for the properties
192-
* @param rule the matching rule
193191
* @param <S> the instance from which the properties get copied.
194192
* @param <T> the instance to which the properties get copied
195193
* @return the original target instance containing all applicable properties
196194
* @throws BeanMappingException
197195
*/
198-
public <S, T> T map(S source, T target, BeanMapperRule rule) {
196+
public <S, T> T map(S source, T target, MappableFields fieldsToMap) {
199197
BeanMatch beanMatch = getBeanMatch(source.getClass(), target.getClass());
200-
return processFields(source, target, beanMatch, rule);
198+
return processFields(source, target, fieldsToMap.compressBeanMatch(beanMatch));
201199
}
202200

203201
private <S> ConstructorArguments getConstructorArguments(S source, BeanMatch beanMatch) {
@@ -249,7 +247,7 @@ private <T, S> BeanMatch getBeanMatch(Class<S> sourceClazz, Class<T> targetClazz
249247
* @return A filled target object.
250248
* @throws BeanMappingException
251249
*/
252-
private <S, T> T processFields(S source, T target, BeanMatch beanMatch, BeanMapperRule rule) {
250+
private <S, T> T processFields(S source, T target, BeanMatch beanMatch) {
253251
for (String fieldName : beanMatch.getTargetNode().keySet()) {
254252
BeanField sourceField = beanMatch.getSourceNode().get(fieldName);
255253
if(sourceField == null) {
@@ -261,7 +259,7 @@ private <S, T> T processFields(S source, T target, BeanMatch beanMatch, BeanMapp
261259
// No target field found -> check for alias
262260
targetField = beanMatch.getAliases().get(fieldName);
263261
}
264-
processField(new BeanFieldMatch(source, target, sourceField, targetField, fieldName, beanMatch), rule);
262+
processField(new BeanFieldMatch(source, target, sourceField, targetField, fieldName, beanMatch));
265263
}
266264
return target;
267265
}
@@ -271,17 +269,17 @@ private <S, T> T processFields(S source, T target, BeanMatch beanMatch, BeanMapp
271269
* @param beanFieldMatch contains the fields belonging to the source/target field match
272270
* @throws BeanMappingException
273271
*/
274-
private void processField(BeanFieldMatch beanFieldMatch, BeanMapperRule rule) {
272+
private void processField(BeanFieldMatch beanFieldMatch) {
275273
if (!beanFieldMatch.hasMatchingSource()) {
276274
dealWithNonMatchingNode(beanFieldMatch);
277275
return;
278276
}
279277
if (!isConverterFor(beanFieldMatch.getSourceClass(), beanFieldMatch.getTargetClass()) &&
280-
!beanFieldMatch.hasSimilarClasses() &&
281-
isMappableClass(beanFieldMatch.getTargetClass()) &&
278+
(!beanFieldMatch.hasSimilarClasses() || (beanFieldMatch.hasSimilarClasses() && beanFieldMatch.getTargetObject() != null)) &&
279+
isMappableClass(beanFieldMatch.getTargetClass()) &&
282280
beanFieldMatch.getSourceObject() != null) {
283281

284-
dealWithMappableNestedClass(beanFieldMatch, rule);
282+
dealWithMappableNestedClass(beanFieldMatch);
285283
return;
286284
}
287285
if (beanFieldMatch.isMappable()) {
@@ -326,17 +324,20 @@ private void copySourceToTarget(BeanFieldMatch beanFieldMatch) {
326324
* If the field is a class which can itself be mapped to another class, it must be treated
327325
* as such. The matching process is called recursively to deal with this pair.
328326
* @param beanFieldMatch contains the fields belonging to the source/target field match
329-
* @param rule the matching rule
330327
* @throws BeanMappingException
331328
*/
332-
private void dealWithMappableNestedClass(BeanFieldMatch beanFieldMatch, BeanMapperRule rule) {
329+
private void dealWithMappableNestedClass(BeanFieldMatch beanFieldMatch) {
333330
Object encapsulatedSource = beanFieldMatch.getSourceObject();
334331
Object target;
335332
if (encapsulatedSource != null) {
336333
if(beanFieldMatch.getTargetObject() == null){
337334
target = map(encapsulatedSource, beanFieldMatch.getTargetClass());
338335
}else {
339-
target = map(encapsulatedSource, beanFieldMatch.getTarget(), rule);
336+
if(beanFieldMatch.getBeanMatch().getMappableFields() == null) {
337+
target = map(encapsulatedSource, beanFieldMatch.getTargetObject());
338+
} else {
339+
target = map(encapsulatedSource, beanFieldMatch.getTargetObject(), beanFieldMatch.getBeanMatch().getMappableFields().splitForField(beanFieldMatch.getSourceFieldName()));
340+
}
340341
}
341342
beanFieldMatch.writeObject(target);
342343
}

src/main/java/io/beanmapper/core/BeanFieldMatch.java

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ public BeanCollectionInstructions getCollectionInstructions() {
7474
null;
7575
}
7676

77+
public String getSourceFieldName() {
78+
return sourceBeanField.getName();
79+
}
80+
7781
public BeanMatch getBeanMatch() {
7882
return beanMatch;
7983
}

src/main/java/io/beanmapper/core/BeanMatch.java

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.beanmapper.core;
22

3+
import io.beanmapper.core.rule.MappableFields;
4+
35
import java.util.Map;
46

57
public class BeanMatch {
@@ -14,12 +16,19 @@ public class BeanMatch {
1416

1517
private final Map<String, BeanField> aliases;
1618

19+
private final MappableFields mappableFields;
20+
1721
public BeanMatch(Class<?> sourceClass, Class<?> targetClass, Map<String, BeanField> sourceNode, Map<String, BeanField> targetNode, Map<String, BeanField> aliases) {
22+
this(sourceClass, targetClass, sourceNode, targetNode, aliases, null);
23+
}
24+
25+
public BeanMatch(Class<?> sourceClass, Class<?> targetClass, Map<String, BeanField> sourceNode, Map<String, BeanField> targetNode, Map<String, BeanField> aliases, MappableFields mappableFields) {
1826
this.sourceClass = sourceClass;
1927
this.targetClass = targetClass;
2028
this.sourceNode = sourceNode;
2129
this.targetNode = targetNode;
2230
this.aliases = aliases;
31+
this.mappableFields = mappableFields;
2332
}
2433

2534
public Class<?> getSourceClass() {
@@ -41,4 +50,8 @@ public Map<String, BeanField> getTargetNode() {
4150
public Map<String, BeanField> getAliases() {
4251
return aliases;
4352
}
53+
54+
public MappableFields getMappableFields() {
55+
return mappableFields;
56+
}
4457
}

src/main/java/io/beanmapper/core/rule/BeanMapperRule.java

-25
This file was deleted.

src/main/java/io/beanmapper/core/rule/ConstantMapperRule.java

-30
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* (C) 2014 42 bv (www.42.nl). All rights reserved.
3+
*/
4+
package io.beanmapper.core.rule;
5+
6+
import io.beanmapper.core.BeanField;
7+
import io.beanmapper.core.BeanMatch;
8+
9+
import java.util.*;
10+
11+
/**
12+
* Maps each property when the source field is included.
13+
*
14+
* @author Jeroen van Schagen
15+
* @since Nov 6, 2015
16+
*/
17+
public class MappableFields {
18+
19+
private final Set<String> fieldNames;
20+
21+
public MappableFields(Collection<String> fieldNames) {
22+
this.fieldNames = new HashSet<String>(fieldNames);
23+
}
24+
25+
public MappableFields(String... fieldNames) {
26+
this(Arrays.asList(fieldNames));
27+
}
28+
29+
public BeanMatch compressBeanMatch(BeanMatch beanMatch) {
30+
Map<String, BeanField> sourceNode = new HashMap<String, BeanField>();
31+
for(String includeField : fieldNames) {
32+
sourceNode.put(includeField, beanMatch.getSourceNode().get(includeField));
33+
}
34+
return new BeanMatch(beanMatch.getSourceClass(), beanMatch.getTargetClass(), sourceNode, beanMatch.getTargetNode(), beanMatch.getAliases(), this);
35+
}
36+
37+
public MappableFields splitForField(String fieldName) {
38+
Set<String> mappableNestedFields = new HashSet<String>();
39+
for(String includeField : fieldNames) {
40+
String[] splitFields = includeField.split("\\.");
41+
if(splitFields.length > 1 && splitFields[0].equals(fieldName)) {
42+
mappableNestedFields.add(includeField.substring(splitFields[0].length()+1));
43+
}
44+
}
45+
return new MappableFields(mappableNestedFields);
46+
}
47+
}

src/main/java/io/beanmapper/core/rule/SourceFieldMapperRule.java

-44
This file was deleted.

0 commit comments

Comments
 (0)