mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#710 Deferring processing of mappers with incomplete source/target types to a later processing round
This commit is contained in:
parent
03bf027858
commit
55b74ae384
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.tests;
|
||||||
|
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mapstruct.itest.testutil.runner.ProcessorSuite;
|
||||||
|
import org.mapstruct.itest.testutil.runner.ProcessorSuite.ProcessorType;
|
||||||
|
import org.mapstruct.itest.testutil.runner.ProcessorSuiteRunner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests usage of MapStruct with another processor that generates supertypes of mapping source/target types.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
@RunWith( ProcessorSuiteRunner.class )
|
||||||
|
@ProcessorSuite(baseDir = "superTypeGenerationTest", processorTypes = ProcessorType.ORACLE_JAVA_8)
|
||||||
|
public class SuperTypeGenerationTest {
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>itest-supertypegeneration-generator</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
<compilerArgs>
|
||||||
|
<compilerArg>-proc:none</compilerArg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.processing.AbstractProcessor;
|
||||||
|
import javax.annotation.processing.RoundEnvironment;
|
||||||
|
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||||
|
import javax.lang.model.element.AnnotationMirror;
|
||||||
|
import javax.lang.model.element.Element;
|
||||||
|
import javax.lang.model.element.Name;
|
||||||
|
import javax.lang.model.element.PackageElement;
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates base classes.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@SupportedAnnotationTypes("org.mapstruct.itest.supertypegeneration.GenBase")
|
||||||
|
public class BaseGenerationProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
|
for (TypeElement annotation : annotations) {
|
||||||
|
Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith( annotation );
|
||||||
|
for (Element element : annotated) {
|
||||||
|
AnnotationMirror annotationMirror = element.getAnnotationMirrors().get(0);
|
||||||
|
Integer level = (Integer) annotationMirror.getElementValues().values().iterator().next().getValue();
|
||||||
|
|
||||||
|
if ( level >= 1 ) {
|
||||||
|
try {
|
||||||
|
PackageElement packageElement = processingEnv.getElementUtils().getPackageOf( element );
|
||||||
|
Name name = element.getSimpleName();
|
||||||
|
String baseName = name.toString() + "Base";
|
||||||
|
String baseBaseName = level > 1 ? baseName + "Base" : null;
|
||||||
|
|
||||||
|
JavaFileObject baseGen = processingEnv.getFiler().createSourceFile( packageElement.getQualifiedName() + "." + baseName );
|
||||||
|
Writer writer = baseGen.openWriter();
|
||||||
|
writer.append( "package " + packageElement.getQualifiedName() + ";\n" );
|
||||||
|
writer.append( "\n" );
|
||||||
|
writer.append( "import org.mapstruct.itest.supertypegeneration.GenBase;\n" );
|
||||||
|
writer.append( "\n" );
|
||||||
|
if ( level > 1 ) {
|
||||||
|
writer.append( "@GenBase( " + (level - 1) + " )\n" );
|
||||||
|
writer.append( "public class " + baseName + " extends " + baseBaseName + " {\n" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writer.append( "public class " + baseName + " {\n" );
|
||||||
|
}
|
||||||
|
writer.append( " private String baseName" + level + ";\n" );
|
||||||
|
writer.append( " public String getBaseName" + level + "() { return baseName" + level + "; }\n" );
|
||||||
|
writer.append( " public void setBaseName" + level + "(String baseName" + level + ") { this.baseName" + level + " = baseName" + level + ";}\n" );
|
||||||
|
writer.append( "}\n" );
|
||||||
|
writer.flush();
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers generation of base-classes.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public @interface GenBase {
|
||||||
|
|
||||||
|
int value();
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
# Copyright 2012-2015 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.
|
||||||
|
org.mapstruct.itest.supertypegeneration.BaseGenerationProcessor
|
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright 2012-2015 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-it-parent</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>generator</module>
|
||||||
|
<module>usage</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
@ -0,0 +1,47 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-supertypegeneration-aggregator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>itest-supertypegeneration-usage</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct.itest</groupId>
|
||||||
|
<artifactId>itest-supertypegeneration-generator</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
<compilerArgs>
|
||||||
|
<compilerArg>-XprintProcessorInfo</compilerArg>
|
||||||
|
<compilerArg>-XprintRounds</compilerArg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration.usage;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public abstract class AnotherOrderMapper {
|
||||||
|
|
||||||
|
public static final AnotherOrderMapper INSTANCE = Mappers.getMapper( AnotherOrderMapper.class );
|
||||||
|
|
||||||
|
public abstract OrderDto orderToDto(Order order);
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration.usage;
|
||||||
|
|
||||||
|
import org.mapstruct.itest.supertypegeneration.GenBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
@GenBase(2)
|
||||||
|
public class Order extends OrderBase {
|
||||||
|
|
||||||
|
private String item;
|
||||||
|
|
||||||
|
public String getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(String item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration.usage;
|
||||||
|
|
||||||
|
import org.mapstruct.itest.supertypegeneration.GenBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
@GenBase(2)
|
||||||
|
public class OrderDto extends OrderDtoBase {
|
||||||
|
|
||||||
|
private String item;
|
||||||
|
|
||||||
|
public String getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(String item) {
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration.usage;
|
||||||
|
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public abstract class OrderMapper {
|
||||||
|
|
||||||
|
public static final OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
|
||||||
|
|
||||||
|
public abstract OrderDto orderToDto(Order order);
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.itest.supertypegeneration.usage;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mapstruct.itest.supertypegeneration.usage.Order;
|
||||||
|
import org.mapstruct.itest.supertypegeneration.usage.OrderDto;
|
||||||
|
import org.mapstruct.itest.supertypegeneration.usage.OrderMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test for using MapStruct with another annotation processor that generates super-types of mapping source
|
||||||
|
* and target types.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
public class GeneratedBasesTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void considersPropertiesOnGeneratedSourceAndTargetTypes() {
|
||||||
|
Order order = new Order();
|
||||||
|
order.setItem( "my item" );
|
||||||
|
order.setBaseName2( "my base name 2" );
|
||||||
|
order.setBaseName1( "my base name 1" );
|
||||||
|
|
||||||
|
OrderDto dto = OrderMapper.INSTANCE.orderToDto( order );
|
||||||
|
assertEquals( order.getItem(), dto.getItem() );
|
||||||
|
assertEquals( order.getBaseName2(), dto.getBaseName2() );
|
||||||
|
assertEquals( order.getBaseName1(), dto.getBaseName1() );
|
||||||
|
|
||||||
|
// Let's make sure several mappers can be generated
|
||||||
|
dto = AnotherOrderMapper.INSTANCE.orderToDto( order );
|
||||||
|
assertEquals( order.getItem(), dto.getItem() );
|
||||||
|
assertEquals( order.getBaseName2(), dto.getBaseName2() );
|
||||||
|
assertEquals( order.getBaseName1(), dto.getBaseName1() );
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.io.StringWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
@ -49,6 +50,7 @@ import org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext;
|
|||||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor;
|
import org.mapstruct.ap.internal.processor.ModelElementProcessor;
|
||||||
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext;
|
import org.mapstruct.ap.internal.processor.ModelElementProcessor.ProcessorContext;
|
||||||
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
import org.mapstruct.ap.internal.util.AnnotationProcessingException;
|
||||||
|
import org.mapstruct.ap.internal.util.TypeHierarchyErroneousException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSR 269 annotation {@link Processor} which generates the implementations for mapper interfaces (interfaces
|
* A JSR 269 annotation {@link Processor} which generates the implementations for mapper interfaces (interfaces
|
||||||
@ -105,6 +107,17 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
private Options options;
|
private Options options;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any mappers for which an implementation cannot be generated in the current round because they have source/target
|
||||||
|
* types with incomplete hierarchies (as super-types are to be generated by other processors). They will be
|
||||||
|
* processed in subsequent rounds.
|
||||||
|
* <p>
|
||||||
|
* If the hierarchy of a mapper's source/target types is never completed (i.e. the missing super-types are not
|
||||||
|
* generated by other processors), this mapper will not be generated; That's fine, the compiler will raise an error
|
||||||
|
* due to the inconsistent Java types used as source or target anyways.
|
||||||
|
*/
|
||||||
|
private Set<TypeElement> deferredMappers = new HashSet<TypeElement>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||||
super.init( processingEnv );
|
super.init( processingEnv );
|
||||||
@ -132,50 +145,85 @@ public class MappingProcessor extends AbstractProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
|
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
|
||||||
|
// nothing to do in the last round
|
||||||
|
if ( !roundEnvironment.processingOver() ) {
|
||||||
|
// process any mappers left over from previous rounds
|
||||||
|
Set<TypeElement> deferredMappers = getAndResetDeferredMappers();
|
||||||
|
processMapperElements( deferredMappers );
|
||||||
|
|
||||||
|
// get and process any mappers from this round
|
||||||
|
Set<TypeElement> mappers = getMappers( annotations, roundEnvironment );
|
||||||
|
processMapperElements( mappers );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ANNOTATIONS_CLAIMED_EXCLUSIVELY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets fresh copies of all mappers deferred from previous rounds (the originals may contain references to
|
||||||
|
* erroneous source/target type elements).
|
||||||
|
*/
|
||||||
|
private Set<TypeElement> getAndResetDeferredMappers() {
|
||||||
|
Set<TypeElement> deferred = new HashSet<TypeElement>( deferredMappers.size() );
|
||||||
|
|
||||||
|
for (TypeElement element : deferredMappers ) {
|
||||||
|
deferred.add( processingEnv.getElementUtils().getTypeElement( element.getQualifiedName() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
deferredMappers.clear();
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<TypeElement> getMappers(final Set<? extends TypeElement> annotations,
|
||||||
|
final RoundEnvironment roundEnvironment) {
|
||||||
|
Set<TypeElement> mapperTypes = new HashSet<TypeElement>();
|
||||||
|
|
||||||
for ( TypeElement annotation : annotations ) {
|
for ( TypeElement annotation : annotations ) {
|
||||||
|
|
||||||
//Indicates that the annotation's type isn't on the class path of the compiled
|
//Indicates that the annotation's type isn't on the class path of the compiled
|
||||||
//project. Let the compiler deal with that and print an appropriate error.
|
//project. Let the compiler deal with that and print an appropriate error.
|
||||||
if ( annotation.getKind() != ElementKind.ANNOTATION_TYPE ) {
|
if ( annotation.getKind() != ElementKind.ANNOTATION_TYPE ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<? extends Element> elementsWithAnnotation;
|
|
||||||
try {
|
try {
|
||||||
elementsWithAnnotation = roundEnvironment.getElementsAnnotatedWith( annotation );
|
Set<? extends Element> annotatedMappers = roundEnvironment.getElementsAnnotatedWith( annotation );
|
||||||
|
for (Element mapperElement : annotatedMappers) {
|
||||||
|
TypeElement mapperTypeElement = asTypeElement( mapperElement );
|
||||||
|
|
||||||
|
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with
|
||||||
|
// annotations unknown to the compiler, even though they are not declared Mappers
|
||||||
|
if ( mapperTypeElement != null && MapperPrism.getInstanceOn( mapperTypeElement ) != null ) {
|
||||||
|
mapperTypes.add( mapperTypeElement );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch ( Throwable t ) { // whenever that may happen, but just to stay on the save side
|
catch ( Throwable t ) { // whenever that may happen, but just to stay on the save side
|
||||||
handleUncaughtError( annotation, t );
|
handleUncaughtError( annotation, t );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return mapperTypes;
|
||||||
|
}
|
||||||
|
|
||||||
for ( Element mapperElement : elementsWithAnnotation ) {
|
private void processMapperElements(Set<TypeElement> mapperElements) {
|
||||||
try {
|
for ( TypeElement mapperElement : mapperElements ) {
|
||||||
TypeElement mapperTypeElement = asTypeElement( mapperElement );
|
try {
|
||||||
|
// create a new context for each generated mapper in order to have imports of referenced types
|
||||||
// on some JDKs, RoundEnvironment.getElementsAnnotatedWith( ... ) returns types with
|
// correctly managed;
|
||||||
// annotations unknown to the compiler, even though they are not declared Mappers
|
// note that this assumes that a new source file is created for each mapper which must not
|
||||||
if ( mapperTypeElement == null || MapperPrism.getInstanceOn( mapperTypeElement ) == null ) {
|
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
|
||||||
continue;
|
// of one outer interface
|
||||||
}
|
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
|
||||||
|
processMapperTypeElement( context, mapperElement );
|
||||||
// create a new context for each generated mapper in order to have imports of referenced types
|
}
|
||||||
// correctly managed;
|
catch ( TypeHierarchyErroneousException thie ) {
|
||||||
// note that this assumes that a new source file is created for each mapper which must not
|
deferredMappers.add( mapperElement );
|
||||||
// necessarily be the case, e.g. in case of several mapper interfaces declared as inner types
|
}
|
||||||
// of one outer interface
|
catch ( Throwable t ) {
|
||||||
ProcessorContext context = new DefaultModelElementProcessorContext( processingEnv, options );
|
handleUncaughtError( mapperElement, t );
|
||||||
processMapperTypeElement( context, mapperTypeElement );
|
break;
|
||||||
}
|
|
||||||
catch ( Throwable t ) {
|
|
||||||
handleUncaughtError( mapperElement, t );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ANNOTATIONS_CLAIMED_EXCLUSIVELY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleUncaughtError(Element element, Throwable thrown) {
|
private void handleUncaughtError(Element element, Throwable thrown) {
|
||||||
|
@ -155,6 +155,10 @@ public class Executables {
|
|||||||
element = replaceTypeElementIfNecessary( elementUtils, element );
|
element = replaceTypeElementIfNecessary( elementUtils, element );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( element.asType().getKind() == TypeKind.ERROR ) {
|
||||||
|
throw new TypeHierarchyErroneousException( element );
|
||||||
|
}
|
||||||
|
|
||||||
addNotYetOverridden( elementUtils, alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
addNotYetOverridden( elementUtils, alreadyAdded, methodsIn( element.getEnclosedElements() ), parentType );
|
||||||
|
|
||||||
if ( hasNonObjectSuperclass( element ) ) {
|
if ( hasNonObjectSuperclass( element ) ) {
|
||||||
@ -244,8 +248,12 @@ public class Executables {
|
|||||||
* @return {@code true}, iff the type has a super-class that is not java.lang.Object
|
* @return {@code true}, iff the type has a super-class that is not java.lang.Object
|
||||||
*/
|
*/
|
||||||
private static boolean hasNonObjectSuperclass(TypeElement element) {
|
private static boolean hasNonObjectSuperclass(TypeElement element) {
|
||||||
|
if ( element.getSuperclass().getKind() == TypeKind.ERROR ) {
|
||||||
|
throw new TypeHierarchyErroneousException( element );
|
||||||
|
}
|
||||||
|
|
||||||
return element.getSuperclass().getKind() == TypeKind.DECLARED
|
return element.getSuperclass().getKind() == TypeKind.DECLARED
|
||||||
&& asTypeElement( element.getSuperclass() ).getSuperclass().getKind() == TypeKind.DECLARED;
|
&& !asTypeElement( element.getSuperclass() ).getQualifiedName().toString().equals( "java.lang.Object" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2015 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.internal.util;
|
||||||
|
|
||||||
|
import javax.lang.model.element.TypeElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates a type element was visited whose hierarchy was erroneous, because it has a non-existing super-type.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TypeHierarchyErroneousException extends RuntimeException {
|
||||||
|
|
||||||
|
private TypeElement element;
|
||||||
|
|
||||||
|
public TypeHierarchyErroneousException(TypeElement element) {
|
||||||
|
this.element = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeElement getElement() {
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user