org.mapstruct.ap.internal.model.GeneratedType Maven / Gradle / Ivy
/*
* Copyright MapStruct Authors.
*
* Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0
*/
package org.mapstruct.ap.internal.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.Elements;
import org.mapstruct.ap.internal.model.common.Accessibility;
import org.mapstruct.ap.internal.model.common.ModelElement;
import org.mapstruct.ap.internal.model.common.Type;
import org.mapstruct.ap.internal.model.common.TypeFactory;
import org.mapstruct.ap.internal.option.Options;
import org.mapstruct.ap.internal.util.Strings;
import org.mapstruct.ap.internal.version.VersionInformation;
/**
* A type generated by MapStruct, e.g. representing a mapper type.
*
* @author Gunnar Morling
*/
public abstract class GeneratedType extends ModelElement {
private static final String JAVA_LANG_PACKAGE = "java.lang";
protected abstract static class GeneratedTypeBuilder {
private T myself;
protected TypeFactory typeFactory;
protected Elements elementUtils;
protected Options options;
protected VersionInformation versionInformation;
protected SortedSet extraImportedTypes;
protected List methods;
GeneratedTypeBuilder(Class selfType) {
myself = selfType.cast( this );
}
public T elementUtils(Elements elementUtils) {
this.elementUtils = elementUtils;
return myself;
}
public T typeFactory(TypeFactory typeFactory) {
this.typeFactory = typeFactory;
return myself;
}
public T options(Options options) {
this.options = options;
return myself;
}
public T versionInformation(VersionInformation versionInformation) {
this.versionInformation = versionInformation;
return myself;
}
public T extraImports(SortedSet extraImportedTypes) {
this.extraImportedTypes = extraImportedTypes;
return myself;
}
public T methods(List methods) {
this.methods = methods;
return myself;
}
}
private final String packageName;
private final String name;
private final String superClassName;
private final String interfacePackage;
private final String interfaceName;
private final List annotations;
private final List methods;
private final SortedSet extraImportedTypes;
private final boolean suppressGeneratorTimestamp;
private final boolean suppressGeneratorVersionComment;
private final VersionInformation versionInformation;
private final Accessibility accessibility;
private List fields;
private Constructor constructor;
/**
* Type representing the {@code @Generated} annotation
*/
private final Type generatedType;
private final boolean generatedTypeAvailable;
// CHECKSTYLE:OFF
protected GeneratedType(TypeFactory typeFactory, String packageName, String name, String superClassName,
String interfacePackage, String interfaceName, List methods,
List fields, Options options, VersionInformation versionInformation,
Accessibility accessibility, SortedSet extraImportedTypes, Constructor constructor) {
this.packageName = packageName;
this.name = name;
this.superClassName = superClassName;
this.interfacePackage = interfacePackage;
this.interfaceName = interfaceName;
this.extraImportedTypes = extraImportedTypes;
this.annotations = new ArrayList<>();
this.methods = methods;
this.fields = fields;
this.suppressGeneratorTimestamp = options.isSuppressGeneratorTimestamp();
this.suppressGeneratorVersionComment = options.isSuppressGeneratorVersionComment();
this.versionInformation = versionInformation;
this.accessibility = accessibility;
if ( versionInformation.isSourceVersionAtLeast9() &&
typeFactory.isTypeAvailable( "javax.annotation.processing.Generated" ) ) {
this.generatedType = typeFactory.getType( "javax.annotation.processing.Generated" );
this.generatedTypeAvailable = true;
}
else if ( typeFactory.isTypeAvailable( "javax.annotation.Generated" ) ) {
this.generatedType = typeFactory.getType( "javax.annotation.Generated" );
this.generatedTypeAvailable = true;
}
else {
this.generatedType = null;
this.generatedTypeAvailable = false;
}
this.constructor = constructor;
}
// CHECKSTYLE:ON
public String getPackageName() {
return packageName;
}
public boolean hasPackageName() {
return !Strings.isEmpty( packageName );
}
public String getName() {
return name;
}
public String getSuperClassName() {
return superClassName;
}
public String getInterfacePackage() {
return interfacePackage;
}
public String getInterfaceName() {
return interfaceName;
}
public List getAnnotations() {
return annotations;
}
public void addAnnotation(Annotation annotation) {
annotations.add( annotation );
}
public List getMethods() {
return methods;
}
public List getFields() {
return fields;
}
public void setFields(List fields) {
this.fields = fields;
}
public boolean isSuppressGeneratorTimestamp() {
return suppressGeneratorTimestamp;
}
public boolean isSuppressGeneratorVersionComment() {
return suppressGeneratorVersionComment;
}
public boolean isGeneratedTypeAvailable() {
return generatedTypeAvailable;
}
public VersionInformation getVersionInformation() {
return versionInformation;
}
public Accessibility getAccessibility() {
return accessibility;
}
public void setConstructor(Constructor constructor) {
this.constructor = constructor;
}
@Override
public SortedSet getImportTypes() {
SortedSet importedTypes = new TreeSet<>();
addIfImportRequired( importedTypes, generatedType );
for ( MappingMethod mappingMethod : methods ) {
for ( Type type : mappingMethod.getImportTypes() ) {
addIfImportRequired( importedTypes, type );
}
}
for ( Field field : fields ) {
if ( field.isTypeRequiresImport() ) {
for ( Type type : field.getImportTypes() ) {
addIfImportRequired( importedTypes, type );
}
}
}
for ( Annotation annotation : annotations ) {
addIfImportRequired( importedTypes, annotation.getType() );
}
for ( Type extraImport : extraImportedTypes ) {
addIfImportRequired( importedTypes, extraImport );
}
if ( constructor != null ) {
for ( Type type : constructor.getImportTypes() ) {
addIfImportRequired( importedTypes, type );
}
}
return importedTypes;
}
public SortedSet getImportTypeNames() {
SortedSet importTypeNames = new TreeSet<>();
for ( Type type : getImportTypes() ) {
importTypeNames.add( type.getImportName() );
}
return importTypeNames;
}
public Constructor getConstructor() {
return constructor;
}
public void removeConstructor() {
constructor = null;
}
protected void addIfImportRequired(Collection collection, Type typeToAdd) {
if ( typeToAdd == null ) {
return;
}
if ( needsImportDeclaration( typeToAdd ) ) {
collection.add( typeToAdd );
}
}
private boolean needsImportDeclaration(Type typeToAdd) {
if ( !typeToAdd.isToBeImported() ) {
return false;
}
if ( typeToAdd.getTypeMirror().getKind() != TypeKind.DECLARED && !typeToAdd.isArrayType() ) {
return false;
}
if ( typeToAdd.getPackageName() != null ) {
if ( typeToAdd.getPackageName().equals( JAVA_LANG_PACKAGE ) ) {
// only the types in the java.lang package are implicitly imported, the packages under java.lang
// like java.lang.management are not.
return false;
}
if ( typeToAdd.getPackageName().equals( packageName ) ) {
if ( typeToAdd.getTypeElement() != null ) {
if ( !typeToAdd.getTypeElement().getNestingKind().isNested() ) {
return false;
}
}
else if ( typeToAdd.getComponentType() != null ) {
if ( !typeToAdd.getComponentType().getTypeElement().getNestingKind().isNested() ) {
return false;
}
}
}
}
return true;
}
}