diff --git a/processor/src/main/java/org/mapstruct/ap/builtin/BuiltInMappingMethods.java b/processor/src/main/java/org/mapstruct/ap/builtin/BuiltInMappingMethods.java index c210346ff..cec7c8335 100644 --- a/processor/src/main/java/org/mapstruct/ap/builtin/BuiltInMappingMethods.java +++ b/processor/src/main/java/org/mapstruct/ap/builtin/BuiltInMappingMethods.java @@ -18,27 +18,35 @@ */ package org.mapstruct.ap.builtin; -import org.mapstruct.ap.model.source.BuiltInMethod; -import java.util.HashSet; -import org.mapstruct.ap.model.common.TypeFactory; +import java.util.Arrays; +import java.util.List; +import org.mapstruct.ap.model.common.TypeFactory; +import org.mapstruct.ap.model.source.BuiltInMethod; /** - * Registry for all build in methods. + * Registry for all built-in methods. * * @author Sjaak Derksen */ -public class BuiltInMappingMethods extends HashSet { +public class BuiltInMappingMethods { - public BuiltInMappingMethods( TypeFactory typeFactory ) { + private final List builtInMethods; - add( new JaxbElemToValue( typeFactory ) ); - add( new ListOfJaxbElemToListOfValue( typeFactory ) ); - add( new DateToXmlGregorianCalendar( typeFactory ) ); - add( new XmlGregorianCalendarToDate( typeFactory ) ); - add( new StringToXmlGregorianCalendar( typeFactory ) ); - add( new XmlGregorianCalendarToString( typeFactory ) ); - add( new CalendarToXmlGregorianCalendar( typeFactory ) ); - add( new XmlGregorianCalendarToCalendar( typeFactory ) ); + public BuiltInMappingMethods(TypeFactory typeFactory) { + builtInMethods = Arrays.asList( + new JaxbElemToValue( typeFactory ), + new ListOfJaxbElemToListOfValue( typeFactory ), + new DateToXmlGregorianCalendar( typeFactory ), + new XmlGregorianCalendarToDate( typeFactory ), + new StringToXmlGregorianCalendar( typeFactory ), + new XmlGregorianCalendarToString( typeFactory ), + new CalendarToXmlGregorianCalendar( typeFactory ), + new XmlGregorianCalendarToCalendar( typeFactory ) + ); + } + + public List getBuiltInMethods() { + return builtInMethods; } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java index 12079dc72..78890290a 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java @@ -18,11 +18,9 @@ */ package org.mapstruct.ap.model; -import org.mapstruct.ap.model.source.BuiltInMethod; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -54,14 +52,13 @@ public class Mapper extends ModelElement { private final List annotations; private final List mappingMethods; private final List referencedMappers; - private final Set builtInMethods; private final boolean suppressGeneratorTimestamp; private final Accessibility accessibility; private Mapper(TypeFactory typeFactory, String packageName, boolean superTypeIsInterface, String interfaceName, String implementationName, List mappingMethods, List referencedMappers, boolean suppressGeneratorTimestamp, - Set builtInMethods, Accessibility accessibility) { + Accessibility accessibility) { this.packageName = packageName; this.superTypeIsInterface = superTypeIsInterface; this.interfaceName = interfaceName; @@ -69,7 +66,6 @@ public class Mapper extends ModelElement { this.annotations = new ArrayList(); this.mappingMethods = mappingMethods; this.referencedMappers = referencedMappers; - this.builtInMethods = builtInMethods; this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; this.typeFactory = typeFactory; this.accessibility = accessibility; @@ -81,7 +77,6 @@ public class Mapper extends ModelElement { private TypeElement element; private List mappingMethods; private List mapperReferences; - private Set builtInMethods; private Elements elementUtils; private boolean suppressGeneratorTimestamp; @@ -101,11 +96,6 @@ public class Mapper extends ModelElement { return this; } - public Builder builtInMethods(Set builtInMethods) { - this.builtInMethods = builtInMethods; - return this; - } - public Builder suppressGeneratorTimestamp(boolean suppressGeneratorTimestamp) { this.suppressGeneratorTimestamp = suppressGeneratorTimestamp; return this; @@ -131,7 +121,6 @@ public class Mapper extends ModelElement { mappingMethods, mapperReferences, suppressGeneratorTimestamp, - builtInMethods, Accessibility.fromModifiers( element.getModifiers() ) ); } @@ -158,12 +147,6 @@ public class Mapper extends ModelElement { addWithDependents( importedTypes, annotation.getType() ); } - for ( BuiltInMethod builtInMethod : builtInMethods ) { - for ( Type type : builtInMethod.getImportTypes() ) { - addWithDependents( importedTypes, type ); - } - } - return importedTypes; } @@ -250,8 +233,4 @@ public class Mapper extends ModelElement { public Accessibility getAccessibility() { return accessibility; } - - public Set getBuiltInMethods() { - return builtInMethods; - } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/VirtualMappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/VirtualMappingMethod.java new file mode 100644 index 000000000..c2452fdee --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/model/VirtualMappingMethod.java @@ -0,0 +1,83 @@ +/** + * Copyright 2012-2014 Gunnar Morling (http://www.gunnarmorling.de/) + * and/or other contributors as indicated by the @authors tag. See the + * copyright.txt file in the distribution for a full listing of all + * contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mapstruct.ap.model; + +import java.util.Set; + +import org.mapstruct.ap.model.common.Type; +import org.mapstruct.ap.model.source.BuiltInMethod; + +/** + * A mapping method which is not based on an actual method declared in the original mapper interface but is added as + * private method to map a certain source/target type combination. Based on a {@link BuiltInMethod}. + * + * @author Gunnar Morling + */ +public class VirtualMappingMethod extends MappingMethod { + + private final String templateName; + private final Set importTypes; + + public VirtualMappingMethod(BuiltInMethod method) { + super( method ); + this.importTypes = method.getImportTypes(); + this.templateName = method.getClass().getName() + ".ftl"; + } + + @Override + public String getTemplateName() { + return templateName; + } + + @Override + public Set getImportTypes() { + return importTypes; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ( ( templateName == null ) ? 0 : templateName.hashCode() ); + return result; + } + + @Override + public boolean equals(Object obj) { + if ( this == obj ) { + return true; + } + if ( obj == null ) { + return false; + } + if ( getClass() != obj.getClass() ) { + return false; + } + VirtualMappingMethod other = (VirtualMappingMethod) obj; + if ( templateName == null ) { + if ( other.templateName != null ) { + return false; + } + } + else if ( !templateName.equals( other.templateName ) ) { + return false; + } + return true; + } +} diff --git a/processor/src/main/java/org/mapstruct/ap/model/common/ModelElement.java b/processor/src/main/java/org/mapstruct/ap/model/common/ModelElement.java index 2714ac50e..977034be7 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/common/ModelElement.java +++ b/processor/src/main/java/org/mapstruct/ap/model/common/ModelElement.java @@ -22,18 +22,16 @@ import java.io.Writer; import java.util.Set; import org.mapstruct.ap.writer.FreeMarkerModelElementWriter; +import org.mapstruct.ap.writer.FreeMarkerWritable; import org.mapstruct.ap.writer.Writable; /** - * Base class of all model elements. - *

- * Implements the {@link Writable} contract to write model elements into source code files using FreeMarker templates. - * By default, the fully-qualified class name of the given model element type, appended with the extension {@code *.ftl} - * is used as template file name. + * Base class of all model elements. Implements the {@link Writable} contract to write model elements into source code + * files. * * @author Gunnar Morling */ -public abstract class ModelElement implements Writable { +public abstract class ModelElement extends FreeMarkerWritable { @Override public void write(Context context, Writer writer) throws Exception { diff --git a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java index b7fe29276..6e5060eb1 100644 --- a/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java +++ b/processor/src/main/java/org/mapstruct/ap/processor/MapperCreationProcessor.java @@ -36,13 +36,10 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; import javax.tools.Diagnostic.Kind; -import org.mapstruct.ap.model.common.ConversionContext; +import org.mapstruct.ap.builtin.BuiltInMappingMethods; import org.mapstruct.ap.conversion.ConversionProvider; import org.mapstruct.ap.conversion.Conversions; -import org.mapstruct.ap.model.common.DefaultConversionContext; -import org.mapstruct.ap.model.source.BuiltInMethod; -import org.mapstruct.ap.builtin.BuiltInMappingMethods; import org.mapstruct.ap.model.BeanMappingMethod; import org.mapstruct.ap.model.DefaultMapperReference; import org.mapstruct.ap.model.IterableMappingMethod; @@ -53,11 +50,15 @@ import org.mapstruct.ap.model.MappingMethod; import org.mapstruct.ap.model.MethodReference; import org.mapstruct.ap.model.PropertyMapping; import org.mapstruct.ap.model.TypeConversion; +import org.mapstruct.ap.model.VirtualMappingMethod; +import org.mapstruct.ap.model.common.ConversionContext; +import org.mapstruct.ap.model.common.DefaultConversionContext; import org.mapstruct.ap.model.common.Parameter; import org.mapstruct.ap.model.common.Type; import org.mapstruct.ap.model.common.TypeFactory; -import org.mapstruct.ap.model.source.Method; +import org.mapstruct.ap.model.source.BuiltInMethod; import org.mapstruct.ap.model.source.Mapping; +import org.mapstruct.ap.model.source.Method; import org.mapstruct.ap.model.source.SourceMethod; import org.mapstruct.ap.option.Options; import org.mapstruct.ap.option.ReportingPolicy; @@ -82,7 +83,12 @@ public class MapperCreationProcessor implements ModelElementProcessor usedBuiltInMethods; + + /** + * Private methods which are not present in the original mapper interface and are added to map certain property + * types. + */ + private Set virtualMethods; @Override public Mapper process(ProcessorContext context, TypeElement mapperTypeElement, List sourceModel) { @@ -95,7 +101,7 @@ public class MapperCreationProcessor implements ModelElementProcessor(); + this.virtualMethods = new HashSet(); return getMapper( mapperTypeElement, sourceModel ); } @@ -109,6 +115,7 @@ public class MapperCreationProcessor implements ModelElementProcessor mapperReferences = getReferencedMappers( element ); List mappingMethods = getMappingMethods( mapperReferences, methods, unmappedTargetPolicy ); + mappingMethods.addAll( virtualMethods ); Mapper mapper = new Mapper.Builder() .element( element ) @@ -117,10 +124,8 @@ public class MapperCreationProcessor implements ModelElementProcessor( usedBuiltInMethods ) ) .build(); - usedBuiltInMethods.clear(); return mapper; } @@ -582,7 +587,7 @@ public class MapperCreationProcessor implements ModelElementProcessor <@includeModel object=mappingMethod/> - -<#list builtInMethods as builtInMethod> - -<#nt> <@includeModel object=builtInMethod/> - }