From 61f181a589564131b1a540e5322ec63d56604870 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Mon, 28 May 2012 14:50:43 +0200 Subject: [PATCH] Initial import --- .gitignore | 14 ++ core/etc/license.txt | 13 ++ core/pom.xml | 46 ++++ core/src/main/java/de/moapa/maple/Mapper.java | 20 ++ .../src/main/java/de/moapa/maple/Mappers.java | 45 ++++ .../src/main/java/de/moapa/maple/Mapping.java | 20 ++ .../test/java/de/moapa/maple/MappersTest.java | 31 +++ .../java/de/moapa/maple/test/model/Foo.java | 20 ++ .../de/moapa/maple/test/model/FooImpl.java | 20 ++ etc/license.txt | 13 ++ parent/etc/license.txt | 13 ++ parent/pom.xml | 121 +++++++++++ pom.xml | 40 ++++ processor/etc/license.txt | 13 ++ processor/pom.xml | 97 +++++++++ .../maple/ap/MapperGenerationVisitor.java | 140 ++++++++++++ .../de/moapa/maple/ap/MappingProcessor.java | 77 +++++++ .../java/de/moapa/maple/ap/model/Mapper.java | 52 +++++ .../de/moapa/maple/ap/model/MapperMethod.java | 41 ++++ .../de/moapa/maple/ap/model/Parameter.java | 35 +++ .../java/de/moapa/maple/ap/model/Type.java | 36 ++++ .../javax.annotation.processing.Processor | 1 + .../resources/dozer-mapper-implementation.ftl | 36 ++++ .../de/moapa/maple/ap/test/CarMapperTest.java | 201 ++++++++++++++++++ .../de/moapa/maple/ap/test/model/Car.java | 33 +++ .../de/moapa/maple/ap/test/model/CarDto.java | 36 ++++ .../moapa/maple/ap/test/model/CarMapper.java | 27 +++ 27 files changed, 1241 insertions(+) create mode 100644 .gitignore create mode 100644 core/etc/license.txt create mode 100644 core/pom.xml create mode 100644 core/src/main/java/de/moapa/maple/Mapper.java create mode 100644 core/src/main/java/de/moapa/maple/Mappers.java create mode 100644 core/src/main/java/de/moapa/maple/Mapping.java create mode 100644 core/src/test/java/de/moapa/maple/MappersTest.java create mode 100644 core/src/test/java/de/moapa/maple/test/model/Foo.java create mode 100644 core/src/test/java/de/moapa/maple/test/model/FooImpl.java create mode 100644 etc/license.txt create mode 100644 parent/etc/license.txt create mode 100644 parent/pom.xml create mode 100644 pom.xml create mode 100644 processor/etc/license.txt create mode 100644 processor/pom.xml create mode 100644 processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/MappingProcessor.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/model/Mapper.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/model/MapperMethod.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/model/Parameter.java create mode 100644 processor/src/main/java/de/moapa/maple/ap/model/Type.java create mode 100644 processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor create mode 100644 processor/src/main/resources/dozer-mapper-implementation.ftl create mode 100644 processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java create mode 100644 processor/src/test/java/de/moapa/maple/ap/test/model/Car.java create mode 100644 processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java create mode 100644 processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7c7c1fcdca --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Eclipse +.metadata +.classpath +.project +.settings + +# IntelliJ +*.iml +*.ipr +*.iws + +# Build +target +test-output \ No newline at end of file diff --git a/core/etc/license.txt b/core/etc/license.txt new file mode 100644 index 0000000000..a9168191bc --- /dev/null +++ b/core/etc/license.txt @@ -0,0 +1,13 @@ + Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + + 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. \ No newline at end of file diff --git a/core/pom.xml b/core/pom.xml new file mode 100644 index 0000000000..9110d8e550 --- /dev/null +++ b/core/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + + de.moapa.maple + maple-parent + 1.0-SNAPSHOT + ../parent/pom.xml + + + maple + jar + Maple Core + + + + org.testng + testng + test + + + org.easytesting + fest-assert + test + + + diff --git a/core/src/main/java/de/moapa/maple/Mapper.java b/core/src/main/java/de/moapa/maple/Mapper.java new file mode 100644 index 0000000000..f6d49cc45a --- /dev/null +++ b/core/src/main/java/de/moapa/maple/Mapper.java @@ -0,0 +1,20 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple; + +public @interface Mapper { + +} diff --git a/core/src/main/java/de/moapa/maple/Mappers.java b/core/src/main/java/de/moapa/maple/Mappers.java new file mode 100644 index 0000000000..0193d7012d --- /dev/null +++ b/core/src/main/java/de/moapa/maple/Mappers.java @@ -0,0 +1,45 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple; + + +public class Mappers { + + private final static String IMPLEMENTATION_SUFFIX = "Impl"; + + /** + * TODO: Check that + * - clazz is an interface + * - the implementation type implements clazz + * - clazz is annotated with @Mapper + * + * TODO: Use privileged action + */ + @SuppressWarnings("unchecked") + public static T getMapper(Class clazz) { + try { + +// ClassLoader classLoader = clazz.getClassLoader(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + + return (T) classLoader.loadClass( clazz.getName() + IMPLEMENTATION_SUFFIX ).newInstance(); + } + catch ( Exception e ) { + e.printStackTrace(); + throw new RuntimeException( e ); + } + } +} diff --git a/core/src/main/java/de/moapa/maple/Mapping.java b/core/src/main/java/de/moapa/maple/Mapping.java new file mode 100644 index 0000000000..2efd59c6b0 --- /dev/null +++ b/core/src/main/java/de/moapa/maple/Mapping.java @@ -0,0 +1,20 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple; + +public @interface Mapping { + +} diff --git a/core/src/test/java/de/moapa/maple/MappersTest.java b/core/src/test/java/de/moapa/maple/MappersTest.java new file mode 100644 index 0000000000..13b08e98f4 --- /dev/null +++ b/core/src/test/java/de/moapa/maple/MappersTest.java @@ -0,0 +1,31 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple; + +import de.moapa.maple.test.model.Foo; +import org.testng.annotations.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class MappersTest { + + @Test + public void shouldReturnImplementationInstance() { + + Foo mapper = Mappers.getMapper( Foo.class ); + assertThat( mapper ).isNotNull(); + } +} diff --git a/core/src/test/java/de/moapa/maple/test/model/Foo.java b/core/src/test/java/de/moapa/maple/test/model/Foo.java new file mode 100644 index 0000000000..b052afdafa --- /dev/null +++ b/core/src/test/java/de/moapa/maple/test/model/Foo.java @@ -0,0 +1,20 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.test.model; + +public interface Foo { + +} diff --git a/core/src/test/java/de/moapa/maple/test/model/FooImpl.java b/core/src/test/java/de/moapa/maple/test/model/FooImpl.java new file mode 100644 index 0000000000..44c7881f45 --- /dev/null +++ b/core/src/test/java/de/moapa/maple/test/model/FooImpl.java @@ -0,0 +1,20 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.test.model; + +public class FooImpl implements Foo { + +} diff --git a/etc/license.txt b/etc/license.txt new file mode 100644 index 0000000000..a9168191bc --- /dev/null +++ b/etc/license.txt @@ -0,0 +1,13 @@ + Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + + 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. \ No newline at end of file diff --git a/parent/etc/license.txt b/parent/etc/license.txt new file mode 100644 index 0000000000..a9168191bc --- /dev/null +++ b/parent/etc/license.txt @@ -0,0 +1,13 @@ + Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + + 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. \ No newline at end of file diff --git a/parent/pom.xml b/parent/pom.xml new file mode 100644 index 0000000000..c53a9eb0c2 --- /dev/null +++ b/parent/pom.xml @@ -0,0 +1,121 @@ + + + + 4.0.0 + + de.moapa.maple + maple-parent + 1.0-SNAPSHOT + pom + + Maple Parent + https://github.com/gunnarmorling/maple + + + UTF-8 + + + + + + org.freemarker + freemarker + 2.3.14 + + + net.sf.dozer + dozer + 5.3.2 + + + org.slf4j + slf4j-jdk14 + 1.5.10 + + + + org.testng + testng + 6.3.1 + + + org.easytesting + fest-assert + 1.4 + + + + ${project.groupId} + maple + ${project.version} + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12 + + + com.mycila.maven-license-plugin + maven-license-plugin + 1.9.0 + + + + + + + com.mycila.maven-license-plugin + maven-license-plugin + +
etc/license.txt
+ true +
+ + + + check + + + +
+
+
+ +
diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000..e13bd15b54 --- /dev/null +++ b/pom.xml @@ -0,0 +1,40 @@ + + + + + 4.0.0 + + + de.moapa.maple + maple-parent + 1.0-SNAPSHOT + parent/pom.xml + + + maple-aggregator + pom + Maple-Aggregator + + + parent + core + processor + + diff --git a/processor/etc/license.txt b/processor/etc/license.txt new file mode 100644 index 0000000000..a9168191bc --- /dev/null +++ b/processor/etc/license.txt @@ -0,0 +1,13 @@ + Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + + 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. \ No newline at end of file diff --git a/processor/pom.xml b/processor/pom.xml new file mode 100644 index 0000000000..3501264250 --- /dev/null +++ b/processor/pom.xml @@ -0,0 +1,97 @@ + + + + 4.0.0 + + + de.moapa.maple + maple-parent + 1.0-SNAPSHOT + ../parent/pom.xml + + + maple-processor + jar + Maple Processor + + + + org.freemarker + freemarker + + + + net.sf.dozer + dozer + test + + + org.slf4j + slf4j-jdk14 + test + + + org.testng + testng + test + + + org.easytesting + fest-assert + test + + + ${project.groupId} + maple + test + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + generate-test-resources + + copy-dependencies + + + ${project.build.directory}/test-dependencies + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + -proc:none + + + + + + diff --git a/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java b/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java new file mode 100644 index 0000000000..3100a64cc8 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/MapperGenerationVisitor.java @@ -0,0 +1,140 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap; + +import java.io.BufferedWriter; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.ElementKindVisitor6; +import javax.tools.JavaFileObject; + +import de.moapa.maple.ap.model.Mapper; +import de.moapa.maple.ap.model.MapperMethod; +import de.moapa.maple.ap.model.Parameter; +import de.moapa.maple.ap.model.Type; +import freemarker.template.Configuration; +import freemarker.template.Template; + +import static javax.lang.model.util.ElementFilter.methodsIn; + +class MapperGenerationVisitor extends ElementKindVisitor6 { + + private final static String IMPLEMENTATION_SUFFIX = "Impl"; + + private final static String TEMPLATE_NAME = "dozer-mapper-implementation.ftl"; + + private final ProcessingEnvironment processingEnvironment; + + private final Configuration configuration; + + public MapperGenerationVisitor(ProcessingEnvironment processingEnvironment, Configuration configuration) { + this.processingEnvironment = processingEnvironment; + this.configuration = configuration; + } + + @Override + public Void visitTypeAsInterface(TypeElement element, Void p) { + + Mapper model = retrieveModel( element ); + String sourceFileName = element.getQualifiedName() + IMPLEMENTATION_SUFFIX; + + writeModelToSourceFile( sourceFileName, model ); + + return null; + } + + private void writeModelToSourceFile(String fileName, Mapper model) { + try { + JavaFileObject sourceFile = processingEnvironment.getFiler().createSourceFile( fileName ); + BufferedWriter writer = new BufferedWriter( sourceFile.openWriter() ); + + Template template = configuration.getTemplate( TEMPLATE_NAME ); + template.process( model, writer ); + writer.flush(); + writer.close(); + } + catch ( Exception e ) { + throw new RuntimeException( e ); + } + } + + private Mapper retrieveModel(TypeElement element) { + + return new Mapper( + processingEnvironment.getElementUtils().getPackageOf( element ).getQualifiedName().toString(), + element.getSimpleName() + IMPLEMENTATION_SUFFIX, + element.getSimpleName().toString(), + retrieveMethods( element ) + ); + } + + private List retrieveMethods(TypeElement element) { + + List methods = new ArrayList(); + + for ( ExecutableElement oneMethod : methodsIn( element.getEnclosedElements() ) ) { + + methods.add( + new MapperMethod( + oneMethod.getSimpleName().toString(), + retrieveReturnType( oneMethod ), + retrieveParameter( oneMethod ) + ) + ); + } + + return methods; + } + + private Parameter retrieveParameter(ExecutableElement method) { + + List parameters = method.getParameters(); + + if ( parameters.size() != 1 ) { + //TODO: Log error + return null; + } + + return new Parameter( + parameters.get( 0 ).getSimpleName().toString(), + new Type( + processingEnvironment.getElementUtils() + .getPackageOf( parameters.get( 0 ) ) + .getQualifiedName() + .toString(), + processingEnvironment.getTypeUtils() + .asElement( parameters.get( 0 ).asType() ) + .getSimpleName() + .toString() + ) + ); + } + + private Type retrieveReturnType(ExecutableElement method) { + + Element returnTypeElement = processingEnvironment.getTypeUtils().asElement( method.getReturnType() ); + + return new Type( + processingEnvironment.getElementUtils().getPackageOf( returnTypeElement ).getQualifiedName().toString(), + returnTypeElement.getSimpleName().toString() + ); + } +} \ No newline at end of file diff --git a/processor/src/main/java/de/moapa/maple/ap/MappingProcessor.java b/processor/src/main/java/de/moapa/maple/ap/MappingProcessor.java new file mode 100644 index 0000000000..022312b636 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/MappingProcessor.java @@ -0,0 +1,77 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap; + + +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; + +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; + +@SupportedAnnotationTypes("de.moapa.maple.Mapper") +public class MappingProcessor extends AbstractProcessor { + + /** + * Whether this processor claims all processed annotations exclusively or not. + */ + private static final boolean ANNOTATIONS_CLAIMED_EXCLUSIVELY = false; + + private Configuration configuration; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + + super.init( processingEnv ); + + configuration = new Configuration(); + configuration.setClassForTemplateLoading( MappingProcessor.class, "/" ); + configuration.setObjectWrapper( new DefaultObjectWrapper() ); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latestSupported(); + } + + @Override + public boolean process( + final Set annotations, + final RoundEnvironment roundEnvironment) { + + for ( TypeElement oneAnnotation : annotations ) { + + //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. + if ( oneAnnotation.getKind() != ElementKind.ANNOTATION_TYPE ) { + continue; + } + + for ( Element oneAnnotatedElement : roundEnvironment.getElementsAnnotatedWith( oneAnnotation ) ) { + oneAnnotatedElement.accept( new MapperGenerationVisitor( processingEnv, configuration ), null ); + } + } + + return ANNOTATIONS_CLAIMED_EXCLUSIVELY; + } +} \ No newline at end of file diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java b/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java new file mode 100644 index 0000000000..5e1e44f6bc --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/model/Mapper.java @@ -0,0 +1,52 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.model; + +import java.util.List; + +public class Mapper { + + private final String packageName; + + private final String implementationType; + + private final String interfaceType; + + private final List mapperMethods; + + public Mapper(String packageName, String implementationType, String interfaceType, List mapperMethods) { + this.packageName = packageName; + this.implementationType = implementationType; + this.interfaceType = interfaceType; + this.mapperMethods = mapperMethods; + } + + public String getPackageName() { + return packageName; + } + + public String getImplementationType() { + return implementationType; + } + + public String getInterfaceType() { + return interfaceType; + } + + public List getMapperMethods() { + return mapperMethods; + } +} diff --git a/processor/src/main/java/de/moapa/maple/ap/model/MapperMethod.java b/processor/src/main/java/de/moapa/maple/ap/model/MapperMethod.java new file mode 100644 index 0000000000..01137012c9 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/model/MapperMethod.java @@ -0,0 +1,41 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.model; + +public class MapperMethod { + + private final String name; + private final Type returnType; + private final Parameter parameter; + + public MapperMethod(String name, Type returnType, Parameter parameter) { + this.name = name; + this.returnType = returnType; + this.parameter = parameter; + } + + public String getName() { + return name; + } + + public Type getReturnType() { + return returnType; + } + + public Parameter getParameter() { + return parameter; + } +} diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Parameter.java b/processor/src/main/java/de/moapa/maple/ap/model/Parameter.java new file mode 100644 index 0000000000..c82c8eb0d5 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/model/Parameter.java @@ -0,0 +1,35 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.model; + +public class Parameter { + + private final String name; + private final Type type; + + public Parameter(String name, Type type) { + this.name = name; + this.type = type; + } + + public String getName() { + return name; + } + + public Type getType() { + return type; + } +} diff --git a/processor/src/main/java/de/moapa/maple/ap/model/Type.java b/processor/src/main/java/de/moapa/maple/ap/model/Type.java new file mode 100644 index 0000000000..7613aad2c2 --- /dev/null +++ b/processor/src/main/java/de/moapa/maple/ap/model/Type.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.model; + +public class Type { + + private final String packageName; + + private final String name; + + public Type(String packageName, String name) { + this.packageName = packageName; + this.name = name; + } + + public String getPackageName() { + return packageName; + } + + public String getName() { + return name; + } +} diff --git a/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor new file mode 100644 index 0000000000..40a4e03810 --- /dev/null +++ b/processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -0,0 +1 @@ +de.moapa.maple.ap.MappingProcessor \ No newline at end of file diff --git a/processor/src/main/resources/dozer-mapper-implementation.ftl b/processor/src/main/resources/dozer-mapper-implementation.ftl new file mode 100644 index 0000000000..9927ec77f7 --- /dev/null +++ b/processor/src/main/resources/dozer-mapper-implementation.ftl @@ -0,0 +1,36 @@ +<#-- + + Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + + 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 ${packageName}; + +import org.dozer.DozerBeanMapper; +import org.dozer.Mapper; + +public class ${implementationType} implements ${interfaceType} { + +private final Mapper mapper; + +public ${implementationType}() { +mapper = new DozerBeanMapper(); +} + +<#list mapperMethods as oneMethod> +public ${oneMethod.returnType.name} ${oneMethod.name}(${oneMethod.parameter.type.name} ${oneMethod.parameter.name}) { +return mapper.map(${oneMethod.parameter.name}, ${oneMethod.returnType.name}.class); +} + +} diff --git a/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java b/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java new file mode 100644 index 0000000000..3f34343955 --- /dev/null +++ b/processor/src/test/java/de/moapa/maple/ap/test/CarMapperTest.java @@ -0,0 +1,201 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import de.moapa.maple.ap.MappingProcessor; +import de.moapa.maple.ap.test.model.Car; +import de.moapa.maple.ap.test.model.CarDto; +import de.moapa.maple.ap.test.model.CarMapper; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class CarMapperTest { + + private DiagnosticCollector diagnostics; + private JavaCompiler compiler; + + private String sourceDir; + private String classOutputDir; + private String sourceOutputDir; + private List classPath; + + @BeforeClass + public void setup() throws Exception { + + compiler = ToolProvider.getSystemJavaCompiler(); + + String basePath = getBasePath(); + + sourceDir = basePath + "/src/test/java"; + classOutputDir = basePath + "/target/compilation-tests/classes"; + sourceOutputDir = basePath + "/target/compilation-tests/generated-sources/mapping"; + + String testDependenciesDir = basePath + "/target/test-dependencies/"; + classPath = Arrays.asList( + new File( testDependenciesDir, "maple.jar" ), + new File( testDependenciesDir, "dozer.jar" ), + new File( testDependenciesDir, "slf4j-api.jar" ), + new File( testDependenciesDir, "slf4j-jdk14.jar" ) + ); + + createOutputDirs(); + + Thread.currentThread().setContextClassLoader( + new URLClassLoader( + new URL[] { new File( classOutputDir ).toURI().toURL() }, + Thread.currentThread().getContextClassLoader() + ) + ); + } + + @BeforeMethod + public void setUpDiagnostics() { + diagnostics = new DiagnosticCollector(); + } + + @Test + public void shouldProvideMapperInstance() throws Exception { + + //given + File[] sourceFiles = getSourceFiles( Car.class, CarDto.class, CarMapper.class ); + + //when + boolean compilationSuccessful = compile( diagnostics, sourceFiles ); + + //then + assertThat( compilationSuccessful ).describedAs( "Compilation failed: " + diagnostics.getDiagnostics() ) + .isTrue(); + assertThat( CarMapper.INSTANCE ).isNotNull(); + } + + @Test + public void shouldMapCar() { + + //given + File[] sourceFiles = getSourceFiles( Car.class, CarDto.class, CarMapper.class ); + Car car = new Car( "Morris" ); + + //when + boolean compilationSuccessful = compile( diagnostics, sourceFiles ); + CarDto carDto = CarMapper.INSTANCE.carToCarDto( car ); + + //then + assertThat( compilationSuccessful ).describedAs( "Compilation failed: " + diagnostics.getDiagnostics() ) + .isTrue(); + assertThat( carDto ).isNotNull(); + assertThat( carDto.getMake() ).isEqualTo( car.getMake() ); + } + + private File[] getSourceFiles(Class... clazz) { + + File[] sourceFiles = new File[clazz.length]; + + for ( int i = 0; i < clazz.length; i++ ) { + + sourceFiles[i] = new File( + sourceDir + + File.separator + + clazz[i].getName().replace( ".", File.separator ) + + ".java" + ); + } + + + return sourceFiles; + } + + public boolean compile(DiagnosticCollector diagnostics, File... sourceFiles) { + + StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null ); + + Iterable compilationUnits = fileManager.getJavaFileObjects( sourceFiles ); + + try { + fileManager.setLocation( StandardLocation.CLASS_PATH, classPath ); + fileManager.setLocation( StandardLocation.CLASS_OUTPUT, Arrays.asList( new File( classOutputDir ) ) ); + fileManager.setLocation( StandardLocation.SOURCE_OUTPUT, Arrays.asList( new File( sourceOutputDir ) ) ); + } + catch ( IOException e ) { + throw new RuntimeException( e ); + } + + CompilationTask task = compiler.getTask( + null, + fileManager, + diagnostics, + Collections.emptyList(), + null, + compilationUnits + ); + task.setProcessors( Arrays.asList( new MappingProcessor() ) ); + + return task.call(); + } + + private String getBasePath() { + + try { + return new File( "." ).getCanonicalPath(); + } + catch ( IOException e ) { + throw new RuntimeException( e ); + } + } + + private void createOutputDirs() { + + File directory = new File( classOutputDir ); + deleteDirectory( directory ); + directory.mkdirs(); + + directory = new File( sourceOutputDir ); + deleteDirectory( directory ); + directory.mkdirs(); + } + + private void deleteDirectory(File path) { + if ( path.exists() ) { + File[] files = path.listFiles(); + for ( int i = 0; i < files.length; i++ ) { + if ( files[i].isDirectory() ) { + deleteDirectory( files[i] ); + } + else { + files[i].delete(); + } + } + } + path.delete(); + } +} diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java b/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java new file mode 100644 index 0000000000..000762f6ad --- /dev/null +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/Car.java @@ -0,0 +1,33 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.test.model; + +public class Car { + + private String make; + + public Car(String make) { + this.make = make; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } +} diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java b/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java new file mode 100644 index 0000000000..0044380a0a --- /dev/null +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/CarDto.java @@ -0,0 +1,36 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.test.model; + +public class CarDto { + + private String make; + + public CarDto() { + } + + public CarDto(String make) { + this.make = make; + } + + public String getMake() { + return make; + } + + public void setMake(String make) { + this.make = make; + } +} diff --git a/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java b/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java new file mode 100644 index 0000000000..2246b51605 --- /dev/null +++ b/processor/src/test/java/de/moapa/maple/ap/test/model/CarMapper.java @@ -0,0 +1,27 @@ +/** + * Copyright 2012 Gunnar Morling (http://www.gunnarmorling.de/) + * + * 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 de.moapa.maple.ap.test.model; + +import de.moapa.maple.Mapper; +import de.moapa.maple.Mappers; + +@Mapper +public interface CarMapper { + + CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); + + CarDto carToCarDto(Car car); +}