Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Feature #137: Implement withIoC={CDI, CDI_SINGLETON} options #141

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void emitCustomMappersFields(JavaWriter writer, boolean assign) throws IOExcepti
writer.emitJavadoc("Custom Mapper setter for " + field);

EnumSet<Modifier> modifiers = EnumSet.of(PUBLIC, FINAL);
if (ioC == IoC.CDI) {
if (ioC == IoC.CDI || ioC == IoC.CDI_SINGLETON || ioC == IoC.CDI_APPLICATION_SCOPED) {
modifiers = EnumSet.of(PUBLIC);
}
writer.beginMethod("void", "setCustomMapper" + customMapperField.getSimpleName(),modifiers, customMapperField.asType().toString(), "mapper");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public void emitFactoryFields(JavaWriter writer, boolean assign) throws IOExcept
writer.emitJavadoc("Factory setter for " + field);

EnumSet<Modifier> modifiers = EnumSet.of(PUBLIC, FINAL);
if (ioC == IoC.CDI) {
if (ioC == IoC.CDI || ioC == IoC.CDI_SINGLETON || ioC == IoC.CDI_APPLICATION_SCOPED) {
modifiers = EnumSet.of(PUBLIC);
}
writer.beginMethod("void", "setFactory" + factoryField.getSimpleName(), modifiers, factoryField.asType().toString(), "_factory");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*-
* Copyright 2013 Xebia and Séven Le Mesle
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -16,26 +16,34 @@
*/
package fr.xebia.extras.selma.codegen;

import com.squareup.javawriter.JavaWriter;
import fr.xebia.extras.selma.SelmaConstants;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PUBLIC;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.util.*;

import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PUBLIC;

/**
* Handles the generation of the Mapper class
*/
public class MapperClassGenerator {
import com.squareup.javawriter.JavaWriter;

import fr.xebia.extras.selma.SelmaConstants;

/** Handles the generation of the Mapper class */
public class MapperClassGenerator {

public static final String GENERATED_BY_SELMA = "GENERATED BY S3LM4";
private final Collection<ExecutableElement> mapperMethods;
private final String origClasse;
Expand All @@ -45,77 +53,75 @@ public class MapperClassGenerator {
private final MapperWrapper mapper;
private final DeclaredType declaredType;
private List<MethodWrapper> methodWrappers;

public MapperClassGenerator(String classe, Collection<ExecutableElement> executableElements, ProcessingEnvironment processingEnvironment) {

public MapperClassGenerator(String classe, Collection<ExecutableElement> executableElements,
ProcessingEnvironment processingEnvironment) {
this.origClasse = classe;
this.mapperMethods = executableElements;
this.processingEnv = processingEnvironment;
context = new MapperGeneratorContext(processingEnv);

element = context.getTypeElement(classe);
declaredType = (DeclaredType) element.asType();

mapper = new MapperWrapper(context, element);
context.setWrapper(mapper);

methodWrappers = validateTypes();

}



private List<MethodWrapper> validateTypes() {

List<MethodWrapper> res = new ArrayList<MethodWrapper>();

for (ExecutableElement mapperMethod : mapperMethods) {

MethodWrapper methodWrapper = new MethodWrapper(mapperMethod, declaredType, context);
res.add(methodWrapper);

mapper.buildEnumForMethod(methodWrapper);

InOutType inOutType = methodWrapper.inOutType();
if (inOutType.differs()) {
MappingBuilder builder = MappingBuilder.getBuilderFor(context, inOutType);

if ((inOutType.in().getKind() != TypeKind.DECLARED || inOutType.out().getKind() != TypeKind.DECLARED) && builder == null) {
context.error(mapperMethod, "In type : %s and Out type : %s differs and this kind of conversion is not supported here", inOutType.in(), inOutType.out());
context.error(mapperMethod, "In type : %s and Out type : %s differs and this kind of conversion is not supported here",
inOutType.in(), inOutType.out());
} else {
context.mappingMethod(methodWrapper.inOutType(), methodWrapper.getSimpleName());
}
}

}

return res;
}

public void build() throws IOException {

boolean firstMethod = true;
JavaWriter writer = null;
JavaFileObject sourceFile = null;

final TypeElement type = processingEnv.getElementUtils().getTypeElement(origClasse);
final String packageName = getPackage(type).getQualifiedName().toString();
final String strippedTypeName = strippedTypeName(type.getQualifiedName().toString(), packageName);

final String adapterName = new StringBuilder(packageName)
.append('.')
.append(strippedTypeName.replace('.', '_'))

final String adapterName = new StringBuilder(packageName).append('.').append(strippedTypeName.replace('.', '_'))
.append(SelmaConstants.MAPPER_CLASS_SUFFIX).toString();

final List<MapperMethodGenerator> methodGenerators = new ArrayList<MapperMethodGenerator>();



for (MethodWrapper mapperMethod : methodWrappers) {

if (firstMethod) {
sourceFile = processingEnv.getFiler().createSourceFile(adapterName, type);
writer = new JavaWriter(sourceFile.openWriter());

writer.emitSingleLineComment(GENERATED_BY_SELMA);
writer.emitPackage(packageName);
writer.emitEmptyLine();

switch (mapper.ioC) {
case SPRING:
if (mapper.ioCServiceName != "") {
Expand All @@ -124,44 +130,55 @@ public void build() throws IOException {
writer.emitAnnotation("org.springframework.stereotype.Service");
}
break;

case CDI:
writer.emitAnnotation("javax.inject.Named");
break;

case CDI_SINGLETON:
writer.emitAnnotation("javax.inject.Named");
writer.emitAnnotation("javax.inject.Singleton");
break;

case CDI_APPLICATION_SCOPED:
writer.emitAnnotation("javax.enterprise.context.ApplicationScoped");
break;

default:
break;
}

openClassBlock(writer, adapterName, strippedTypeName);
writer.emitEmptyLine();
firstMethod = false;
}
// Prepare mapping method
// Prepare mapping method
methodGenerators.add(new MapperMethodGenerator(writer, mapperMethod, mapper));
}

// Build mapping methods
// Build mapping methods
for (MapperMethodGenerator mapperMethodGenerator : methodGenerators) {
mapperMethodGenerator.build(methodGenerators);

mapper.collectMaps(mapperMethodGenerator.maps());

writer.emitEmptyLine();
}

buildConstructor(writer, adapterName);

writer.endType();
writer.close();

mapper.reportUnused();
}

private void openClassBlock(JavaWriter writer, String adapterName, String strippedTypeName) throws IOException {
String[] interfaceName = new String[]{strippedTypeName};
String[] interfaceName = new String[] { strippedTypeName };
String className = strippedTypeName;
Set<Modifier> modifiers = EnumSet.of(PUBLIC);
if (mapper.isAbstractClass()) {
interfaceName = new String[]{};
interfaceName = new String[] {};
} else {
className = null;
}
Expand All @@ -170,38 +187,36 @@ private void openClassBlock(JavaWriter writer, String adapterName, String stripp
}
writer.beginType(adapterName, "class", modifiers, className, interfaceName);
}

private void buildConstructor(JavaWriter writer, String adapterName) throws IOException {
mapper.emitSourceFields(writer);
mapper.emitCustomMappersFields(writer, false);
mapper.emitFactoryFields(writer, false);

// First build default constructor
writer.emitEmptyLine();
writer.emitJavadoc("Single constructor");
writer.beginMethod(null, adapterName, EnumSet.of(PUBLIC), mapper.sourceConstructorArgs());

// assign source in parameters to instance fields
mapper.emitSourceAssigns(writer);

// Add customMapper instantiation
mapper.emitCustomMappersFields(writer, true);
mapper.emitFactoryFields(writer, true);

writer.endMethod();
writer.emitEmptyLine();
}



public PackageElement getPackage(Element type) {
while (type.getKind() != ElementKind.PACKAGE) {
type = type.getEnclosingElement();
}
return (PackageElement) type;
}

public String strippedTypeName(String type, String packageName) {
return type.substring(packageName.isEmpty() ? 0 : packageName.length() + 1);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*-
* Copyright 2013 Xebia and 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.it.custom.mapper;

import fr.xebia.extras.selma.IoC;
import fr.xebia.extras.selma.Mapper;
import fr.xebia.extras.selma.beans.Book;
import fr.xebia.extras.selma.beans.BookDTO;

@Mapper(withIoC = IoC.CDI)
public interface CustomCdiMapperInMaps {

public Book asBook(BookDTO source);

public BookDTO asBookDto(Book source);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*-
* Copyright 2013 Xebia and 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.it.custom.mapper;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;

import org.junit.Test;

import fr.xebia.extras.selma.Selma;
import fr.xebia.extras.selma.it.utils.Compile;
import fr.xebia.extras.selma.it.utils.IntegrationTestBase;

@Compile(withClasses = CustomCdiMapperInMaps.class)
public class CustomCdiMapperInMapsIT extends IntegrationTestBase {

@Test
public void given_cdi_mapper_should_be_annotated_with_Inject() {

final CustomCdiMapperInMaps mapper = Selma.getMapper(CustomCdiMapperInMaps.class);
assertThat(mapper.getClass().getAnnotation(javax.inject.Named.class), notNullValue());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*-
* Copyright 2013 Xebia and 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.it.custom.mapper;

import fr.xebia.extras.selma.IoC;
import fr.xebia.extras.selma.Mapper;
import fr.xebia.extras.selma.beans.Book;
import fr.xebia.extras.selma.beans.BookDTO;

@Mapper(withIoC = IoC.CDI_SINGLETON)
public interface CustomCdiSingletonMapperInMaps {

public Book asBook(BookDTO source);

public BookDTO asBookDto(Book source);

}
Loading