1
1
package io .beanmapper ;
2
2
3
+ import io .beanmapper .annotations .BeanConstruct ;
3
4
import io .beanmapper .annotations .BeanDefault ;
4
5
import io .beanmapper .annotations .BeanProperty ;
5
6
import io .beanmapper .core .BeanField ;
6
7
import io .beanmapper .core .BeanFieldMatch ;
7
8
import io .beanmapper .core .BeanMatch ;
8
9
import io .beanmapper .core .BeanMatchStore ;
9
10
import io .beanmapper .core .constructor .BeanInitializer ;
10
- import io .beanmapper .core .constructor .NoArgConstructorBeanInitializer ;
11
+ import io .beanmapper .core .constructor .DefaultBeanInitializer ;
11
12
import io .beanmapper .core .converter .BeanConverter ;
12
13
import io .beanmapper .core .converter .collections .CollectionListConverter ;
13
14
import io .beanmapper .core .converter .collections .CollectionMapConverter ;
14
15
import io .beanmapper .core .converter .collections .CollectionSetConverter ;
15
- import io .beanmapper .core .converter .impl .NumberToNumberConverter ;
16
- import io .beanmapper .core .converter .impl .ObjectToStringConverter ;
17
- import io .beanmapper .core .converter .impl .PrimitiveConverter ;
18
- import io .beanmapper .core .converter .impl .StringToBigDecimalConverter ;
19
- import io .beanmapper .core .converter .impl .StringToBooleanConverter ;
20
- import io .beanmapper .core .converter .impl .StringToEnumConverter ;
21
- import io .beanmapper .core .converter .impl .StringToIntegerConverter ;
22
- import io .beanmapper .core .converter .impl .StringToLongConverter ;
16
+ import io .beanmapper .core .converter .impl .*;
23
17
import io .beanmapper .core .rule .BeanMapperRule ;
24
18
import io .beanmapper .core .rule .ConstantMapperRule ;
25
19
import io .beanmapper .core .unproxy .BeanUnproxy ;
26
20
import io .beanmapper .core .unproxy .DefaultBeanUnproxy ;
27
21
import io .beanmapper .core .unproxy .SkippingBeanUnproxy ;
28
22
import io .beanmapper .exceptions .BeanConversionException ;
29
23
import io .beanmapper .exceptions .BeanFieldNoMatchException ;
24
+ import io .beanmapper .exceptions .BeanInstantiationException ;
30
25
import io .beanmapper .exceptions .BeanMappingException ;
26
+ import io .beanmapper .utils .ConstructorArguments ;
31
27
32
28
import java .util .ArrayList ;
33
29
import java .util .Collection ;
@@ -44,7 +40,7 @@ public class BeanMapper {
44
40
/**
45
41
* Initializes the beans.
46
42
*/
47
- private BeanInitializer beanInitializer = new NoArgConstructorBeanInitializer ();
43
+ private BeanInitializer beanInitializer = new DefaultBeanInitializer ();
48
44
49
45
/**
50
46
* Removes any potential proxies of beans.
@@ -136,8 +132,10 @@ public <S, T> T map(S source, Class<T> targetClass, BeanInitializer beanInitiali
136
132
}
137
133
}
138
134
139
- T target = beanInitializer .instantiate (targetClass );
140
- return map (source , target );
135
+ BeanMatch beanMatch = getBeanMatch (source .getClass (), targetClass );
136
+ T target = beanInitializer .instantiate (targetClass , getConstructorArguments (source , beanMatch ));
137
+
138
+ return processFields (source , target , beanMatch , new ConstantMapperRule (true ));
141
139
}
142
140
143
141
/**
@@ -166,7 +164,7 @@ public <S, T> Collection<T> map(Collection<S> sourceItems, Class<T> targetClass)
166
164
*/
167
165
@ SuppressWarnings ({ "unchecked" , "rawtypes" })
168
166
public <S , T > Collection <T > map (Collection <S > sourceItems , Class <T > targetClass , Class <? extends Collection > collectionClass ) {
169
- Collection <T > targetItems = (Collection <T >) beanInitializer .instantiate (collectionClass );
167
+ Collection <T > targetItems = (Collection <T >) beanInitializer .instantiate (collectionClass , null );
170
168
for (S source : sourceItems ) {
171
169
targetItems .add (map (source , targetClass ));
172
170
}
@@ -183,7 +181,8 @@ public <S, T> Collection<T> map(Collection<S> sourceItems, Class<T> targetClass,
183
181
* @throws BeanMappingException
184
182
*/
185
183
public <S , T > T map (S source , T target ) {
186
- return map (source , target , new ConstantMapperRule (true ));
184
+ BeanMatch beanMatch = getBeanMatch (source .getClass (), target .getClass ());
185
+ return processFields (source , target , beanMatch , new ConstantMapperRule (true ));
187
186
}
188
187
189
188
/**
@@ -197,7 +196,44 @@ public <S, T> T map(S source, T target) {
197
196
* @throws BeanMappingException
198
197
*/
199
198
public <S , T > T map (S source , T target , BeanMapperRule rule ) {
200
- return matchSourceToTarget (source , target , rule );
199
+ BeanMatch beanMatch = getBeanMatch (source .getClass (), target .getClass ());
200
+ return processFields (source , target , beanMatch , rule );
201
+ }
202
+
203
+ private <S > ConstructorArguments getConstructorArguments (S source , BeanMatch beanMatch ) {
204
+ BeanConstruct beanConstruct = beanMatch .getTargetClass ().getAnnotation (BeanConstruct .class );
205
+
206
+ if (beanConstruct == null ){
207
+ beanConstruct = beanMatch .getSourceClass ().getAnnotation (BeanConstruct .class );
208
+ }
209
+
210
+ String [] constructArgs ;
211
+ ConstructorArguments arguments = null ;
212
+
213
+ if (beanConstruct != null ){
214
+ constructArgs = beanConstruct .value ();
215
+ arguments = new ConstructorArguments (constructArgs .length );
216
+
217
+ for (int i =0 ; i <constructArgs .length ; i ++) {
218
+ if (beanMatch .getSourceNode ().containsKey (constructArgs [i ]) || beanMatch .getAliases ().containsKey (constructArgs [i ])) {
219
+ BeanField constructField = beanMatch .getSourceNode ().get (constructArgs [i ]);
220
+ if (constructField == null ) {
221
+ constructField = beanMatch .getAliases ().get (constructArgs [i ]);
222
+ }
223
+ arguments .types [i ] = constructField .getProperty ().getType ();
224
+ arguments .values [i ] = constructField .getObject (source );
225
+ } else {
226
+ throw new BeanInstantiationException (beanMatch .getTargetClass (), null );
227
+ }
228
+ }
229
+ }
230
+ return arguments ;
231
+ }
232
+
233
+ private <T , S > BeanMatch getBeanMatch (Class <S > sourceClazz , Class <T > targetClazz ) {
234
+ Class <?> sourceClass = beanUnproxy .unproxy (sourceClazz );
235
+ Class <?> targetClass = beanUnproxy .unproxy (targetClazz );
236
+ return beanMatchStore .getBeanMatch (sourceClass , targetClass );
201
237
}
202
238
203
239
/**
@@ -213,24 +249,23 @@ public <S, T> T map(S source, T target, BeanMapperRule rule) {
213
249
* @return A filled target object.
214
250
* @throws BeanMappingException
215
251
*/
216
- private <S , T > T matchSourceToTarget (S source , T target , BeanMapperRule rule ) {
217
- BeanMatch beanMatch = getBeanMatch (source , target );
252
+ private <S , T > T processFields (S source , T target , BeanMatch beanMatch , BeanMapperRule rule ) {
218
253
for (String fieldName : beanMatch .getTargetNode ().keySet ()) {
219
254
BeanField sourceField = beanMatch .getSourceNode ().get (fieldName );
255
+ if (sourceField == null ) {
256
+ // No source field found -> check for alias
257
+ sourceField = beanMatch .getAliases ().get (fieldName );
258
+ }
220
259
BeanField targetField = beanMatch .getTargetNode ().get (fieldName );
221
- if (rule .isAllowed (sourceField , targetField )) {
222
- processField (new BeanFieldMatch (source , target , sourceField , targetField , fieldName ), rule );
260
+ if (targetField == null ) {
261
+ // No target field found -> check for alias
262
+ targetField = beanMatch .getAliases ().get (fieldName );
223
263
}
264
+ processField (new BeanFieldMatch (source , target , sourceField , targetField , fieldName , beanMatch ), rule );
224
265
}
225
266
return target ;
226
267
}
227
268
228
- private <T , S > BeanMatch getBeanMatch (S source , T target ) {
229
- Class <?> sourceClass = beanUnproxy .unproxy (source .getClass ());
230
- Class <?> targetClass = beanUnproxy .unproxy (target .getClass ());
231
- return beanMatchStore .getBeanMatch (sourceClass , targetClass );
232
- }
233
-
234
269
/**
235
270
* Process a single combination of a source and a target field.
236
271
* @param beanFieldMatch contains the fields belonging to the source/target field match
@@ -296,9 +331,14 @@ private void copySourceToTarget(BeanFieldMatch beanFieldMatch) {
296
331
*/
297
332
private void dealWithMappableNestedClass (BeanFieldMatch beanFieldMatch , BeanMapperRule rule ) {
298
333
Object encapsulatedSource = beanFieldMatch .getSourceObject ();
334
+ Object target ;
299
335
if (encapsulatedSource != null ) {
300
- Object encapsulatedTarget = beanFieldMatch .getOrCreateTargetObject ();
301
- matchSourceToTarget (encapsulatedSource , encapsulatedTarget , rule );
336
+ if (beanFieldMatch .getTargetObject () == null ){
337
+ target = map (encapsulatedSource , beanFieldMatch .getTargetClass ());
338
+ }else {
339
+ target = map (encapsulatedSource , beanFieldMatch .getTarget (), rule );
340
+ }
341
+ beanFieldMatch .writeObject (target );
302
342
}
303
343
}
304
344
0 commit comments