#109 Breaking up cycle between "model" and "writer" packages by introducing Writable interface

This commit is contained in:
Gunnar Morling 2014-01-25 11:39:19 +01:00
parent 21ed656348
commit 4d4f55a162
16 changed files with 109 additions and 106 deletions

View File

@ -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 );
}
}

View File

@ -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<Type> getImportTypes() {
return Collections.asSet( type );
return Collections.singleton( type );
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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();
}

View File

@ -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<Parameter> parameters;

View File

@ -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.
* <p>
* 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> T get(Class<T> 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<Type> getImportTypes();
public abstract Set<Type> getImportTypes();
}

View File

@ -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;

View File

@ -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;

View File

@ -43,7 +43,7 @@ import org.mapstruct.ap.util.TypeFactory;
*
* @author Gunnar Morling
*/
public class Type extends AbstractModelElement implements Comparable<Type> {
public class Type extends ModelElement implements Comparable<Type> {
private final String packageName;
private final String name;

View File

@ -28,7 +28,7 @@ import java.util.Set;
*
* @author Gunnar Morling
*/
public class TypeConversion extends AbstractModelElement {
public class TypeConversion extends ModelElement {
private final Set<Type> importTypes;
private final List<Type> exceptionTypes;

View File

@ -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

View File

@ -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();
}
/**

View File

@ -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() ) );

View File

@ -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> T get(Class<T> 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;
}