mirror of
https://github.com/mapstruct/mapstruct.git
synced 2025-07-12 00:00:08 +08:00
#32 Preparing aggregated model to allow nodes to write out themselves using specific templates
This commit is contained in:
parent
522c9e851a
commit
781f698a8a
@ -130,8 +130,7 @@ public class MapperGenerationVisitor extends ElementKindVisitor6<Void, Void> {
|
|||||||
throw new RuntimeException( e );
|
throw new RuntimeException( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelWriter modelWriter = new ModelWriter( "mapper-implementation.ftl" );
|
new ModelWriter().writeModel( sourceFile, model );
|
||||||
modelWriter.writeModel( sourceFile, model );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mapper retrieveModel(TypeElement element) {
|
private Mapper retrieveModel(TypeElement element) {
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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 class AbstractModelElement implements ModelElement {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Context context, Writer writer) throws Exception {
|
||||||
|
new FreeMarkerModelElementWriter().write( this, context, writer );
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ import java.util.SortedSet;
|
|||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import javax.annotation.Generated;
|
import javax.annotation.Generated;
|
||||||
|
|
||||||
public class Mapper {
|
public class Mapper extends AbstractModelElement {
|
||||||
|
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
private final String interfaceName;
|
private final String interfaceName;
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A model element with the ability to write itself into a given {@link Writer}.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
public interface ModelElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes this model element to the given writer.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
void write(Context context, Writer writer) throws Exception;
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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;
|
||||||
|
|
||||||
|
import freemarker.template.Configuration;
|
||||||
|
import freemarker.template.Template;
|
||||||
|
import org.mapstruct.ap.model.ModelElement;
|
||||||
|
import org.mapstruct.ap.model.ModelElement.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate for writing given {@link ModelElements} into a {@link Writer} using
|
||||||
|
* FreeMarker templates.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
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(ModelElement modelElement, String templateName, Context context, Writer writer) throws Exception {
|
||||||
|
Configuration configuration = context.get( Configuration.class );
|
||||||
|
|
||||||
|
Template template = configuration.getTemplate( templateName );
|
||||||
|
template.process( modelElement, writer );
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2012-2013 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.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import freemarker.core.Environment;
|
||||||
|
import freemarker.ext.beans.BeanModel;
|
||||||
|
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
|
||||||
|
* imported into the parent template by using this directive like so:
|
||||||
|
* {@code <@includeModel object=myProperty/>}.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
public class ModelIncludeDirective implements TemplateDirectiveModel {
|
||||||
|
|
||||||
|
private DefaultModelElementWriterContext context;
|
||||||
|
|
||||||
|
public ModelIncludeDirective(DefaultModelElementWriterContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
|
||||||
|
TemplateDirectiveBody body)
|
||||||
|
throws TemplateException, IOException {
|
||||||
|
|
||||||
|
Object wrappedObject = ( (BeanModel) params.get( "object" ) ).getWrappedObject();
|
||||||
|
|
||||||
|
if ( !( wrappedObject instanceof ModelElement ) ) {
|
||||||
|
throw new IllegalArgumentException( "Given object isn't a ModelElement:" + wrappedObject );
|
||||||
|
}
|
||||||
|
|
||||||
|
ModelElement modelElement = (ModelElement) wrappedObject;
|
||||||
|
|
||||||
|
try {
|
||||||
|
modelElement.write( context, env.getOut() );
|
||||||
|
}
|
||||||
|
catch ( TemplateException te ) {
|
||||||
|
throw te;
|
||||||
|
}
|
||||||
|
catch ( IOException ioe ) {
|
||||||
|
throw ioe;
|
||||||
|
}
|
||||||
|
catch ( RuntimeException re ) {
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
throw new RuntimeException( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,11 +19,14 @@
|
|||||||
package org.mapstruct.ap.writer;
|
package org.mapstruct.ap.writer;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import javax.tools.JavaFileObject;
|
import javax.tools.JavaFileObject;
|
||||||
|
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.DefaultObjectWrapper;
|
import freemarker.template.DefaultObjectWrapper;
|
||||||
import freemarker.template.Template;
|
import org.mapstruct.ap.model.ModelElement;
|
||||||
|
import org.mapstruct.ap.model.ModelElement.Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes Java source files based on given mapper models, using a FreeMarker
|
* Writes Java source files based on given mapper models, using a FreeMarker
|
||||||
@ -39,25 +42,22 @@ public class ModelWriter {
|
|||||||
*/
|
*/
|
||||||
private static final Configuration CONFIGURATION;
|
private static final Configuration CONFIGURATION;
|
||||||
|
|
||||||
private final String templateName;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
CONFIGURATION = new Configuration();
|
CONFIGURATION = new Configuration();
|
||||||
CONFIGURATION.setClassForTemplateLoading( ModelWriter.class, "/" );
|
CONFIGURATION.setClassForTemplateLoading( ModelWriter.class, "/" );
|
||||||
CONFIGURATION.setObjectWrapper( new DefaultObjectWrapper() );
|
CONFIGURATION.setObjectWrapper( new DefaultObjectWrapper() );
|
||||||
|
CONFIGURATION.setSharedVariable(
|
||||||
|
"includeModel",
|
||||||
|
new ModelIncludeDirective( new DefaultModelElementWriterContext( CONFIGURATION ) )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelWriter(String templateName) {
|
public void writeModel(JavaFileObject sourceFile, ModelElement model) {
|
||||||
this.templateName = templateName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeModel(JavaFileObject sourceFile, Object model) {
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BufferedWriter writer = new BufferedWriter( sourceFile.openWriter() );
|
BufferedWriter writer = new BufferedWriter( sourceFile.openWriter() );
|
||||||
|
|
||||||
Template template = CONFIGURATION.getTemplate( templateName );
|
model.write( new DefaultModelElementWriterContext( CONFIGURATION ), writer );
|
||||||
template.process( model, writer );
|
|
||||||
writer.flush();
|
writer.flush();
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
@ -68,4 +68,25 @@ public class ModelWriter {
|
|||||||
throw new RuntimeException( e );
|
throw new RuntimeException( e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Context} implementation which provides access to the current
|
||||||
|
* FreeMarker {@link Configuration}.
|
||||||
|
*
|
||||||
|
* @author Gunnar Morling
|
||||||
|
*/
|
||||||
|
static class DefaultModelElementWriterContext implements Context {
|
||||||
|
|
||||||
|
private Map<Class<?>, Object> values = new HashMap<Class<?>, Object>();
|
||||||
|
|
||||||
|
private DefaultModelElementWriterContext(Configuration configuration) {
|
||||||
|
values.put( Configuration.class, configuration );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> T get(Class<T> type) {
|
||||||
|
return (T) values.get( type );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user