private String generateFieldMapCode( SourceCodeContext code, FieldMap fieldMap, ClassMap<?, ?> classMap, VariableRef destination, StringBuilder logDetails) throws Exception { final VariableRef sourceProperty = new VariableRef(fieldMap.getSource(), "source"); final VariableRef destinationProperty = new VariableRef(fieldMap.getDestination(), "destination"); destinationProperty.setOwner(destination); if (!sourceProperty.isReadable() || ((!destinationProperty.isAssignable()) && destinationProperty.type().isImmutable())) { if (logDetails != null) { code.debugField(fieldMap, "excluding because "); if (!sourceProperty.isReadable()) { Type<?> sourceType = classMap.getAType().equals(destination.type()) ? classMap.getBType() : classMap.getAType(); logDetails.append( sourceType + "." + fieldMap.getSource().getName() + "(" + fieldMap.getSource().getType() + ") is not readable"); } else { logDetails.append( destination.type() + "." + fieldMap.getDestination().getName() + "(" + fieldMap.getDestination().getType() + ") is not assignable and cannot be mapped in-place"); } } return ""; } // Make sure the source and destination types are accessible to the // builder compilerStrategy.assureTypeIsAccessible(sourceProperty.rawType()); compilerStrategy.assureTypeIsAccessible(destinationProperty.rawType()); return code.mapFields(fieldMap, sourceProperty, destinationProperty); }
private Set<FieldMap> addMapMethod( SourceCodeContext code, boolean aToB, ClassMap<?, ?> classMap, StringBuilder logDetails) { Set<FieldMap> mappedFields = new LinkedHashSet<FieldMap>(); if (logDetails != null) { if (aToB) { logDetails.append( "\n\t" + code.getClassSimpleName() + ".mapAToB(" + classMap.getAType() + ", " + classMap.getBTypeName() + ") {"); } else { logDetails.append( "\n\t" + code.getClassSimpleName() + ".mapBToA(" + classMap.getBType() + ", " + classMap.getATypeName() + ") {"); } } final StringBuilder out = new StringBuilder(); final String mapMethod = "map" + (aToB ? "AtoB" : "BtoA"); out.append("\tpublic void "); out.append(mapMethod); out.append( format( "(java.lang.Object a, java.lang.Object b, %s mappingContext) {\n\n", MappingContext.class.getCanonicalName())); VariableRef source; VariableRef destination; if (aToB) { source = new VariableRef(classMap.getAType(), "source"); destination = new VariableRef(classMap.getBType(), "destination"); } else { source = new VariableRef(classMap.getBType(), "source"); destination = new VariableRef(classMap.getAType(), "destination"); } append( out, format("super.%s(a, b, mappingContext);", mapMethod), "\n\n", "// sourceType: " + source.type() + source.declare("a"), "// destinationType: " + destination.type() + destination.declare("b"), "\n\n"); for (FieldMap currentFieldMap : classMap.getFieldsMapping()) { if (currentFieldMap.isExcluded()) { if (logDetails != null) { code.debugField(currentFieldMap, "excuding (explicitly)"); } continue; } if (isAlreadyExistsInUsedMappers(currentFieldMap, classMap)) { if (logDetails != null) { code.debugField( currentFieldMap, "excluding because it is already handled by another mapper in this hierarchy"); } continue; } FieldMap fieldMap = currentFieldMap; if (!aToB) { fieldMap = fieldMap.flip(); } if (!fieldMap.isIgnored()) { if (code.aggregateSpecsApply(fieldMap)) { continue; } try { mappedFields.add(currentFieldMap); String sourceCode = generateFieldMapCode(code, fieldMap, classMap, destination, logDetails); out.append(sourceCode); } catch (final Exception e) { MappingException me = new MappingException(e); me.setSourceProperty(fieldMap.getSource()); me.setDestinationProperty(fieldMap.getDestination()); me.setSourceType(source.type()); me.setDestinationType(destination.type()); throw me; } } else if (logDetails != null) { code.debugField(fieldMap, "ignored for this mapping direction"); } } out.append(code.mapAggregateFields()); out.append("\n\t\tif(customMapper != null) { \n\t\t\t customMapper.") .append(mapMethod) .append("(source, destination, mappingContext);\n\t\t}"); out.append("\n\t}"); if (logDetails != null) { logDetails.append("\n\t}"); } code.addMethod(out.toString()); return mappedFields; }