Skip to content

Commit

Permalink
#46 - Add support for IgnoreMissing SOURCE / DESTINATION / ALL / NONE…
Browse files Browse the repository at this point in the history
… with IT
  • Loading branch information
slemesle committed Nov 28, 2014
1 parent dd4b45c commit 88ed2fa
Show file tree
Hide file tree
Showing 20 changed files with 521 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,11 @@ public TypeMirror getAsTypeMirror(String parameter) {
}

public String getAsString(String parameter) {
return (String) map.get(parameter).getValue();
return map.get(parameter).getValue().toString();
}

public <T> T getAs(String parameter) {
return (T) map.get(parameter).getValue();
}

public Element asElement() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package fr.xebia.extras.selma.codegen;


import fr.xebia.extras.selma.codegen.compiler.CompilerMessageRegistry;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
Expand All @@ -36,6 +38,7 @@ public class MapperGeneratorContext {


private final ProcessingEnvironment processingEnv;
private final CompilerMessageRegistry messageRegistry;
int depth = 0;

Elements elements;
Expand All @@ -60,12 +63,14 @@ public MapperGeneratorContext(ProcessingEnvironment processingEnvironment) {
this.processingEnv = processingEnvironment;
mappingRegistry = new HashMap<String, MappingMethod>();
methodStack = new LinkedList<MappingMethod>();
messageRegistry = new CompilerMessageRegistry();

}


public void error(Element element, String message, Object... args) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format(message, args), element);

processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, String.format(message, args), messageRegistry.hasMessageFor(Diagnostic.Kind.ERROR, element) ? null : element);
}

public void pushStackForBody(MappingSourceNode node, SourceNodeVars vars) {
Expand All @@ -84,7 +89,7 @@ public StackElem popStack() {
}

public void warn(String s, ExecutableElement element) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, s, element);
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, s, messageRegistry.hasMessageFor(Diagnostic.Kind.WARNING, element) ? null : element);
}

