Skip to content

Commit

Permalink
code generation has been decoupled
Browse files Browse the repository at this point in the history
  • Loading branch information
avurro committed Jul 22, 2015
1 parent 2ac8b47 commit 0082329
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 90 deletions.
8 changes: 7 additions & 1 deletion JMapper Framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@
</build>

<dependencies>


<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.10</version>
</dependency>

<dependency>
<groupId>com.googlecode.jmapper-framework</groupId>
<artifactId>jmapper-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package com.googlecode.jmapper;

import static com.googlecode.jmapper.generation.MapperBuilder.from;
import javassist.NotFoundException;
import static com.googlecode.jmapper.util.GeneralUtility.isNull;

import com.googlecode.jmapper.api.IJMapper;
import com.googlecode.jmapper.api.enums.MappingType;
import com.googlecode.jmapper.api.enums.NullPointerControl;
Expand Down Expand Up @@ -401,10 +401,10 @@ public JMapper(final Class<D> destination,final Class<S> source,final ChooseCon
.analyzing(config)
.presentIn(xmlPath));

}catch (Exception e) { JmapperLog.ERROR(e); }
}catch (Throwable e) { JmapperLog.ERROR(e); }
}

private IMapper<D,S> createMapper(MapperBuilder mapper) throws NotFoundException, Exception{
private IMapper<D,S> createMapper(MapperBuilder mapper) throws Throwable{

Class<IMapper<D,S>> mapperClass = mapper.exist()?mapper.<D,S>get()
:mapper.<D,S>generate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private JmapperLog(){}
*
* @param e exception to handle
*/
public static void ERROR(Exception e) throws JMapperException{
public static void ERROR(Throwable e) throws JMapperException{
logger.error("{}: {}",e.getClass().getSimpleName(),e.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright (C) 2012 - 2015 Alessandro Vurro.
*
* 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 com.googlecode.jmapper.generation;

import java.util.List;

import com.googlecode.jmapper.generation.beans.Constructor;
import com.googlecode.jmapper.generation.beans.Method;

/**
* Implements this interface if you want define a custom code generation.
*
* @author Alessandro Vurro
*
*/
public interface ICodeGenerator {

/**
* Generates a class with this parameters.
* @param clazzName class name
* @param constructors list of costructors
* @param methods list of methods
* @return the generated class
* @throws Throwable
*/
Class<?> generate(String clazzName,List<Constructor> constructors,List<Method> methods) throws Throwable;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* Copyright (C) 2012 - 2015 Alessandro Vurro.
*
* 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 com.googlecode.jmapper.generation;

import java.util.List;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;

import com.googlecode.jmapper.IMapper;
import com.googlecode.jmapper.config.Error;
import com.googlecode.jmapper.generation.beans.Constructor;
import com.googlecode.jmapper.generation.beans.Method;

/**
* Javassist implementation.
*
* @author Alessandro Vurro
*
*/
public class JavassistGenerator implements ICodeGenerator {

public Class<?> generate(String clazzName, List<Constructor> constructors,
List<Method> methods) throws Throwable {
try{
ClassPool cp = ClassPool.getDefault();
// create the class
CtClass cc = cp.makeClass(clazzName);

// adds the interface
cc.addInterface(cp.get(IMapper.class.getName()));

// adds constructor
for (Constructor constructor : constructors) {
// create constructor
CtConstructor ctConstructor = new CtConstructor(toCtClass(constructor.getParameters()), cc);
// set body constructor
ctConstructor.setBody(constructor.getBody());
// add constructor to CtClass
cc.addConstructor(ctConstructor);
}

// adds methods
for (Method method : methods) {
try{// create method
CtMethod ctMethod = new CtMethod(toCtClass(method.getReturnType())[0],method.getName(), toCtClass(method.getParameters()), cc);
// set body method
ctMethod.setBody(method.getBody());
// add method to CtClass
cc.addMethod(ctMethod); }
catch (CannotCompileException e) { Error.bodyContainsIllegalCode(method,e); }
}

Class<?> generetedClass = cc.toClass();
cc.defrost();
return generetedClass;
}catch (NotFoundException e) { Error.notFoundException(e); }
return null;
}

/**
* This method transforms classes in CtClass[]
* @param classes
* @return CtClass[] version of classes parameter
* @throws Exception in case of not found class
*/
private static CtClass[] toCtClass(Class<?>... classes) throws Exception{
ClassPool cp = ClassPool.getDefault();
CtClass[] parameters = new CtClass[classes.length];
for(int i=0;i<classes.length;i++)
parameters[i]=cp.get(classes[i].getName());

return parameters;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

import static com.googlecode.jmapper.generation.MapperGenerator.generateMapperClass;
import static com.googlecode.jmapper.util.ClassesManager.mapperClassName;
import static com.googlecode.jmapper.xml.XmlBuilder.loadXml;
import static com.googlecode.jmapper.util.GeneralUtility.isNull;
import static com.googlecode.jmapper.xml.XmlBuilder.loadXml;

import java.util.HashSet;
import java.util.Set;
Expand All @@ -28,8 +28,6 @@
import com.googlecode.jmapper.enums.ChooseConfig;
import com.googlecode.jmapper.generation.beans.Method;

import javassist.NotFoundException;

/**
* MapperBuilder increases the readability of the code to retrieve the
* parameters necessary to create or find a new IMapper class. <br>
Expand Down Expand Up @@ -75,11 +73,9 @@ public <D, S> Class<IMapper<D, S>> get() {
* @param <D> Destination Class
* @param <S> Source Class
* @return the generated mapper class
* @throws NotFoundException if class doesn't exists
* @throws Exception in other cases such as illegalcode
* @throws Throwable
* */
public <D, S> Class<IMapper<D, S>> generate() throws NotFoundException,
Exception {
public <D, S> Class<IMapper<D, S>> generate() throws Throwable {

// if defined the dynamic methods are treated differently
// a reference to this list is passed to the MapperConstructor and filled recursively
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,15 @@
import static com.googlecode.jmapper.util.GeneralUtility.list;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;

import org.reflections.Reflections;

import com.googlecode.jmapper.IMapper;
import com.googlecode.jmapper.config.Error;
import com.googlecode.jmapper.generation.beans.Constructor;
import com.googlecode.jmapper.generation.beans.Method;

Expand All @@ -52,10 +47,9 @@ public class MapperGenerator {
* @param mapping parameter that containts the mappings
* @param dynamicMethods dynamic methods to add
* @return a new instance of IMapper interface, following the mappingBuilder specifications
* @throws NotFoundException if class to generate doesn't exists
* @throws Exception other cases
* @throws Throwable
*/
public static Class<?> generateMapperClass(MapperConstructor mapping, Set<Method> dynamicMethods) throws NotFoundException, Exception{
public static Class<?> generateMapperClass(MapperConstructor mapping, Set<Method> dynamicMethods) throws Throwable{

// adds empty constructor
ArrayList<Constructor> constructors = list(new Constructor());
Expand All @@ -71,69 +65,13 @@ public static Class<?> generateMapperClass(MapperConstructor mapping, Set<Method
.setBody("{"+mappings.get(method.getName())+"}"));

String className = mapping.getMapperName();
return generateClass(className, constructors, methods);
}

/**
* Generates the class starting from some data.
*
* @param clazzName The class that will be generated
* @param superClazzName superClass of clazzName
* @param constructors constructors of the class that will be generated
* @param methods methods of the class that will be generated
* @return the generated Class
* @throws Exception in case of illegal code
*/
private static Class<?> generateClass(String clazzName,List<Constructor> constructors,List<Method> methods) throws Exception {
try{
ClassPool cp = ClassPool.getDefault();
// create the class
CtClass cc = cp.makeClass(clazzName);

// adds the interface
cc.addInterface(cp.get(IMapper.class.getName()));

// adds constructor
for (Constructor constructor : constructors) {
// create constructor
CtConstructor ctConstructor = new CtConstructor(
toCtClass(constructor.getParameters()), cc);
// set body constructor
ctConstructor.setBody(constructor.getBody());
// add constructor to CtClass
cc.addConstructor(ctConstructor);
}

// adds methods
for (Method method : methods) {
try{// create method
CtMethod ctMethod = new CtMethod(toCtClass(method.getReturnType())[0],method.getName(), toCtClass(method.getParameters()), cc);
// set body method
ctMethod.setBody(method.getBody());
// add method to CtClass
cc.addMethod(ctMethod); }
catch (CannotCompileException e) { Error.bodyContainsIllegalCode(method,e); }
}

Class<?> generetedClass = cc.toClass();
cc.defrost();
return generetedClass;
}catch (NotFoundException e) { Error.notFoundException(e); }
return null;
}

/**
* This method transforms classes in CtClass[]
* @param classes
* @return CtClass[] version of classes parameter
* @throws Exception in case of not found class
*/
private static CtClass[] toCtClass(Class<?>... classes) throws Exception{
ClassPool cp = ClassPool.getDefault();
CtClass[] parameters = new CtClass[classes.length];
for(int i=0;i<classes.length;i++)
parameters[i]=cp.get(classes[i].getName());

return parameters;
Set<Class<? extends ICodeGenerator>> generators = new Reflections("com.googlecode.jmapper.generation").getSubTypesOf(ICodeGenerator.class);

ICodeGenerator generator = generators.isEmpty()? new JavassistGenerator():generators.iterator().next().newInstance();

return generator.generate(className, constructors, methods);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,8 @@ public void loadStructures(Set<Method> dynamicMethodsToWrite) {
conversionHandler.load(conversionAnalyzer)
.from(sourceMappedField).to(destinationMappedField);

if(conversionHandler.toBeCreated()){
Method method = conversionHandler.loadMethod();
System.out.println(method.getBody());
dynamicMethodsToWrite.add(method);
}
if(conversionHandler.toBeCreated())
dynamicMethodsToWrite.add(conversionHandler.loadMethod());

operation.setConversionMethod(conversionHandler.getMethod())
.setMemberShip (conversionHandler.getMembership());
Expand Down

0 comments on commit 0082329

Please sign in to comment.