From 4d4f55a162e657142c6e01122618646d0c50b664 Mon Sep 17 00:00:00 2001 From: Gunnar Morling Date: Sat, 25 Jan 2014 11:39:19 +0100 Subject: [PATCH] #109 Breaking up cycle between "model" and "writer" packages by introducing Writable interface --- .../ap/model/AbstractModelElement.java | 39 ------------- .../org/mapstruct/ap/model/Annotation.java | 14 +++-- .../ap/model/AnnotationMapperReference.java | 2 +- .../ap/model/DefaultMapperReference.java | 2 +- .../java/org/mapstruct/ap/model/Mapper.java | 3 +- .../mapstruct/ap/model/MapperReference.java | 12 ++-- .../org/mapstruct/ap/model/MappingMethod.java | 2 +- .../org/mapstruct/ap/model/ModelElement.java | 49 ++++++----------- .../org/mapstruct/ap/model/Parameter.java | 2 +- .../mapstruct/ap/model/PropertyMapping.java | 2 +- .../java/org/mapstruct/ap/model/Type.java | 2 +- .../mapstruct/ap/model/TypeConversion.java | 2 +- .../writer/FreeMarkerModelElementWriter.java | 13 ++--- .../ap/writer/ModelIncludeDirective.java | 11 ++-- .../org/mapstruct/ap/writer/ModelWriter.java | 5 +- .../org/mapstruct/ap/writer/Writable.java | 55 +++++++++++++++++++ 16 files changed, 109 insertions(+), 106 deletions(-) delete mode 100644 processor/src/main/java/org/mapstruct/ap/model/AbstractModelElement.java create mode 100644 processor/src/main/java/org/mapstruct/ap/writer/Writable.java diff --git a/processor/src/main/java/org/mapstruct/ap/model/AbstractModelElement.java b/processor/src/main/java/org/mapstruct/ap/model/AbstractModelElement.java deleted file mode 100644 index f54a81ee2..000000000 --- a/processor/src/main/java/org/mapstruct/ap/model/AbstractModelElement.java +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 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.io.Writer; - -import org.mapstruct.ap.writer.FreeMarkerModelElementWriter; - -/** - * Default implementation of {@link ModelElement} which writes model elements - * 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. - * - * @author Gunnar Morling - */ -public abstract class AbstractModelElement implements ModelElement { - - @Override - public void write(Context context, Writer writer) throws Exception { - new FreeMarkerModelElementWriter().write( this, context, writer ); - } -} diff --git a/processor/src/main/java/org/mapstruct/ap/model/Annotation.java b/processor/src/main/java/org/mapstruct/ap/model/Annotation.java index 4936aa074..894b69ab8 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Annotation.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Annotation.java @@ -18,13 +18,17 @@ */ package org.mapstruct.ap.model; +import java.util.Collections; import java.util.Set; -import org.mapstruct.ap.util.Collections; +/** + * Represents a Java 5 annotation. + * + * @author Gunnar Morling + */ +public class Annotation extends ModelElement { -public class Annotation extends AbstractModelElement { - - private Type type; + private final Type type; public Annotation(Type type) { this.type = type; @@ -36,6 +40,6 @@ public class Annotation extends AbstractModelElement { @Override public Set getImportTypes() { - return Collections.asSet( type ); + return Collections.singleton( type ); } } diff --git a/processor/src/main/java/org/mapstruct/ap/model/AnnotationMapperReference.java b/processor/src/main/java/org/mapstruct/ap/model/AnnotationMapperReference.java index c9f49ee34..6986be4a2 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/AnnotationMapperReference.java +++ b/processor/src/main/java/org/mapstruct/ap/model/AnnotationMapperReference.java @@ -30,7 +30,7 @@ import org.mapstruct.ap.util.Strings; * @author Gunnar Morling * @author Andreas Gudian */ -public class AnnotationMapperReference extends AbstractModelElement implements MapperReference { +public class AnnotationMapperReference extends MapperReference { private final Annotation annotation; private final Type type; diff --git a/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java b/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java index 6cc9d1904..98c942362 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java +++ b/processor/src/main/java/org/mapstruct/ap/model/DefaultMapperReference.java @@ -31,7 +31,7 @@ import org.mapstruct.ap.util.TypeFactory; * * @author Gunnar Morling */ -public class DefaultMapperReference extends AbstractModelElement implements MapperReference { +public class DefaultMapperReference extends MapperReference { private final Type type; private final boolean isAnnotatedMapper; 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 0e6243831..2a2354a9f 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Mapper.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Mapper.java @@ -23,7 +23,6 @@ import java.util.Collection; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; - import javax.annotation.Generated; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; @@ -37,7 +36,7 @@ import org.mapstruct.ap.util.TypeFactory; * * @author Gunnar Morling */ -public class Mapper extends AbstractModelElement { +public class Mapper extends ModelElement { private static final String IMPLEMENTATION_SUFFIX = "Impl"; diff --git a/processor/src/main/java/org/mapstruct/ap/model/MapperReference.java b/processor/src/main/java/org/mapstruct/ap/model/MapperReference.java index 1dd8edd92..2ae730ba1 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MapperReference.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MapperReference.java @@ -19,12 +19,16 @@ package org.mapstruct.ap.model; /** - * A reference to another mapper class, which itself may be generated or - * hand-written. + * A reference to another mapper class, which itself may be generated or hand-written. * * @author Gunnar Morling */ -public interface MapperReference extends ModelElement { +public abstract class MapperReference extends ModelElement { - Type getMapperType(); + /** + * Returns the type of the referenced mapper + * + * @return the type of the referenced mapper + */ + public abstract Type getMapperType(); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java b/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java index 39eba56a3..92a54b63d 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java +++ b/processor/src/main/java/org/mapstruct/ap/model/MappingMethod.java @@ -32,7 +32,7 @@ import org.mapstruct.ap.util.Strings; * * @author Gunnar Morling */ -public abstract class MappingMethod extends AbstractModelElement { +public abstract class MappingMethod extends ModelElement { private final String name; private final List parameters; diff --git a/processor/src/main/java/org/mapstruct/ap/model/ModelElement.java b/processor/src/main/java/org/mapstruct/ap/model/ModelElement.java index 59c8f9bc1..dfac6aee3 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/ModelElement.java +++ b/processor/src/main/java/org/mapstruct/ap/model/ModelElement.java @@ -21,47 +21,30 @@ package org.mapstruct.ap.model; import java.io.Writer; import java.util.Set; +import org.mapstruct.ap.writer.FreeMarkerModelElementWriter; +import org.mapstruct.ap.writer.Writable; + /** - * A model element with the ability to write itself into a given {@link Writer}. + * 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. * * @author Gunnar Morling */ -public interface ModelElement { +public abstract class ModelElement implements Writable { - /** - * Passed to {@link ModelElement}, providing access to additional data - * specific to a given implementation of the model serialization mechanism. - * - * @author Gunnar Morling - */ - interface Context { - - /** - * Retrieves the object with the given type from this context. - * - * @param type The type of the object to retrieve from this context. - * - * @return The object with the given type from this context. - */ - T get(Class type); + @Override + public void write(Context context, Writer writer) throws Exception { + new FreeMarkerModelElementWriter().write( this, context, writer ); } /** - * Writes this model element to the given writer. + * Returns a set containing those {@link Type}s referenced by this model element for which an import statement needs + * to be declared. * - * @param context Provides additional data specific to the used implementation - * of the model serialization mechanism. - * @param writer The writer to write this model to. Must not be closed by - * implementations. + * @return A set with type referenced by this model element. Must not be {@code null}. */ - void write(Context context, Writer writer) throws Exception; - - /** - * Returns a set containing those {@link Type}s referenced by this model - * element for which an import statement needs to be declared. - * - * @return A set with type referenced by this model element. Must not be - * {@code null.} - */ - Set getImportTypes(); + public abstract Set getImportTypes(); } diff --git a/processor/src/main/java/org/mapstruct/ap/model/Parameter.java b/processor/src/main/java/org/mapstruct/ap/model/Parameter.java index 1f2a7e565..e913d239b 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Parameter.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Parameter.java @@ -27,7 +27,7 @@ import org.mapstruct.ap.util.Collections; * * @author Gunnar Morling */ -public class Parameter extends AbstractModelElement { +public class Parameter extends ModelElement { private final String name; private final Type type; diff --git a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java index e14ee8241..e6e3b716e 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java +++ b/processor/src/main/java/org/mapstruct/ap/model/PropertyMapping.java @@ -29,7 +29,7 @@ import java.util.Set; * * @author Gunnar Morling */ -public class PropertyMapping extends AbstractModelElement { +public class PropertyMapping extends ModelElement { private final String sourceBeanName; private final String sourceName; diff --git a/processor/src/main/java/org/mapstruct/ap/model/Type.java b/processor/src/main/java/org/mapstruct/ap/model/Type.java index afa9d6deb..114350bcd 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/Type.java +++ b/processor/src/main/java/org/mapstruct/ap/model/Type.java @@ -43,7 +43,7 @@ import org.mapstruct.ap.util.TypeFactory; * * @author Gunnar Morling */ -public class Type extends AbstractModelElement implements Comparable { +public class Type extends ModelElement implements Comparable { private final String packageName; private final String name; diff --git a/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java b/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java index 868b1fc8f..8b0cf76d6 100644 --- a/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java +++ b/processor/src/main/java/org/mapstruct/ap/model/TypeConversion.java @@ -28,7 +28,7 @@ import java.util.Set; * * @author Gunnar Morling */ -public class TypeConversion extends AbstractModelElement { +public class TypeConversion extends ModelElement { private final Set importTypes; private final List exceptionTypes; diff --git a/processor/src/main/java/org/mapstruct/ap/writer/FreeMarkerModelElementWriter.java b/processor/src/main/java/org/mapstruct/ap/writer/FreeMarkerModelElementWriter.java index c295e04ee..b31ca2c51 100644 --- a/processor/src/main/java/org/mapstruct/ap/writer/FreeMarkerModelElementWriter.java +++ b/processor/src/main/java/org/mapstruct/ap/writer/FreeMarkerModelElementWriter.java @@ -29,11 +29,10 @@ import freemarker.template.Template; import freemarker.template.TemplateHashModel; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; -import org.mapstruct.ap.model.ModelElement; -import org.mapstruct.ap.model.ModelElement.Context; +import org.mapstruct.ap.writer.Writable.Context; /** - * Delegate for writing given {@link ModelElement}s into a {@link Writer} using + * Delegate for writing given {@link Writable}s into a {@link Writer} using * FreeMarker templates. Any parameters passed to the * {@link ModelIncludeDirective} in addition to element itself can be accessed * from within the template using the {@code ext} pseudo-element. @@ -42,16 +41,16 @@ import org.mapstruct.ap.model.ModelElement.Context; */ public class FreeMarkerModelElementWriter { - public void write(ModelElement modelElement, Context context, Writer writer) throws Exception { - write( modelElement, modelElement.getClass().getName() + ".ftl", context, writer ); + public void write(Writable writable, Context context, Writer writer) throws Exception { + write( writable, writable.getClass().getName() + ".ftl", context, writer ); } - public void write(ModelElement modelElement, String templateName, Context context, Writer writer) throws Exception { + public void write(Writable writable, String templateName, Context context, Writer writer) throws Exception { Configuration configuration = context.get( Configuration.class ); Template template = configuration.getTemplate( templateName ); template.process( new ExternalParamsTemplateModel( - new BeanModel( modelElement, BeansWrapper.getDefaultInstance() ), + new BeanModel( writable, BeansWrapper.getDefaultInstance() ), new SimpleMapModel( context.get( Map.class ), BeansWrapper.getDefaultInstance() ) ), writer diff --git a/processor/src/main/java/org/mapstruct/ap/writer/ModelIncludeDirective.java b/processor/src/main/java/org/mapstruct/ap/writer/ModelIncludeDirective.java index 6ad331459..6ca5f1610 100644 --- a/processor/src/main/java/org/mapstruct/ap/writer/ModelIncludeDirective.java +++ b/processor/src/main/java/org/mapstruct/ap/writer/ModelIncludeDirective.java @@ -29,12 +29,11 @@ import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; -import org.mapstruct.ap.model.ModelElement; import org.mapstruct.ap.writer.ModelWriter.DefaultModelElementWriterContext; /** * A {@link TemplateDirectiveModel} which allows to recursively write a graph of - * {@link ModelElement}s, with each element using its own template. Elements are + * {@link Writable}s, with each element using its own template. Elements are * imported into the parent template by using this directive like so: * {@code <@includeModel object=myProperty/>}. * @@ -53,7 +52,7 @@ public class ModelIncludeDirective implements TemplateDirectiveModel { TemplateDirectiveBody body) throws TemplateException, IOException { - ModelElement modelElement = getModelElement( params ); + Writable modelElement = getModelElement( params ); DefaultModelElementWriterContext context = createContext( params ); try { @@ -74,7 +73,7 @@ public class ModelIncludeDirective implements TemplateDirectiveModel { } @SuppressWarnings("rawtypes") - private ModelElement getModelElement(Map params) { + private Writable getModelElement(Map params) { if ( !params.containsKey( "object" ) ) { throw new IllegalArgumentException( "Object to be included must be passed to this directive via the 'object' parameter" @@ -89,11 +88,11 @@ public class ModelIncludeDirective implements TemplateDirectiveModel { ); } - if ( !( objectModel.getWrappedObject() instanceof ModelElement ) ) { + if ( !( objectModel.getWrappedObject() instanceof Writable ) ) { throw new IllegalArgumentException( "Given object isn't a ModelElement:" + objectModel.getWrappedObject() ); } - return (ModelElement) objectModel.getWrappedObject(); + return (Writable) objectModel.getWrappedObject(); } /** diff --git a/processor/src/main/java/org/mapstruct/ap/writer/ModelWriter.java b/processor/src/main/java/org/mapstruct/ap/writer/ModelWriter.java index 41c46fcbf..68c05925e 100644 --- a/processor/src/main/java/org/mapstruct/ap/writer/ModelWriter.java +++ b/processor/src/main/java/org/mapstruct/ap/writer/ModelWriter.java @@ -26,8 +26,7 @@ import javax.tools.JavaFileObject; import freemarker.log.Logger; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; -import org.mapstruct.ap.model.ModelElement; -import org.mapstruct.ap.model.ModelElement.Context; +import org.mapstruct.ap.writer.Writable.Context; /** * Writes Java source files based on given mapper models, using a FreeMarker @@ -60,7 +59,7 @@ public class ModelWriter { ); } - public void writeModel(JavaFileObject sourceFile, ModelElement model) { + public void writeModel(JavaFileObject sourceFile, Writable model) { try { BufferedWriter writer = new BufferedWriter( new IndentationCorrectingWriter( sourceFile.openWriter() ) ); diff --git a/processor/src/main/java/org/mapstruct/ap/writer/Writable.java b/processor/src/main/java/org/mapstruct/ap/writer/Writable.java new file mode 100644 index 000000000..6df1a302f --- /dev/null +++ b/processor/src/main/java/org/mapstruct/ap/writer/Writable.java @@ -0,0 +1,55 @@ +/** + * 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.writer; + +import java.io.Writer; + +/** + * An element with the ability to write itself into a given {@link Writer}. + * + * @author Gunnar Morling + */ +public interface Writable { + + /** + * Passed to {@link Writable}, providing access to additional data specific to a given implementation of the model + * serialization mechanism. + * + * @author Gunnar Morling + */ + interface Context { + + /** + * Retrieves the object with the given type from this context. + * + * @param type The type of the object to retrieve from this context. + * + * @return The object with the given type from this context. + */ + T get(Class type); + } + + /** + * Writes this element to the given writer. + * + * @param context Provides additional data specific to the used implementation of the serialization mechanism. + * @param writer The writer to write this element to. Must not be closed by implementations. + */ + void write(Context context, Writer writer) throws Exception; +}