/**
Expand Down Expand Up @@ -113,10 +118,6 @@ public String mappingMethod(InOutType inOutType) {
return method.name();
}

public Collection<MappingMethod> mappingMethods() {
return mappingRegistry.values();
}

private MappingMethod getMappingMethod(InOutType inOutType, MappingMethod mappingMethod) {
InOutType key = inOutType;
MappingMethod method = mappingMethod;
Expand Down Expand Up @@ -159,25 +160,12 @@ public MappingMethod popMappingMethod() {
return mappingMethod;
}

public ProcessingEnvironment processingEnv() {
return processingEnv;
}

public Elements elements() {
return elements;
}

public void info(Element typeElement, String templateMessage, Object... args) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format(templateMessage, args), typeElement);
}

public void warn(Element element, String templateMessage, Object... args) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, String.format(templateMessage, args), element);
}


public void notice(Element element, String templateMessage, Object... args) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format(templateMessage, args), element);
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, String.format(templateMessage, args), messageRegistry.hasMessageFor(Diagnostic.Kind.WARNING, element) ? null : element);
}

public void setNewParams(String newParams) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,35 +225,35 @@ private MappingSourceNode generate(InOutType inOutType) throws IOException {
continue; // Skip ignored in field
}

if (isMissingInDestination && maps.isIgnoreMissingProperties()) {
if (isMissingInDestination && maps.ignoreMissing().isIgnoreDestination()) {
continue; // Skip ignored missing properties in destination bean
} else {
}


if (isMissingInDestination) {
context.error(inBean.getFieldElement(field), String.format("setter for field %s from source bean %s is missing in destination bean %s using field %s !\n" +
" --> Add @Mapper(withIgnoreFields=\"%s.%s\") / @Maps(withIgnoreFields=\"%s.%s\") to mapper interface / method or add missing getter or specify corresponding @Field to customize field to field mapping", field, inOutType.in(), inOutType.out(), customFieldsFor, inOutType.in(), field, inOutType.in(), field));
continue;
}
if (isMissingInDestination) {
context.error(mapperMethod.element(), String.format("setter for field %s from source bean %s is missing in destination bean %s !\n" +
" --> Add @Mapper(withIgnoreFields=\"%s.%s\") / @Maps(withIgnoreFields=\"%s.%s\") to mapper interface / method or add missing getter or specify corresponding @Field to customize field to field mapping", field, inOutType.in(), inOutType.out(), inOutType.in(), field, inOutType.in(), field));
continue;
}

try {
MappingBuilder mappingBuilder = findBuilderFor(new InOutType(inBean.getTypeFor(field), outBean.getTypeFor(outFieldName), inOutType.isOutPutAsParam()));
if (mappingBuilder != null) {
ptr = ptr.child(mappingBuilder.build(context, new SourceNodeVars(field, outFieldName, inBean, outBean)
.withInOutType(new InOutType(inBean.getTypeFor(field), outBean.getTypeFor(outFieldName), inOutType.isOutPutAsParam())).withAssign(false)));
try {
MappingBuilder mappingBuilder = findBuilderFor(new InOutType(inBean.getTypeFor(field), outBean.getTypeFor(outFieldName), inOutType.isOutPutAsParam()));
if (mappingBuilder != null) {
ptr = ptr.child(mappingBuilder.build(context, new SourceNodeVars(field, outFieldName, inBean, outBean)
.withInOutType(new InOutType(inBean.getTypeFor(field), outBean.getTypeFor(outFieldName), inOutType.isOutPutAsParam())).withAssign(false)));

generateStack(context);
} else {
handleNotSupported(inOutType, ptr);
}
} catch (Exception e) {
System.out.printf("Error while searching builder for field %s on %s mapper", field, inOutType.toString());
e.printStackTrace();
generateStack(context);
} else {
handleNotSupported(inOutType, ptr);
}
} catch (Exception e) {
System.out.printf("Error while searching builder for field %s on %s mapper", field, inOutType.toString());
e.printStackTrace();
}


ptr = lastChild(ptr);
}
ptr = lastChild(ptr);

outFields.remove(outFieldName);
}

Expand All @@ -263,11 +263,11 @@ private MappingSourceNode generate(InOutType inOutType) throws IOException {
ptr = lastChild(ptr);
}

if (!maps.isIgnoreMissingProperties()) { // Report destination bean fields not mapped
if (!maps.ignoreMissing().isIgnoreSource()) { // Report destination bean fields not mapped
for (String outField : outFields) {

if (!maps.isIgnoredField(outField, inOutType.outAsDeclaredType())) {
context.error(outBean.getSetterElement(outField), "setter for field %s from destination bean %s has no getter in source bean %s !\n" +
context.error(mapperMethod.element(), "setter for field %s from destination bean %s has no getter in source bean %s !\n" +
" --> Add @Mapper(withIgnoreFields=\"%s.%s\") / @Maps(withIgnoreFields=\"%s.%s\") to mapper interface / method or add missing setter or specify corresponding @Field to customize field to field mapping", outField, inOutType.out(), inOutType.in(), inOutType.out(), outField, inOutType.out(), outField);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@
package fr.xebia.extras.selma.codegen;

import com.squareup.javawriter.JavaWriter;
import fr.xebia.extras.selma.IgnoreMissing;
import fr.xebia.extras.selma.Mapper;

import javax.lang.model.element.TypeElement;
import java.io.IOException;
import java.util.List;

import static fr.xebia.extras.selma.IgnoreMissing.ALL;
import static fr.xebia.extras.selma.IgnoreMissing.DEFAULT;
import static fr.xebia.extras.selma.IgnoreMissing.NONE;

/**
* Class used to wrap the Mapper Annotation
*/
public class MapperWrapper {
public static final String WITH_IGNORE_FIELDS = "withIgnoreFields";
public static final String WITH_ENUMS = "withEnums";
public static final String WITH_IGNORE_MISSING = "withIgnoreMissing";
private final FieldsWrapper fields;
private final SourceConfiguration configuration;
private final IgnoreFieldsWrapper ignoreFieldsWrapper;
Expand All @@ -40,6 +46,7 @@ public class MapperWrapper {
private final MapperGeneratorContext context;
private final TypeElement mapperInterface;
private final SourceWrapper source;
private final IgnoreMissing ignoreMissing;

public MapperWrapper(MapperGeneratorContext context, TypeElement mapperInterface) {
this.context = context;
Expand All @@ -55,6 +62,18 @@ public MapperWrapper(MapperGeneratorContext context, TypeElement mapperInterface
ignoreFieldsWrapper = new IgnoreFieldsWrapper(context, mapperInterface, ignoreFieldsParam);
configuration = SourceConfiguration.buildFrom(mapper, ignoreFieldsWrapper);


IgnoreMissing missing = IgnoreMissing.valueOf(mapper.getAsString(WITH_IGNORE_MISSING));
if (missing == DEFAULT) {
if (configuration.isIgnoreMissingProperties()){
ignoreMissing = ALL;
} else {
ignoreMissing = NONE;
}
} else {
ignoreMissing = missing;
}

fields = new FieldsWrapper(context, mapperInterface, mapper);
mappingRegistry.fields(fields);

Expand Down Expand Up @@ -136,7 +155,7 @@ public CustomMapperWrapper customMappers() {

/**
* Method used to collect dependencies from mapping methods that need fields and constructor init
* @param maps
* @param maps maps annotation we want to collect
*/
public void collectMaps(MapsWrapper maps) {
customMappers.addFields(maps.customMapperFields());
Expand All @@ -154,4 +173,8 @@ public String[] sourceConstructorArgs() {
public void emitSourceAssigns(JavaWriter writer) throws IOException {
source.emitAssigns(writer);
}

public IgnoreMissing ignoreMissing(){
return ignoreMissing;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
*/
package fr.xebia.extras.selma.codegen;

import fr.xebia.extras.selma.IgnoreMissing;
import fr.xebia.extras.selma.Maps;

import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import java.util.List;

import static fr.xebia.extras.selma.IgnoreMissing.DEFAULT;

/**
* Created by slemesle on 10/11/14.
*/
Expand All @@ -30,8 +33,9 @@ public class MapsWrapper {
public static final String WITH_CUSTOM_FIELDS = "withCustomFields";
public static final String WITH_IGNORE_FIELDS = "withIgnoreFields";
public static final String WITH_ENUMS = "withEnums";
public static final String IGNORE_MISSING_PROPERTIES = "ignoreMissingProperties";
//private final IgnoreFieldsWrapper ignoreFields;
public static final String WITH_IGNORE_MISSING = "withIgnoreMissing";


private final FieldsWrapper customFields;
private final AnnotationWrapper maps;
private final MappingRegistry registry;
Expand All @@ -41,6 +45,7 @@ public class MapsWrapper {
private final MapperWrapper mapperWrapper;
private final MapperGeneratorContext context;
private final CustomMapperWrapper customMapper;
private final IgnoreMissing ignoreMissing;
private boolean ignoreMissingProperties;

public MapsWrapper(MethodWrapper method, MapperWrapper mapperWrapper) {
Expand All @@ -62,12 +67,14 @@ public MapsWrapper(MethodWrapper method, MapperWrapper mapperWrapper) {
customMapper = new CustomMapperWrapper(mapperWrapper.customMappers(), maps, context);
registry.customMappers(customMapper);

if (mapperWrapper.isIgnoreMissingProperties()){
ignoreMissingProperties = true;
} else if (maps != null && maps.getAsBoolean(IGNORE_MISSING_PROPERTIES)) {
ignoreMissingProperties = true;
//TODO remove this code in 0.11
ignoreMissingProperties = mapperWrapper.isIgnoreMissingProperties();

IgnoreMissing missing = (maps == null ? DEFAULT : IgnoreMissing.valueOf(maps.getAsString(WITH_IGNORE_MISSING)));
if (missing == DEFAULT){
ignoreMissing = mapperWrapper.ignoreMissing();
} else {
ignoreMissingProperties = false;
ignoreMissing = missing;
}

}
Expand Down Expand Up @@ -111,4 +118,8 @@ public boolean isIgnoreMissingProperties() {
public List<TypeElement> customMapperFields() {
return customMapper.mapperFields();
}

public IgnoreMissing ignoreMissing(){
return ignoreMissing;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2013 Séven Le Mesle
*
* 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 fr.xebia.extras.selma.codegen.compiler;

import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import java.util.HashSet;

/**
*
*/
public class CompilerMessageRegistry {

private final HashSet<KindElementPair> messageSet;

public CompilerMessageRegistry() {
messageSet = new HashSet<KindElementPair>();
}


public boolean hasMessageFor(Diagnostic.Kind kind, Element element){
KindElementPair pair = new KindElementPair(kind, element);

if (messageSet.contains(pair)){
return true;
} else {
messageSet.add(pair);
return false;
}
}


private class KindElementPair {

final Diagnostic.Kind kind;
final Element element;

public KindElementPair(Diagnostic.Kind kind, Element element) {
this.kind = kind;
this.element = element;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

KindElementPair that = (KindElementPair) o;

if (!element.equals(that.element)) return false;
if (kind != that.kind) return false;

return true;
}

@Override
public int hashCode() {
int result = kind.hashCode();
result = 31 * result + element.hashCode();
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public class BeanMapperIT extends IntegrationTestBase {
public void beanMapper_should_map_properties()throws Exception{


System.out.println(System.getProperty("java.classpath"));
BeanMapper mapper = Selma.getMapper(BeanMapper.class);

PersonIn personIn = new PersonIn();
Expand Down
Loading

0 comments on commit 88ed2fa

Please sign in to comment.