Coverage Report - org.dozer.loader.DozerBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
DozerBuilder
100%
33/33
87%
14/16
1.198
DozerBuilder$ClassDefinitionBuilder
100%
19/19
N/A
1.198
DozerBuilder$ConfigurationBuilder
94%
34/36
50%
2/4
1.198
DozerBuilder$CustomConverterBuilder
100%
11/11
N/A
1.198
DozerBuilder$FieldBuider
N/A
N/A
1.198
DozerBuilder$FieldDefinitionBuilder
95%
21/22
N/A
1.198
DozerBuilder$FieldExclusionBuilder
100%
14/14
N/A
1.198
DozerBuilder$FieldMappingBuilder
97%
66/68
100%
14/14
1.198
DozerBuilder$MappingBuilder
100%
47/47
100%
2/2
1.198
 
 1  
 /**
 2  
  * Copyright 2005-2013 Dozer Project
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.dozer.loader;
 17  
 
 18  
 import org.apache.commons.lang3.StringUtils;
 19  
 import org.dozer.CustomConverter;
 20  
 import org.dozer.MappingException;
 21  
 import org.dozer.classmap.*;
 22  
 import org.dozer.converters.CustomConverterDescription;
 23  
 import org.dozer.fieldmap.*;
 24  
 import org.dozer.util.DozerConstants;
 25  
 import org.dozer.util.MappingUtils;
 26  
 
 27  
 import java.util.ArrayList;
 28  
 import java.util.List;
 29  
 
 30  
 /**
 31  
  * Builder API for achivieng the same effect as custom Xml mappings.
 32  
  * Is intended to be used from application to prepare repetetive mappings programmatically.
 33  
  * <p/>
 34  
  * Note that some of the fail-fast checks from Xml validation has not yet been ported.
 35  
  * Responsibility on filling all mandatory attributes is left to API user.
 36  
  * <p/>
 37  
  * Not thread safe
 38  
  *
 39  
  * @author dmitry.buzdin
 40  
  */
 41  56130
 public class DozerBuilder {
 42  
 
 43  630
   MappingFileData data = new MappingFileData();
 44  630
   private final List<MappingBuilder> mappingBuilders = new ArrayList<MappingBuilder>();
 45  
 
 46  
   public MappingFileData build() {
 47  626
     for (MappingBuilder builder : mappingBuilders) {
 48  5480
       builder.build();
 49  5480
     }
 50  626
     return data;
 51  
   }
 52  
 
 53  
   public ConfigurationBuilder configuration() {
 54  233
     Configuration configuration = new Configuration();
 55  233
     data.setConfiguration(configuration);
 56  233
     return new ConfigurationBuilder(configuration);
 57  
   }
 58  
 
 59  
   public MappingBuilder mapping() {
 60  5484
     Configuration configuration = data.getConfiguration();
 61  5484
     ClassMap classMap = new ClassMap(configuration);
 62  5484
     data.getClassMaps().add(classMap);
 63  5484
     MappingBuilder mappingDefinitionBuilder = new MappingBuilder(classMap);
 64  5484
     mappingBuilders.add(mappingDefinitionBuilder);
 65  5484
     return mappingDefinitionBuilder;
 66  
   }
 67  
 
 68  
   public static class MappingBuilder {
 69  
 
 70  
     private ClassMap classMap;
 71  5484
     private final List<FieldBuider> fieldBuilders = new ArrayList<FieldBuider>();
 72  
 
 73  5484
     public MappingBuilder(ClassMap classMap) {
 74  5484
       this.classMap = classMap;
 75  5484
     }
 76  
 
 77  
     public MappingBuilder dateFormat(String dateFormat) {
 78  110
       classMap.setDateFormat(dateFormat);
 79  110
       return this;
 80  
     }
 81  
 
 82  
     public MappingBuilder mapNull(boolean value) {
 83  67
       classMap.setMapNull(value);
 84  67
       return this;
 85  
     }
 86  
 
 87  
     public MappingBuilder mapEmptyString(boolean value) {
 88  15
       classMap.setMapEmptyString(value);
 89  15
       return this;
 90  
     }
 91  
 
 92  
     // TODO Load class ?
 93  
     public MappingBuilder beanFactory(String typeName) {
 94  1
       classMap.setBeanFactory(typeName);
 95  1
       return this;
 96  
     }
 97  
 
 98  
     public MappingBuilder relationshipType(RelationshipType type) {
 99  3
       classMap.setRelationshipType(type);
 100  3
       return this;
 101  
     }
 102  
 
 103  
     public MappingBuilder wildcard(Boolean value) {
 104  871
       classMap.setWildcard(value);
 105  871
       return this;
 106  
     }
 107  
 
 108  
     public MappingBuilder trimStrings(Boolean value) {
 109  7
       classMap.setTrimStrings(value);
 110  7
       return this;
 111  
     }
 112  
 
 113  
     public MappingBuilder stopOnErrors(Boolean value) {
 114  444
       classMap.setStopOnErrors(value);
 115  444
       return this;
 116  
     }
 117  
 
 118  
     public MappingBuilder mapId(String id) {
 119  677
       classMap.setMapId(id);
 120  677
       return this;
 121  
     }
 122  
 
 123  
     public MappingBuilder type(MappingDirection type) {
 124  281
       classMap.setType(type);
 125  281
       return this;
 126  
     }
 127  
 
 128  
     public ClassDefinitionBuilder classA(String typeName) {
 129  5484
       Class<?> type = MappingUtils.loadClass(typeName);
 130  5482
       return classA(type);
 131  
     }
 132  
 
 133  
     public ClassDefinitionBuilder classA(Class type) {
 134  5482
       DozerClass classDefinition = new DozerClass();
 135  5482
       classDefinition.setName(type.getName());
 136  5482
       classMap.setSrcClass(classDefinition);
 137  5482
       return new ClassDefinitionBuilder(classDefinition);
 138  
     }
 139  
 
 140  
     public ClassDefinitionBuilder classB(String typeName) {
 141  5482
       Class<?> type = MappingUtils.loadClass(typeName);
 142  5482
       return classB(type);
 143  
     }
 144  
 
 145  
     public ClassDefinitionBuilder classB(Class type) {
 146  5482
       DozerClass classDefinition = new DozerClass();
 147  5482
       classDefinition.setName(type.getName());
 148  5482
       classMap.setDestClass(classDefinition);
 149  5482
       return new ClassDefinitionBuilder(classDefinition);
 150  
     }
 151  
 
 152  
     public FieldExclusionBuilder fieldExclude() {
 153  829
       ExcludeFieldMap excludeFieldMap = new ExcludeFieldMap(classMap);
 154  829
       FieldExclusionBuilder builder = new FieldExclusionBuilder(excludeFieldMap);
 155  829
       fieldBuilders.add(builder);
 156  829
       return builder;
 157  
     }
 158  
 
 159  
     public FieldMappingBuilder field() {
 160  13473
       FieldMappingBuilder builder = new FieldMappingBuilder(classMap);
 161  13473
       fieldBuilders.add(builder);
 162  13473
       return builder;
 163  
     }
 164  
 
 165  
     public void build() {
 166  5480
       for (FieldBuider builder : fieldBuilders) {
 167  14300
         builder.build();
 168  14300
       }
 169  5480
     }
 170  
 
 171  
   }
 172  
 
 173  
   public interface FieldBuider {
 174  
     FieldDefinitionBuilder a(String name, String type);
 175  
 
 176  
     FieldDefinitionBuilder b(String name, String type);
 177  
 
 178  
     void build();
 179  
   }
 180  
 
 181  
   public static class FieldExclusionBuilder implements FieldBuider {
 182  
 
 183  
     private ExcludeFieldMap fieldMap;
 184  
 
 185  829
     public FieldExclusionBuilder(ExcludeFieldMap fieldMap) {
 186  829
       this.fieldMap = fieldMap;
 187  829
     }
 188  
 
 189  
     public void type(MappingDirection type) {
 190  828
       fieldMap.setType(type);
 191  828
     }
 192  
 
 193  
     public FieldDefinitionBuilder a(String name, String type) {
 194  829
       DozerField field = prepareField(name, type);
 195  829
       fieldMap.setSrcField(field);
 196  829
       return new FieldDefinitionBuilder(field);
 197  
     }
 198  
 
 199  
     public FieldDefinitionBuilder b(String name, String type) {
 200  829
       DozerField field = prepareField(name, type);
 201  829
       fieldMap.setDestField(field);
 202  829
       return new FieldDefinitionBuilder(field);
 203  
     }
 204  
 
 205  
 
 206  
     public void build() {
 207  829
       ClassMap classMap = fieldMap.getClassMap();
 208  829
       classMap.addFieldMapping(fieldMap);
 209  829
     }
 210  
 
 211  
   }
 212  
 
 213  
   public static class FieldMappingBuilder implements FieldBuider {
 214  
 
 215  
     private ClassMap classMap;
 216  
     private DozerField srcField;
 217  
     private DozerField destField;
 218  
     private MappingDirection type;
 219  
     private RelationshipType relationshipType;
 220  
     private boolean removeOrphans;
 221  
     private HintContainer srcHintContainer;
 222  
     private HintContainer destHintContainer;
 223  
     private HintContainer srcDeepIndexHintContainer;
 224  
     private HintContainer destDeepIndexHintContainer;
 225  
     private boolean copyByReference;
 226  
     private String mapId;
 227  
     private String customConverter;
 228  
     private String customConverterId;
 229  
     private String customConverterParam;
 230  
     private boolean copyByReferenceSet;
 231  
 
 232  13473
     public FieldMappingBuilder(ClassMap classMap) {
 233  13473
       this.classMap = classMap;
 234  13473
     }
 235  
 
 236  
     public FieldDefinitionBuilder a(String name) {
 237  23
       return a(name, null);
 238  
     }
 239  
 
 240  
     public FieldDefinitionBuilder a(String name, String type) {
 241  26921
       DozerField field = prepareField(name, type);
 242  26921
       this.srcField = field;
 243  26921
       return new FieldDefinitionBuilder(field);
 244  
     }
 245  
 
 246  
     public FieldDefinitionBuilder b(String name) {
 247  23
       return b(name, null);
 248  
     }
 249  
 
 250  
     public FieldDefinitionBuilder b(String name, String type) {
 251  26921
       DozerField field = prepareField(name, type);
 252  26919
       this.destField = field;
 253  26919
       return new FieldDefinitionBuilder(field);
 254  
     }
 255  
 
 256  
     public void type(MappingDirection type) {
 257  563
       this.type = type;
 258  563
     }
 259  
 
 260  
     public void relationshipType(RelationshipType relationshipType) {
 261  13455
       this.relationshipType = relationshipType;
 262  13455
     }
 263  
 
 264  
     public void removeOrphans(boolean value) {
 265  29
       this.removeOrphans = value;
 266  29
     }
 267  
 
 268  
     public void srcHintContainer(String hint) {
 269  1817
       HintContainer hintContainer = new HintContainer();
 270  1817
       hintContainer.setHintName(hint);
 271  1817
       this.srcHintContainer = hintContainer;
 272  1817
     }
 273  
 
 274  
     public void destHintContainer(String hint) {
 275  2586
       HintContainer hintContainer = new HintContainer();
 276  2586
       hintContainer.setHintName(hint);
 277  2586
       this.destHintContainer = hintContainer;
 278  2586
     }
 279  
 
 280  
     public void srcDeepIndexHintContainer(String hint) {
 281  35
       HintContainer hintContainer = new HintContainer();
 282  35
       hintContainer.setHintName(hint);
 283  35
       this.srcDeepIndexHintContainer = hintContainer;
 284  35
     }
 285  
 
 286  
     public void destDeepIndexHintContainer(String hint) {
 287  49
       HintContainer hintContainer = new HintContainer();
 288  49
       hintContainer.setHintName(hint);
 289  49
       this.destDeepIndexHintContainer = hintContainer;
 290  49
     }
 291  
 
 292  
     public void copyByReference(boolean value) {
 293  230
       this.copyByReferenceSet = true;
 294  230
       this.copyByReference = value;
 295  230
     }
 296  
 
 297  
     public void mapId(String attribute) {
 298  577
       this.mapId = attribute;
 299  577
     }
 300  
 
 301  
     public void customConverter(Class<? extends CustomConverter> type) {
 302  0
       customConverter(type.getName());
 303  0
     }
 304  
 
 305  
     public void customConverter(String typeName) {
 306  72
       this.customConverter = typeName;
 307  72
     }
 308  
 
 309  
     public void customConverterId(String attribute) {
 310  17
       this.customConverterId = attribute;
 311  17
     }
 312  
 
 313  
     public void customConverterParam(String attribute) {
 314  25
       this.customConverterParam = attribute;
 315  25
     }
 316  
 
 317  
     public void build() {
 318  
       // TODO Check Map to Map mapping
 319  
       FieldMap result;
 320  13471
       if (srcField.isMapTypeCustomGetterSetterField() || destField.isMapTypeCustomGetterSetterField()
 321  
           || classMap.isSrcClassMapTypeCustomGetterSetter() || classMap.isDestClassMapTypeCustomGetterSetter()) {
 322  720
         result = new MapFieldMap(classMap);
 323  12751
       } else if (srcField.isCustomGetterSetterField() || destField.isCustomGetterSetterField()) {
 324  1457
         result = new CustomGetSetMethodFieldMap(classMap);
 325  
       } else {
 326  11294
         result = new GenericFieldMap(classMap);
 327  
       }
 328  
 
 329  13471
       result.setSrcField(srcField);
 330  13471
       result.setDestField(destField);
 331  13471
       result.setType(type);
 332  13471
       result.setRelationshipType(relationshipType);
 333  13471
       result.setRemoveOrphans(removeOrphans);
 334  
 
 335  13471
       result.setSrcHintContainer(srcHintContainer);
 336  13471
       result.setDestHintContainer(destHintContainer);
 337  13471
       result.setSrcDeepIndexHintContainer(srcDeepIndexHintContainer);
 338  13471
       result.setDestDeepIndexHintContainer(destDeepIndexHintContainer);
 339  
 
 340  13471
       if (copyByReferenceSet) {
 341  230
         result.setCopyByReference(copyByReference);
 342  
       }
 343  13471
       result.setMapId(mapId);
 344  
 
 345  13471
       result.setCustomConverter(customConverter);
 346  13471
       result.setCustomConverterId(customConverterId);
 347  13471
       result.setCustomConverterParam(customConverterParam);
 348  
 
 349  13471
       classMap.addFieldMapping(result);
 350  13471
     }
 351  
 
 352  
   }
 353  
 
 354  
   public static class FieldDefinitionBuilder {
 355  
     private DozerField field;
 356  
 
 357  55498
     public FieldDefinitionBuilder(DozerField field) {
 358  55498
       this.field = field;
 359  55498
     }
 360  
 
 361  
     public void dateFormat(String attribute) {
 362  276
       field.setDateFormat(attribute);
 363  276
     }
 364  
 
 365  
     public void theGetMethod(String attribute) {
 366  710
       field.setTheGetMethod(attribute);
 367  710
     }
 368  
 
 369  
     public void theSetMethod(String attribute) {
 370  3618
       field.setTheSetMethod(attribute);
 371  3618
     }
 372  
 
 373  
     public void mapGetMethod(String attribute) {
 374  1002
       field.setMapGetMethod(attribute);
 375  1002
     }
 376  
 
 377  
     public void mapSetMethod(String attribute) {
 378  982
       field.setMapSetMethod(attribute);
 379  982
     }
 380  
 
 381  
     public void key(String attribute) {
 382  1830
       field.setKey(attribute);
 383  1830
     }
 384  
 
 385  
     public void createMethod(String attribute) {
 386  86
       field.setCreateMethod(attribute);
 387  86
     }
 388  
 
 389  
     public void accessible(Boolean b) {
 390  274
       field.setAccessible(b);
 391  274
     }
 392  
 
 393  
     public void iterate() {
 394  1
       field.setType(DozerConstants.ITERATE);
 395  1
     }
 396  
 
 397  
     public DozerField build() {
 398  0
       return field;
 399  
     }
 400  
 
 401  
   }
 402  
 
 403  
   private static DozerField prepareField(String name, String type) {
 404  55500
     if (MappingUtils.isBlankOrNull(name)) {
 405  2
       throw new MappingException("Field name can not be empty");
 406  
     }
 407  
     String fieldName;
 408  55498
     String fieldType = null;
 409  55498
     if (isIndexed(name)) {
 410  432
       fieldName = getFieldNameOfIndexedField(name);
 411  
     } else {
 412  55066
       fieldName = name;
 413  
     }
 414  55498
     if (StringUtils.isNotEmpty(type)) {
 415  1348
       fieldType = type;
 416  
     }
 417  55498
     DozerField field = new DozerField(fieldName, fieldType);
 418  55498
     if (isIndexed(name)) {
 419  432
       field.setIndexed(true);
 420  432
       field.setIndex(getIndexOfIndexedField(name));
 421  
     }
 422  55498
     return field;
 423  
   }
 424  
 
 425  
 
 426  
   private static boolean isIndexed(String fieldName) {
 427  110996
     return (fieldName != null) && (fieldName.matches(".+\\[\\d+\\]"));
 428  
   }
 429  
 
 430  
   static String getFieldNameOfIndexedField(String fieldName) {
 431  435
     return fieldName == null ? null : fieldName.replaceAll("\\[\\d+\\]$", "");
 432  
   }
 433  
 
 434  
   private static int getIndexOfIndexedField(String fieldName) {
 435  432
     return Integer.parseInt(fieldName.replaceAll(".*\\[", "").replaceAll("\\]", ""));
 436  
   }
 437  
 
 438  
   public static class ClassDefinitionBuilder {
 439  
 
 440  
     private DozerClass definition;
 441  
 
 442  10964
     public ClassDefinitionBuilder(DozerClass definition) {
 443  10964
       this.definition = definition;
 444  10964
     }
 445  
 
 446  
     public void mapGetMethod(String name) {
 447  282
       definition.setMapGetMethod(name);
 448  282
     }
 449  
 
 450  
     public void mapSetMethod(String name) {
 451  282
       definition.setMapSetMethod(name);
 452  282
     }
 453  
 
 454  
     public void beanFactory(String beanFactory) {
 455  124
       definition.setBeanFactory(beanFactory);
 456  124
     }
 457  
 
 458  
     public void factoryBeanId(String id) {
 459  59
       definition.setFactoryBeanId(id);
 460  59
     }
 461  
 
 462  
     public void createMethod(String name) {
 463  68
       definition.setCreateMethod(name);
 464  68
     }
 465  
 
 466  
     public void mapNull(Boolean value) {
 467  70
       definition.setMapNull(value);
 468  70
     }
 469  
 
 470  
     public void mapEmptyString(Boolean value) {
 471  70
       definition.setMapEmptyString(value);
 472  70
     }
 473  
 
 474  
     public void isAccessible(Boolean value) {
 475  82
       definition.setAccessible(value);
 476  82
     }
 477  
   }
 478  
 
 479  
   public static class ConfigurationBuilder {
 480  
 
 481  
     private Configuration configuration;
 482  
 
 483  
     private CustomConverterDescription converterDescription;
 484  
 
 485  233
     public ConfigurationBuilder(Configuration configuration) {
 486  233
       this.configuration = configuration;
 487  233
     }
 488  
 
 489  
     public void stopOnErrors(Boolean value) {
 490  144
       configuration.setStopOnErrors(value);
 491  144
     }
 492  
 
 493  
     public void dateFormat(String format) {
 494  135
       configuration.setDateFormat(format);
 495  135
     }
 496  
 
 497  
     public void wildcard(Boolean value) {
 498  138
       configuration.setWildcard(value);
 499  138
     }
 500  
 
 501  
     public void trimStrings(Boolean value) {
 502  6
       configuration.setTrimStrings(value);
 503  6
     }
 504  
 
 505  
     public void mapNull(Boolean value) {
 506  1
       configuration.setMapNull(value);
 507  1
     }
 508  
 
 509  
     public void mapEmptyString(Boolean value) {
 510  1
       configuration.setMapEmptyString(value);
 511  1
     }
 512  
 
 513  
     public void relationshipType(RelationshipType value) {
 514  2
       if (value == null) {
 515  0
         configuration.setRelationshipType(DozerConstants.DEFAULT_RELATIONSHIP_TYPE_POLICY);
 516  
       } else {
 517  2
         configuration.setRelationshipType(value);
 518  
       }
 519  2
     }
 520  
 
 521  
     public void beanFactory(String name) {
 522  5
       configuration.setBeanFactory(name);
 523  5
     }
 524  
 
 525  
     public CustomConverterBuilder customConverter(String type) {
 526  395
       Class<?> aClass = MappingUtils.loadClass(type);
 527  395
       return customConverter(aClass);
 528  
     }
 529  
 
 530  
     // TODO Constraint with Generic
 531  
     public CustomConverterBuilder customConverter(Class type) {
 532  395
       converterDescription = new CustomConverterDescription();
 533  395
       converterDescription.setType(type);
 534  395
       configuration.getCustomConverters().addConverter(converterDescription);
 535  395
       return new CustomConverterBuilder(converterDescription);
 536  
     }
 537  
 
 538  
     public ConfigurationBuilder copyByReference(String typeMask) {
 539  130
       CopyByReference copyByReference = new CopyByReference(typeMask);
 540  130
       configuration.getCopyByReferences().add(copyByReference);
 541  130
       return this;
 542  
     }
 543  
 
 544  
     public ConfigurationBuilder allowedException(String type) {
 545  4
       Class<?> exceptionType = MappingUtils.loadClass(type);
 546  4
       return allowedException(exceptionType);
 547  
     }
 548  
 
 549  
     // TODO Restrict with generic
 550  
     public ConfigurationBuilder allowedException(Class type) {
 551  4
       if (!RuntimeException.class.isAssignableFrom(type)) {
 552  0
         MappingUtils.throwMappingException("allowed-exception Type must extend java.lang.RuntimeException: "
 553  
             + type.getName());
 554  
       }
 555  4
       configuration.getAllowedExceptions().getExceptions().add(type);
 556  4
       return this;
 557  
     }
 558  
 
 559  
   }
 560  
 
 561  630
   public static class CustomConverterBuilder {
 562  
     private CustomConverterDescription converterDescription;
 563  
 
 564  395
     public CustomConverterBuilder(CustomConverterDescription converterDescription) {
 565  395
       this.converterDescription = converterDescription;
 566  395
     }
 567  
 
 568  
     public CustomConverterBuilder classA(String type) {
 569  395
       Class<?> aClass = MappingUtils.loadClass(type);
 570  395
       return classA(aClass);
 571  
     }
 572  
 
 573  
     public CustomConverterBuilder classA(Class type) {
 574  395
       converterDescription.setClassA(type);
 575  395
       return this;
 576  
     }
 577  
 
 578  
     public CustomConverterBuilder classB(String type) {
 579  395
       Class<?> aClass = MappingUtils.loadClass(type);
 580  395
       return classB(aClass);
 581  
     }
 582  
 
 583  
     public CustomConverterBuilder classB(Class type) {
 584  395
       converterDescription.setClassB(type);
 585  395
       return this;
 586  
     }
 587  
 
 588  
   }
 589  
 
 590  
 }