package org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.eproto;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import org.ebayopensource.turmeric.runtime.binding.exception.SerializationException;
import org.ebayopensource.turmeric.runtime.common.impl.utils.LogManager;
import org.ebayopensource.turmeric.tools.codegen.CodeGenContext;
import org.ebayopensource.turmeric.tools.codegen.exception.CodeGenFailedException;
import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufMessage;
import org.ebayopensource.turmeric.tools.codegen.fastserformat.protobuf.model.ProtobufSchema;
import org.ebayopensource.turmeric.tools.codegen.util.CodeGenUtil;
import org.ebayopensource.turmeric.tools.codegen.util.ContextClassLoaderUtil;
import com.google.protobuf.ByteString;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCatchBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JConditional;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JForEach;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JPrimitiveType;
import com.sun.codemodel.JTryBlock;
import com.sun.codemodel.JType;
public class EProtoGenerator extends BaseEProtoGenerator {
private static final String BUILDERMEMBER = "m_Builder";
private static final String JAXBPOJOCLASS = "JAXBPOJOCLASS";
private static final String GETENUMMETHOD = "getEnum";
private Map<String, JAXB2EJProtoMapping> jaxbProtoMapping;
private List<Class<?>> wrapperClasses;
private static Logger s_logger = LogManager.getInstance(EProtoGenerator.class);
private static EProtoGenerator s_EProtoGenerator = new EProtoGenerator();
private Logger getLogger() {
return s_logger;
}
private EProtoGenerator() {}
public static EProtoGenerator getInstance() {
return s_EProtoGenerator;
}
/**
* Entry method for the EProto generation.
*
* Generates EProto class files for all the types available in the model except for abstract types.
* The EProto classes acts as the mediator between protoformat and the JAXB objects and helps in serialization/deserialization.
* EProto classes has all the getters in the super class (JAXB class) overridden with logic to work with protobuf. In addition
* to the getters, a newInstance method gives the JProto object given a POJO object.
*/
public void generate(ProtobufSchema protobufSchema,
CodeGenContext codeGenContext) throws CodeGenFailedException{
if(protobufSchema == null){
throw new CodeGenFailedException("EProto generation Failed, the proto model is empty and" +
" hence cannot proceed with EProto generation ");
}
populateMapping(protobufSchema);
for(Entry<String, JAXB2EJProtoMapping> mapEntry : jaxbProtoMapping.entrySet()){
String jaxbName = mapEntry.getKey();
Class<?> jaxbPojoClass = ContextClassLoaderUtil.loadRequiredClass(jaxbName);
if(Modifier.isAbstract(jaxbPojoClass.getModifiers()))
continue;
else if(jaxbPojoClass.isEnum()){
/**
* EProto for ENUM is a little different and hence we have a seperate generator for those types.
*/
EnumEProtoGenerator generator = EnumEProtoGenerator.getInstance();
generator.createJCodeModel(mapEntry.getValue(), jaxbPojoClass, codeGenContext);
getLogger().log(Level.INFO, "Successfully generated EProto for " + jaxbName);
continue;
}
JAXB2EJProtoMapping mapValue = mapEntry.getValue();
EProtoContext protoContext = getPojoInfo(mapValue.getEprotoName(),
mapValue.getComplexTypeName(),
mapValue.getJprotoName(),
mapValue.getJaxbName());
protoContext.setRootType(mapValue.isRootType());
createJCodeModel(protoContext, codeGenContext);
getLogger().log(Level.INFO, "Successfully generated EProto for " + jaxbName);
}
}
/**
* Creates a context that would be used during the EProto generation. The context would contain
* Message name, JAXB name, JProto name, EProto name that are obtained from the Proto Model
* populated in the previous step.
* Also populates the 8 wrapper classes for the primitve types in a list
* which would be used in following methods
*/
private void populateMapping(ProtobufSchema protobufSchema){
getLogger().log(Level.INFO, "Populating the map with the information from proto model generation ");
jaxbProtoMapping = new HashMap<String, JAXB2EJProtoMapping>();
wrapperClasses = new ArrayList<Class<?>>();
List<ProtobufMessage> protoMessage = protobufSchema.getMessages();
for (ProtobufMessage protobufMessage : protoMessage) {
JAXB2EJProtoMapping protoMapping = new JAXB2EJProtoMapping();
protoMapping.setRootType(protobufMessage.isRootType());
protoMapping.setComplexTypeName(protobufMessage.getMessageName());
protoMapping.setEprotoName(protobufMessage.getEprotoClassName());
protoMapping.setJaxbName(protobufMessage.getJaxbClassName());
protoMapping.setJprotoName(protobufMessage.getJprotoClassName());
jaxbProtoMapping.put(protobufMessage.getJaxbClassName(), protoMapping);
}
wrapperClasses.add(Byte.class);
wrapperClasses.add(Short.class);
wrapperClasses.add(Integer.class);
wrapperClasses.add(Long.class);
wrapperClasses.add(Float.class);
wrapperClasses.add(Double.class);
wrapperClasses.add(Character.class);
wrapperClasses.add(Boolean.class);
wrapperClasses.add(String.class);
wrapperClasses.add(BigDecimal.class);
wrapperClasses.add(BigInteger.class);
wrapperClasses.add(QName.class);
getLogger().log(Level.FINE, "Proto model details in the map \n" + jaxbProtoMapping.toString());
}
public void createJCodeModel(EProtoContext info,
CodeGenContext codeGenContext) throws CodeGenFailedException{
getLogger().log(Level.FINE, "Starting codegeneration for " + info.getFullyQualifiedEProtoName());
JCodeModel codeModel = new JCodeModel();
JDefinedClass targetClass = createNewClass(codeModel, info.getFullyQualifiedEProtoName());
JClass basePOJOClazz = getJClass(info.getFullyQualifiedName(), codeModel);
extend(targetClass, basePOJOClazz);
addFieldsAndConstructor(info, targetClass, codeModel);
addGetters(info, targetClass, codeModel);
if(info.isRootType()){
addParseFrom(info, targetClass, codeModel);
addGetDeserializedJProtoObject(info, targetClass, codeModel);
}
addGetJProtoBuilderObject(info, targetClass, codeModel);
addNewInstanceMethod(info, targetClass, codeModel);
generateJavaFile(codeModel, codeGenContext.getJavaSrcDestLocation());
}
/**
* Adds the fields and COnstructor for the EProto class to be generated.
* the fields are
*
* 1) a constant containing fully qualified POJO class name
* 2) JProto builder member
*
* and the constructor with the JProto as the argument
*/
private void addFieldsAndConstructor(EProtoContext info, JDefinedClass targetClass, JCodeModel codeModel)
throws CodeGenFailedException{
//--------------------------------------------------------------------------------
// Creates
//
// private final static String JAXBPOJOCLASS = <fullyQualifiedPOJOClassname>;
// private<JProtoMessageName>.Builder m_Builder = null;
//
// public <EProtoClassName>(<JProtoMessageName> errormessage) {
// m_Builder = <JProtoMessageName>.newBuilder((errormessage));
// }
//--------------------------------------------------------------------------------
getLogger().log(Level.FINE, "Adding constructors and fields for " + info.getFullyQualifiedEProtoName());
JClass stringJClass = getJClass(String.class, codeModel);
Class<?> something = ContextClassLoaderUtil.loadRequiredClass(info.getBuilderClass());
JClass builderClass = getJClass(something, codeModel);
targetClass.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, stringJClass, JAXBPOJOCLASS,
JExpr.lit(info.getFullyQualifiedName()));
targetClass.field(JMod.PRIVATE, builderClass, BUILDERMEMBER, JExpr._null());
String newBuilderMethod = "newBuilder";
String consArg = info.getComplexTypeName().toLowerCase();
JMethod constructorWithArgs = targetClass.constructor(JMod.PUBLIC);
JClass protoMessageClass = getJClass(info.getFullyQualifiedJProtoMessageName(), codeModel);
constructorWithArgs.param(protoMessageClass, consArg);
JBlock constructorWithArgsBody = constructorWithArgs.body();
JInvocation parseFromInvoker = protoMessageClass.staticInvoke(newBuilderMethod);
parseFromInvoker.arg(JExpr.direct(consArg));
constructorWithArgsBody.assign(JExpr.ref(BUILDERMEMBER), parseFromInvoker);
}
/**
* Generates Getters methods for all the fields defined in the POJO classes. The getters in the
* POJO classes are overridden and the logic involves in getting POJO information from the
* underlying proto information. The getters logic will be different for different return types namely
* 1)primitive types
* 2)String
* 3)Date
* 4)Enum
* 5)User defined Complex type
* 6)List of types (complex and simple)
*/
private void addGetters(EProtoContext info, JDefinedClass targetClass, JCodeModel codeModel)
throws CodeGenFailedException{
getLogger().log(Level.FINE, "Adding getter method for " + info.getFullyQualifiedEProtoName());
List<Method> getterMethods = info.getMethods();
for (Method method : getterMethods) {
JMethod addedMethod = overrideGetter(method, targetClass, codeModel);
getLogger().log(Level.FINE, "Adding " + method.getName() + " getter method of the class "
+ info.getFullyQualifiedEProtoName());
// To add @Override to all the getters.
addedMethod.annotate(Override.class);
String fieldName = info.getGetterToFields().get(method.getName());
JBlock methodBody = addedMethod.body();
if(method.getReturnType().isPrimitive()){
primitiveMethodLogic(info, method, addedMethod, methodBody, codeModel, fieldName);
}
else if(wrapperClasses.contains(method.getReturnType())){
checkMembersForNull(methodBody, fieldName, codeModel, false);
stringMethodLogic(info, method, addedMethod, methodBody, codeModel, false, fieldName);
}
else if(method.getReturnType().equals(XMLGregorianCalendar.class)
|| method.getReturnType().equals(Duration.class)){
checkMembersForNull(methodBody, fieldName, codeModel, false);
dateMethodLogic(info, method, addedMethod, methodBody, codeModel, fieldName);
}
else if(method.getReturnType().isEnum()){
checkMembersForNull(methodBody, fieldName, codeModel, false);
addComplexTypeMethodLogic(info, method, addedMethod, methodBody, codeModel, true, fieldName);
}
else if(method.getReturnType().isArray()){
checkMembersForNull(methodBody, fieldName, codeModel, false);
stringMethodLogic(info, method, addedMethod, methodBody, codeModel, true, fieldName);
}
else{
if(method.getReturnType().equals(List.class)){
checkMembersForNull(methodBody, fieldName, codeModel, true);
addListMethod(info, method, addedMethod, methodBody, codeModel, targetClass, fieldName);
}
else{
checkMembersForNull(methodBody, fieldName, codeModel, false);
addComplexTypeMethodLogic(info, method, addedMethod, methodBody, codeModel, false, fieldName);
}
}
}
}
private void checkMembersForNull(JBlock methodBody, String fieldName, JCodeModel codeModel, boolean isList){
JFieldRef fieldNameRef = JExpr.ref(fieldName);
JConditional ifValNullCondition = null;
if(isList){
JExpression isEmptyExpression = fieldNameRef.invoke("isEmpty").not();
ifValNullCondition = methodBody._if(fieldNameRef.ne(JExpr._null()).cand(isEmptyExpression));
}
else
ifValNullCondition = methodBody._if(fieldNameRef.ne(JExpr._null()));
ifValNullCondition._then()._return(fieldNameRef);
}
private JMethod overrideGetter(Method method, JDefinedClass targetClass,
JCodeModel codeModel) throws CodeGenFailedException{
JType returnType = getJType(method.getGenericReturnType(), codeModel);
JMethod eachMethod = addMethod(targetClass, method.getName(), method.getModifiers() , returnType);
return eachMethod;
}
private void addHasFieldCheck(JFieldRef valueFieldRef, JExpression actualExpression,
JBlock methodBody, String hasFieldMethodName) {
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JExpression hasFieldExpression = builderField.invoke(hasFieldMethodName);
JConditional ifServiceLocCondition = methodBody._if(hasFieldExpression);
ifServiceLocCondition._then().assign(valueFieldRef, actualExpression);
}
private void addGetFieldCountForListCheck(JBlock methodBody, JExpression pojoListRef, String getParamCountMethodName) {
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JExpression hasFieldExpression = builderField.invoke(getParamCountMethodName).gt(JExpr.lit(0)).not();
JConditional ifServiceLocCondition = methodBody._if(hasFieldExpression);
ifServiceLocCondition._then()._return(pojoListRef);
}
/**
* Getter method for primitive types like int, boolean, long etc. Straight forward logic.
* No null check, no usage of EProto classes.
* Generates the following construct.
*/
private void primitiveMethodLogic(EProtoContext info, Method method, JMethod addedMethod,
JBlock methodBody, JCodeModel codeModel, String filedName){
//--------------------------------------------------------------------------------
// Creates
//
// @Override
// public <primitive type> get<MethodName>() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, fieldName);
// return (<Boxed type> m_Builder.getField((fieldDescriptor)));
// }
//--------------------------------------------------------------------------------
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JType returnJType = getJType(method.getGenericReturnType(), codeModel);
String getterMethodName = getGetterMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
JPrimitiveType primitiveType = (JPrimitiveType) returnJType;
JType wrapperType = returnJType.boxify();
JExpression actualParamExpr = primitiveType.unwrap(JExpr.cast(wrapperType, getFieldInvocation));
methodBody._return(actualParamExpr);
}
/**
* Getter method for String types. Straight forward logic. No null check, no usage of EProto classes.
* Generates the following construct.
*/
private void stringMethodLogic(EProtoContext info, Method method, JMethod addedMethod, JBlock methodBody,
JCodeModel codeModel, boolean isArray, String filedName){
//--------------------------------------------------------------------------------
// Creates
//
// @Override
// public String get<MethodName>() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, fieldName);
// return ((String) m_Builder.getField((fieldDescriptor)));
// }
//--------------------------------------------------------------------------------
String valueVariable = "protobufTempValue";
Class<?> returnType = method.getReturnType();
JClass stringClass = getJClass(String.class, codeModel);
JClass integerClass = getJClass(Integer.class, codeModel);
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JFieldRef valueVariableField = JExpr.ref(valueVariable);
JType returnJType = getJType(method.getGenericReturnType(), codeModel);
String getterMethodName = getGetterMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
String hasFieldMethodName = getHasFieldMethodNameForFields(info, method);
JExpression actualParamExpr = null;
if(returnType.equals(BigInteger.class) || returnType.equals(BigDecimal.class)
|| returnType.equals(QName.class)){
actualParamExpr = JExpr.cast(stringClass, getFieldInvocation);
methodBody.decl(stringClass, valueVariable, JExpr._null());
addHasFieldCheck(valueVariableField, actualParamExpr, methodBody, hasFieldMethodName);
JClass bigJClass = getJClass(returnType, codeModel);
actualParamExpr = JExpr._new(bigJClass).arg(valueVariableField);
addEqualsNullCondition(methodBody, valueVariableField);
}
else if(returnType.equals(Short.class) || returnType.equals(Byte.class)){
actualParamExpr = JExpr.cast(integerClass, getFieldInvocation);
methodBody.decl(integerClass, valueVariable, JExpr._null());
addHasFieldCheck(valueVariableField, actualParamExpr, methodBody, hasFieldMethodName);
JClass bigJClass = getJClass(returnType, codeModel);
actualParamExpr = JExpr._new(bigJClass).arg(valueVariableField.invoke("toString"));
addEqualsNullCondition(methodBody, valueVariableField);
}
else if(isArray){
if(returnType.getCanonicalName().equals("byte[]")){
JClass byteStringClass = getJClass(ByteString.class, codeModel);
actualParamExpr = JExpr.cast(byteStringClass, getFieldInvocation);
methodBody.decl(byteStringClass, valueVariable, JExpr._null());
addHasFieldCheck(valueVariableField, actualParamExpr, methodBody, hasFieldMethodName);
actualParamExpr = valueVariableField.invoke("toByteArray");
}
}
else{
actualParamExpr = JExpr.cast(returnJType, getFieldInvocation);
methodBody.decl(returnJType, valueVariable, JExpr._null());
addHasFieldCheck(valueVariableField, actualParamExpr, methodBody, hasFieldMethodName);
// addEqualsNullCondition(methodBody, valueVariableField);
actualParamExpr = valueVariableField;
}
JFieldRef fieldNameRef = JExpr.ref(filedName);
methodBody.assign(fieldNameRef, actualParamExpr);
methodBody._return(fieldNameRef);
}
private void addEqualsNullCondition(JBlock methodBody, JFieldRef valueVariableField){
JConditional ifValNullCondition = methodBody._if(valueVariableField.eq(JExpr._null()));
ifValNullCondition._then()._return(JExpr._null());
}
/**
* Date has to be handled separately unlike other complex types. This method overrides the corresponding date
* method in the JAXB class and includes the logic to convert between long(time in milliseconds) and
* complex type (XMLGregorianCalendar)
*/
private void dateMethodLogic(EProtoContext info, Method method, JMethod addedMethod, JBlock methodBody,
JCodeModel codeModel, String filedName){
//--------------------------------------------------------------------------------
// Creates the following based on the return type
//
// @Override
// public XMLGregorianCalendar getTimestamp() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, "timestamp");
// Long val = ((Long) m_Builder.getField((fieldDescriptor)));
// if (val == null) {
// return null;
// }
// try {
// GregorianCalendar greCal = new GregorianCalendar();
// greCal.setTimeInMillis(timeStamp);
// return DatatypeFactory.newInstance().newXMLGregorianCalendar(greCal);
// } catch (DatatypeConfigurationException _x) {
// return null;
// }
// }
//
//
// @Override
// public Duration getTimestamp() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, "timestamp");
// Long val = ((Long) m_Builder.getField((fieldDescriptor)));
// if (val == null) {
// return null;
// }
// try {
// return DatatypeFactory.newInstance().newDuration(val);
// } catch (DatatypeConfigurationException _x) {
// return null;
// }
// }
//--------------------------------------------------------------------------------
String dateFieldDesc = "protobufTempValue";
Class<?> returnTypeClass = method.getReturnType();
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JFieldRef valInstanceRef = JExpr.ref(dateFieldDesc);
JClass longClass = getJClass(Long.class, codeModel);
JClass dataTypeFactoryClass = getJClass(DatatypeFactory.class, codeModel);
JExpression datatypeFactoryExpr = dataTypeFactoryClass.staticInvoke("newInstance");
String getterMethodName = getGetterMethodNameForFields(info, method);
String hasFieldMethodName = getHasFieldMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
JExpression actualParamExpr = JExpr.cast(longClass, getFieldInvocation);
methodBody.decl(longClass, dateFieldDesc, JExpr._null());
addHasFieldCheck(valInstanceRef, actualParamExpr, methodBody, hasFieldMethodName);
JConditional ifValNullCondition = methodBody._if(valInstanceRef.eq(JExpr._null()));
ifValNullCondition._then()._return(JExpr._null());
JTryBlock jTryBlock = methodBody._try();
JBlock tryBody = jTryBlock.body();
JFieldRef fieldNameRef = JExpr.ref(filedName);
JExpression returnExpr = null;
if(returnTypeClass.equals(XMLGregorianCalendar.class)){
returnExpr = getXMLGregorianCalTryBlock(tryBody, codeModel, datatypeFactoryExpr, valInstanceRef,filedName);
}
else if(returnTypeClass.equals(Duration.class)){
returnExpr = datatypeFactoryExpr.invoke("newDuration").arg(valInstanceRef);
}
tryBody.assign(fieldNameRef, returnExpr);
tryBody._return(fieldNameRef);
JCatchBlock jCatchBlock =
jTryBlock._catch(getJClass(DatatypeConfigurationException.class, codeModel));
jCatchBlock.body()._return(JExpr._null());
}
private JExpression getXMLGregorianCalTryBlock(JBlock tryBody, JCodeModel codeModel,
JExpression dataFactExpr, JFieldRef valInstanceRef, String filedName){
String greCalDesc = "greCal";
JClass greCalClass = getJClass(GregorianCalendar.class, codeModel);
JInvocation urlClassObjCreater = JExpr._new(greCalClass);
JFieldRef calRef = JExpr.ref(greCalDesc);
tryBody.decl(greCalClass, greCalDesc, urlClassObjCreater);
JInvocation setMilliInvocation = calRef.invoke("setTimeInMillis").arg(valInstanceRef);
tryBody.add(setMilliInvocation);
JInvocation returnExpr = dataFactExpr.invoke("newXMLGregorianCalendar").arg(calRef);
return returnExpr;
}
/**
*
* @param info ProtoContext containing various info about the message
* @param method java.lang.Method object
* @param addedMethod
* @param methodBody
* @param codeModel
* @param isEnumField Decides the type of getter to be generated. Enum and COmplex type getter has very
* minimal difference and hence clubbed into one single method based on this value.
* @throws CodeGenFailedException
*/
private void addComplexTypeMethodLogic(EProtoContext info, Method method, JMethod addedMethod, JBlock methodBody,
JCodeModel codeModel, boolean isEnumField, String filedName) throws CodeGenFailedException{
//--------------------------------------------------------------------------------
//
// Creates the following if isEnumField is true (ENUM field)
//
// @Override
// public <Enum> get<Enum>() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, enumFieldName);
// com.google.protobuf.Descriptors.EnumValueDescriptor val = ((com.google.protobuf.Descriptors.EnumValueDescriptor) m_Builder.getField((fieldDescriptor)));
// if (val == null) {
// return null;
// }
// return (<EnumEProto>.getEnum(<JProto>.valueOf(val)));
// }
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//
// Creates the following if isEnumField is false (ComplexType field)
//
// @Override
// public <JAXBType> get<JAXB Method name>() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, jaxbFieldName);
// <JProtoMessageName> val = ( <JProtoMessageName> m_Builder.getField((fieldDescriptor)));
// if (val == null) {
// return null;
// }
// return (new <EProtoName>(val));
// }
//
//--------------------------------------------------------------------------------
JClass complexTypeDescriptorClass = null;
String enumFieldDesc = "protobufTempValue";
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JFieldRef valInstanceRef = JExpr.ref(enumFieldDesc);
String methodReturnType = method.getReturnType().getName();
if(jaxbProtoMapping.get(methodReturnType) == null){
getLogger().log(Level.WARNING, "There seems to be duplicate class issue, the class "
+ methodReturnType + "or the class containing " + methodReturnType + " may contain duplicates.");
return;
}
String jProtoMessageClass = jaxbProtoMapping.get(methodReturnType).getJprotoName();
String eProtoClass = jaxbProtoMapping.get(methodReturnType).getEprotoName();
complexTypeDescriptorClass = getJClass(jProtoMessageClass, codeModel);
String getterMethodName = getGetterMethodNameForFields(info, method);
String hasFieldMethodName = getHasFieldMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
// Builder.getField always returns java.lang.Object. Hence we need to type cast it to
// the type we need it to be.
JExpression actualParamExpr = JExpr.cast(complexTypeDescriptorClass, getFieldInvocation);
methodBody.decl(complexTypeDescriptorClass, enumFieldDesc, JExpr._null());
addHasFieldCheck(valInstanceRef, actualParamExpr, methodBody, hasFieldMethodName);
JConditional ifServiceLocCondition = methodBody._if(valInstanceRef.eq(JExpr._null()));
ifServiceLocCondition._then()._return(JExpr._null());
JExpression returnInvocation = null;
// EProto class for the types used in here may not have been generated by the time
// the control comes here for a given EProto class. Hence we need to use JExpr.direct instead
// of creating a JClass and invoking the methods.
if(isEnumField){
StringBuilder builder = new StringBuilder();
builder.append(eProtoClass)
.append(".").append(GETENUMMETHOD).append("(")
.append(enumFieldDesc).append(")");
returnInvocation = JExpr.direct(builder.toString());
}
else{
StringBuilder builder = new StringBuilder();
builder.append("new ").append(eProtoClass)
.append("(").append(enumFieldDesc).append(")");
returnInvocation = JExpr.direct(builder.toString());
}
JFieldRef fieldNameRef = JExpr.ref(filedName);
methodBody.assign(fieldNameRef, returnInvocation);
methodBody._return(fieldNameRef);
}
/**
* When the List types are used, the info inside the JProto list had to be copied to POJO class' list.
* This logic involves iterating through one list and populating the other and return the resultant list.
* The list can contain either User defined types or primitive types supported by java.
* This method generates the following construct.
*/
private void addListMethod(EProtoContext info, Method method, JMethod addedMethod, JBlock methodBody,
JCodeModel codeModel,JDefinedClass targetClass, String filedName) throws CodeGenFailedException{
//--------------------------------------------------------------------------------
//
// Creates the following
//
// @Override
// public List<JAXBType> getError() {
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, fieldName);
// List<JAXBType> pojoList = new ArrayList<JAXBType>();
// List<JProtoMessageName> protoList =
// ((ArrayList<JProtoMessageName> ) m_Builder.getField((fieldDescriptor)));
// if ((protoList!= null)&&(protoList.size()> 0)) {
// for (<JProtoMessageName> protobufListItem: protoList) {
// pojoList.add((<EProtoName>(protobufListItem)));
// }
// }
// return pojoList;
// }
//--------------------------------------------------------------------------------
String returnName = "pojoList";
String protoListMember = "protoList";
JFieldRef protoListRef = JExpr.ref(protoListMember);
JFieldRef pojoListRef = JExpr.ref(returnName);
//List would have only one Parameterized type
Type[] typesInside = ((ParameterizedType)method.getGenericReturnType()).getActualTypeArguments();
Class<?> returnClass = null;
if((Class.class).equals((typesInside[0]).getClass()))
returnClass = (Class<?>) typesInside[0];
else{
getLogger().log(Level.WARNING, "There seems to be problem wih the" +
" return type of the method " + method.getName() + ". This may lead to " +
"erratic behavior during runtime");
return;
}
String typeName = returnClass.getName();
JAXB2EJProtoMapping mapping = jaxbProtoMapping.get(typeName);
JFieldRef builderField = JExpr.ref(BUILDERMEMBER);
JClass arrayListClass = getJClass(ArrayList.class, codeModel);
JClass dataTypeFactoryClass = getJClass(DatatypeFactory.class, codeModel);
JExpression datatypeFactoryExpr = dataTypeFactoryClass.staticInvoke("newInstance");
if(mapping != null || returnClass.equals(BigDecimal.class) || returnClass.equals(BigInteger.class)
|| returnClass.equals(QName.class) || returnClass.equals(Byte.class) || returnClass.equals(Short.class)
|| returnClass.equals(XMLGregorianCalendar.class) || returnClass.equals(Duration.class) ){
String foreachElement = "protobufListItem";
JFieldRef valInstanceRef = JExpr.ref(foreachElement);
Class<?> protoClass = null;
Class<?> pojoClass = null;
if(mapping != null){
protoClass = ContextClassLoaderUtil.loadRequiredClass(mapping.getJprotoName());
pojoClass = returnClass;
}
else if(returnClass.equals(BigDecimal.class) || returnClass.equals(BigInteger.class)
|| returnClass.equals(QName.class)){
pojoClass = returnClass;
protoClass = String.class;
}
else if(returnClass.equals(Short.class) || returnClass.equals(Byte.class)){
pojoClass = returnClass;
protoClass = Integer.class;
}
else if(returnClass.equals(XMLGregorianCalendar.class) || returnClass.equals(Duration.class)){
pojoClass = returnClass;
protoClass = Long.class;
}
JClass listClass = getJClass(List.class, codeModel);
methodBody.decl(listClass.narrow(pojoClass), returnName, JExpr._new(arrayListClass.narrow(pojoClass)));
String getterMethodName = getGetterMethodNameForFields(info, method);
String fieldCountMethodName = getFieldCountMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
JExpression actualParamExpr = JExpr.cast(listClass.narrow(protoClass), getFieldInvocation);
addGetFieldCountForListCheck(methodBody, pojoListRef, fieldCountMethodName);
methodBody.decl(listClass.narrow(protoClass), protoListMember, actualParamExpr);
JExpression secondCondition = protoListRef.invoke("size").gt(JExpr.lit(0));
JConditional ifServiceLocCondition = methodBody._if(protoListRef.ne(JExpr._null()).cand(secondCondition));
// EProto class for the types used in here may not have been generated by the time
// the control comes here for a given EProto class. Hence we need to use JExpr.direct instead
// of creating a JClass and invoking the methods.
JForEach foreachLoop = ifServiceLocCondition._then().forEach(getJClass(protoClass, codeModel), foreachElement, protoListRef);
JInvocation addToListInvoker = null;
if(mapping != null){
StringBuilder builder = new StringBuilder();
builder.append("new ").append(mapping.getEprotoName()).append("(protobufListItem)");
addToListInvoker = pojoListRef.invoke("add").arg(JExpr.direct(builder.toString()));
foreachLoop.body().add(addToListInvoker);
}
else if(returnClass.equals(QName.class)){
JClass qNameClass = getJClass(QName.class, codeModel);
JExpression qnameValueExpr = qNameClass.staticInvoke("valueOf").arg(JExpr.ref(foreachElement));
addToListInvoker = pojoListRef.invoke("add").arg(qnameValueExpr);
foreachLoop.body().add(addToListInvoker);
}
else if(returnClass.equals(BigDecimal.class) || returnClass.equals(BigInteger.class)){
JExpression integerValueExpr = JExpr._new(getJClass(returnClass, codeModel)).arg(JExpr.ref(foreachElement));
addToListInvoker = pojoListRef.invoke("add").arg(integerValueExpr);
foreachLoop.body().add(addToListInvoker);
}
else if(returnClass.equals(Short.class) || returnClass.equals(Byte.class)){
JExpression integerValueExpr = JExpr._new(getJClass(returnClass, codeModel))
.arg(JExpr.ref(foreachElement).invoke("toString"));
addToListInvoker = pojoListRef.invoke("add").arg(integerValueExpr);
foreachLoop.body().add(addToListInvoker);
}
else if(returnClass.equals(XMLGregorianCalendar.class)){
JTryBlock jTryBlock = foreachLoop.body()._try();
JBlock tryBody = jTryBlock.body();
JExpression returnExpression = getXMLGregorianCalTryBlock(tryBody, codeModel, datatypeFactoryExpr, valInstanceRef, filedName);
addToListInvoker = pojoListRef.invoke("add").arg(returnExpression);
tryBody.add(addToListInvoker);
JCatchBlock jCatchBlock =
jTryBlock._catch(getJClass(DatatypeConfigurationException.class, codeModel));
jCatchBlock.body()._return(JExpr._null());
}
else if(returnClass.equals(Duration.class)){
JTryBlock jTryBlock = foreachLoop.body()._try();
JBlock tryBody = jTryBlock.body();
JExpression returnExpression = datatypeFactoryExpr.invoke("newDuration").arg(valInstanceRef);
addToListInvoker = pojoListRef.invoke("add").arg(returnExpression);
tryBody.add(addToListInvoker);
JCatchBlock jCatchBlock =
jTryBlock._catch(getJClass(DatatypeConfigurationException.class, codeModel));
jCatchBlock.body()._return(JExpr._null());
}
JFieldRef fieldNameRef = JExpr.ref(filedName);
methodBody.assign(fieldNameRef, JExpr.ref(returnName));
methodBody._return(fieldNameRef);
} else{
/**
* The collection is a list of JAVA supported types
@Override
public List<WrapperTypes of Primitive types> get<MethodName>() {
com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = getDescriptor(m_Builder, fieldName);
return ((List<WrapperTypes of Primitive types> ) m_Builder.getField((fieldDescriptor)));
}
*/
String valueField = "protobufTempValue";
JFieldRef valueFieldRef = JExpr.ref(valueField);
JType returnJType = getJType(method.getGenericReturnType(), codeModel);
String getterMethodName = getGetterMethodNameForFields(info, method);
String fieldCountMethodName = getFieldCountMethodNameForFields(info, method);
JInvocation getFieldInvocation = builderField.invoke(getterMethodName);
JType wrapperType = returnJType.boxify();
JExpression actualParamExpr = JExpr.cast(wrapperType, getFieldInvocation);
addGetFieldCountForListCheck(methodBody, JExpr._new(arrayListClass.narrow(returnClass)), fieldCountMethodName);
methodBody.decl(returnJType, valueField, actualParamExpr);
actualParamExpr = valueFieldRef;
JFieldRef fieldNameRef = JExpr.ref(filedName);
methodBody.assign(fieldNameRef, actualParamExpr);
methodBody._return(fieldNameRef);
}
}
/**
* Generates the utility method ParseFrom. This is used to convert the stream into corresponding JAXB object.
*/
private JMethod addParseFrom(EProtoContext info, JDefinedClass targetClass, JCodeModel codeModel) throws CodeGenFailedException{
//--------------------------------------------------------------------------------
// Creates
//
// public static <JAXBName> parseFrom(InputStream data)
// throws Exception
// {
// <JprotoMessageName> deserializedObject = null;
// deserializedObject = <JprotoMessageName>.parseFrom((data));
// return (new EProtoName(deserializedObject));
// }
//--------------------------------------------------------------------------------
getLogger().log(Level.FINE, "Adding parseFrom private method for " + info.getFullyQualifiedEProtoName());
String parseFromMethodName = "parseFrom";
String streamArg = "data";
String returnName = "deserializedObject";
JClass returnTypeClass = getJClass(ContextClassLoaderUtil.loadRequiredClass(info.getFullyQualifiedName()), codeModel);
JMethod parseFromMethod = addMethod(targetClass, parseFromMethodName,
JMod.STATIC | JMod.PUBLIC , returnTypeClass);
parseFromMethod.param(InputStream.class, streamArg);
parseFromMethod._throws(Exception.class);
JBlock methodBody = parseFromMethod.body();
JClass protoMessageClass = getJClass(info.getFullyQualifiedJProtoMessageName(), codeModel);
methodBody.decl(protoMessageClass, returnName, JExpr._null());
JFieldRef svcInstanceRef = JExpr.ref(returnName);
JInvocation parseFromInvoker = protoMessageClass.staticInvoke(parseFromMethodName);
parseFromInvoker.arg(JExpr.direct(streamArg));
methodBody.assign(svcInstanceRef, parseFromInvoker);
// EProto class for the types used in here may not have been generated by the time
// the control comes here for a given EProto class. Hence we need to use JExpr.direct
// instead of creating a JClass and invoking the methods.
StringBuilder builder = new StringBuilder();
builder.append("new ")
.append(info.getFullyQualifiedEProtoName())
.append("(").append(returnName)
.append(")");
JExpression returnInvocation = JExpr.direct(builder.toString());
methodBody._return(returnInvocation);
return parseFromMethod;
}
/**
* Generates the utility method getDeserializedJProtoObject. This is used to convert the stream into corresponding JProto object.
*/
private JMethod addGetDeserializedJProtoObject(EProtoContext info, JDefinedClass targetClass, JCodeModel codeModel)
throws CodeGenFailedException{
//--------------------------------------------------------------------------------
// Creates
//
// public static <JprotoMessageName> getDeserializedJProtoObject(InputStream data)
// throws Exception
// {
// return <JprotoMessageName>.parseFrom((data));
// }
//--------------------------------------------------------------------------------
getLogger().log(Level.FINE, "Adding parseFrom private method for " + info.getFullyQualifiedEProtoName());
String parseFromMethodName = "parseFrom";
String streamArg = "data";
JClass protoMessageClass = getJClass(info.getFullyQualifiedJProtoMessageName(), codeModel);
JMethod deserializedObjectMethod = addMethod(targetClass, "getDeserializedJProtoObject",
JMod.STATIC | JMod.PUBLIC , protoMessageClass);
deserializedObjectMethod.param(InputStream.class, streamArg);
deserializedObjectMethod._throws(Exception.class);
JBlock methodBody = deserializedObjectMethod.body();
JInvocation parseFromInvoker = protoMessageClass.staticInvoke(parseFromMethodName);
parseFromInvoker.arg(JExpr.direct(streamArg));
methodBody._return(parseFromInvoker);
return deserializedObjectMethod;
}
/**
* Generates the utility method getDeserializedJProtoObject. This is used to convert the stream into corresponding JProto object.
*/
private JMethod addGetJProtoBuilderObject(EProtoContext info, JDefinedClass targetClass, JCodeModel codeModel)
throws CodeGenFailedException{
//--------------------------------------------------------------------------------
// Creates
//
// public static <JprotoMessageName> getDeserializedJProtoObject(InputStream data)
// throws Exception
// {
// return <JprotoMessageName>.parseFrom((data));
// }
//--------------------------------------------------------------------------------
Class<?> something = ContextClassLoaderUtil.loadRequiredClass(info.getBuilderClass());
JClass builderClass = getJClass(something, codeModel);
JMethod deserializedObjectMethod = addMethod(targetClass, "getJProtoBuilderObject",
JMod.PUBLIC , builderClass);
JBlock methodBody = deserializedObjectMethod.body();
methodBody._return(JExpr.ref(BUILDERMEMBER));
return deserializedObjectMethod;
}
/**
* This method is to convert the jaxb pojo type to jproto type at runtime.
* This method basically uses jproto builder to build the jproto object.
* This method also checks if runtime polymorphism is used and if yes, we throw a PolymorphismNotSupportedException
* Use Google's FieldDescriptor APIs corresponding to the field to set the values
* Similar to the getters logic, newInstance logic will be different for different return types namely
* 1)primitive types
* 2)String
* 3)Date
* 4)Enum
* 5)User defined Complex type
* 6)List of types (complex and simple)
*/
private JMethod addNewInstanceMethod(EProtoContext info, JDefinedClass targetClass,
JCodeModel codeModel) throws CodeGenFailedException{
//--------------------------------------------------------------------------------
// Creates
//
// public static <JProtoMessageName> newInstance(<JAXBPojoClassName> pojoClass)
// throws Exception
// {
// if (!JAXBPOJOCLASS.equals(pojoClass.getClass().getName())) {
// throw new PolymorphismNotSupportedException(("Polymorphism is not supported. " +
// "Class " + pojoClass.getClass().getName() + " is used instead of <JAXBPojoClassName>"));
// }
//
// <JProtoMessageName>.Builder builder = <JProtoMessageName>.newBuilder();
//
// com.google.protobuf.Descriptors.FieldDescriptor fieldDescriptor = null;
//
// if (pojoClass.get<Methods>!= null) {
// fieldDescriptor = getDescriptor(builder, <fieldName>);
// builder.setField(fieldDescriptor, <POJOClass.get<Method>>/<EProto.newInstance>);
// }
//
// return builder.build();
// }
//--------------------------------------------------------------------------------
getLogger().log(Level.FINE, "Adding newInstance private method for " + info.getFullyQualifiedEProtoName());
String newInstanceMethodName = "newInstance";
String methodArg = "pojoClass";
String returnName = "builder";
JClass methodArgClass = getJClass(ContextClassLoaderUtil.loadRequiredClass(info.getFullyQualifiedName()), codeModel);
JClass returnTypeClass = getJClass(ContextClassLoaderUtil.loadRequiredClass(info.getFullyQualifiedJProtoMessageName()), codeModel);
JClass builderClass = getJClass(ContextClassLoaderUtil.loadRequiredClass(info.getBuilderClass()), codeModel);
JFieldRef protoListRef = JExpr.ref(JAXBPOJOCLASS);
JFieldRef methodArgRef = JExpr.ref(methodArg);
JFieldRef returnRef = JExpr.ref(returnName);
JMethod newInstanceMethod = addMethod(targetClass, newInstanceMethodName,
JMod.STATIC | JMod.PUBLIC , returnTypeClass);
newInstanceMethod.param(methodArgClass, methodArg);
newInstanceMethod._throws(Exception.class);
JBlock newInstanceMethodBody = newInstanceMethod.body();
JClass polyNotSupportedClass = getJClass(SerializationException.class, codeModel);
JExpression condition = methodArgRef.invoke("getClass").invoke("getName");
JConditional ifServiceLocCondition = newInstanceMethodBody._if(protoListRef.invoke("equals").arg(condition).not());
StringBuilder errorMessageBuilder = new StringBuilder();
errorMessageBuilder.append("\"Polymorphism is not supported. \" + \n \t\t\t\"Class \" + ")
.append(methodArg)
.append(".getClass().getName() + \" is used instead of ")
.append(info.getFullyQualifiedName())
.append("\"");
JBlock ifBlock = ifServiceLocCondition._then();
ifBlock._throw(JExpr._new(polyNotSupportedClass).arg(JExpr.direct(errorMessageBuilder.toString())));
newInstanceMethodBody.decl(builderClass, returnName, returnTypeClass.staticInvoke("newBuilder"));
List<Method> getterMethods = info.getMethods();
for (Method method : getterMethods) {
getLogger().log(Level.FINE, "Adding newInstance for the field " + info.getGetterToFields().get(method.getName()));
JBlock insideMethodBody = newInstanceMethodBody;
/**
* addStatements - convenience flag. Except for list type, the
* builder.setField(fieldDescriptor, <POJOClass.get<Method>>/<EProto.newInstance>);
* is gonna be similar for all other types. Hence the expression to be added as
* argument would be figured out first and at the end of the loop(based on the flag's value)
* would be added to the if block. In the case of List, it would be added as and when list is traversed.
*/
boolean addStatements = true;
JExpression setFieldSecondArg = methodArgRef.invoke(method.getName());
JConditional ifCondition = null;
JAXB2EJProtoMapping returntypeMapping = null;
String newMethodName = getSetterMethodNameForFields(info, method);
if(!method.getReturnType().isPrimitive()){
/** return type is primitive
fieldDescriptor = getDescriptor(builder, primitiveFieldName);
builder.setField(fieldDescriptor, pojoClass.get<Methodname>());
*/
ifCondition = newInstanceMethodBody._if(setFieldSecondArg.ne(JExpr._null()));
insideMethodBody = ifCondition._then();
returntypeMapping = jaxbProtoMapping.get(method.getReturnType().getName());
}
/** return type is String/List<PrimitiveTypes>
if (pojoClass.get<Methodname>()!= null) {
fieldDescriptor = getDescriptor(builder, fieldName);
builder.setField(fieldDescriptor, pojoClass.get<Methodname>());
}
*/
if(method.getReturnType().equals(BigInteger.class) || method.getReturnType().equals(BigDecimal.class)
|| method.getReturnType().equals(QName.class)){
setFieldSecondArg = setFieldSecondArg.invoke("toString");
}
else if(method.getReturnType().equals(Duration.class)){
/** return type is Duration(Date), these constructs are fixed.
if (pojoClass.get<Methodname>()!= null) {
fieldDescriptor = getDescriptor(builder, dateFieldName);
builder.setField(fieldDescriptor, pojoClass.get<Methodname>().getTimeInMillis(Calendar.getInstance()));
}
*/
JClass calendarClass = getJClass(Calendar.class, codeModel);
setFieldSecondArg = setFieldSecondArg.invoke("getTimeInMillis").arg(calendarClass.staticInvoke("getInstance"));
}
else if(method.getReturnType().equals(XMLGregorianCalendar.class)){
/** return type is XMLGregorianCalendar(Date), these constructs are fixed.
if (pojoClass.get<Methodname>()!= null) {
fieldDescriptor = getDescriptor(builder, dateFieldName);
builder.setField(fieldDescriptor, pojoClass.get<Methodname>().toGregorianCalendar().getTimeInMillis());
}
*/
setFieldSecondArg = setFieldSecondArg.invoke("toGregorianCalendar").invoke("getTimeInMillis");
}
else if(method.getReturnType().getCanonicalName().equals("byte[]")){
/** return type is byte[], these constructs are fixed.
*/
String byteStringVariable = "byteString";
JFieldRef valueFieldRef = JExpr.ref(byteStringVariable);
JClass byteStringClass = getJClass(ByteString.class, codeModel);
JExpression actualParamExpr = byteStringClass.staticInvoke("copyFrom").arg(setFieldSecondArg);
insideMethodBody.decl(byteStringClass, byteStringVariable, actualParamExpr);
setFieldSecondArg = valueFieldRef;
}
else if(method.getReturnType().isEnum()){
/** return type is ENUM
if (pojoClass.get<Methodname>()!= null) {
fieldDescriptor = getDescriptor(builder, enumFieldName);
builder.setField(fieldDescriptor, (<EProtoClass>.newInstance(pojoClass.get<Methodname>()).getValueDescriptor()));
}
*/
if(returntypeMapping != null){
StringBuilder builder = new StringBuilder();
builder.append(returntypeMapping.getEprotoName())
.append(".newInstance(")
.append(methodArg).append(".")
.append(method.getName()).append("())");
setFieldSecondArg = JExpr.direct(builder.toString());
}
}
else{
if(method.getReturnType().equals(List.class)){
/** return type is List<ComplexTypes/UserDefined types>
if (pojoClass.get<Methodname>()!= null) {
for (<JAXBPOJOClassName> protobufListItem: pojoClass.get<Methodname>()) {
builder.addRepeatedField(fieldDescriptor, (<EProtoClass>.newInstance(protobufListItem)));
}
}
*/
String typeName = null;
String indiMember = "protobufListItem";
Class<?> returnClass = null;
Type[] typesInside = ((ParameterizedType)method.getGenericReturnType()).getActualTypeArguments();
if((Class.class).equals((typesInside[0]).getClass()))
returnClass = (Class<?>) typesInside[0];
else{
getLogger().log(Level.WARNING, "There seems to be problem wih the" +
" return type of the method " + method.getName() + ". This may lead to " +
"erratic behavior during runtime");
continue;
}
typeName = returnClass.getName();
if(returntypeMapping == null){
returntypeMapping = jaxbProtoMapping.get(typeName);
}
if(returntypeMapping != null || returnClass.equals(BigDecimal.class) || returnClass.equals(BigInteger.class)
|| returnClass.equals(QName.class) || returnClass.equals(Byte.class) || returnClass.equals(Short.class)
|| returnClass.equals(XMLGregorianCalendar.class) || returnClass.equals(Duration.class)
|| wrapperClasses.contains(returnClass)){
JClass listClass = getJClass(typeName, codeModel);
JForEach foreachLoop = ifCondition._then().forEach(listClass, indiMember, methodArgRef.invoke(method.getName()));
JInvocation addToListInvoker= returnRef.invoke(newMethodName);
if(returntypeMapping != null){
StringBuilder builder = new StringBuilder();
builder.append(returntypeMapping.getEprotoName())
.append(".newInstance(")
.append(indiMember).append(")");
addToListInvoker.arg(JExpr.direct(builder.toString()));
}
else if(returnClass.equals(QName.class) || returnClass.equals(BigDecimal.class)
|| returnClass.equals(BigInteger.class)){
// these types converted to string in proto world
addToListInvoker.arg(JExpr.ref(indiMember).invoke("toString"));
}
else if(returnClass.equals(Short.class) || returnClass.equals(Byte.class)){
// these types converted to sint32 in proto world
JClass integerClass = getJClass(Integer.class, codeModel);
addToListInvoker.arg(JExpr._new(integerClass).arg(JExpr.ref(indiMember)));
}
else if(returnClass.equals(XMLGregorianCalendar.class)){
addToListInvoker.arg(JExpr.ref(indiMember).invoke("toGregorianCalendar").invoke("getTimeInMillis"));
}
else if(returnClass.equals(Duration.class)){
JClass calendarClass = getJClass(Calendar.class, codeModel);
addToListInvoker.arg(JExpr.ref(indiMember).invoke("getTimeInMillis")
.arg(calendarClass.staticInvoke("getInstance")));
}
else if(wrapperClasses.contains(returnClass)){
addToListInvoker.arg(JExpr.ref(indiMember));
}
JBlock forEachBlock = foreachLoop.body();
forEachBlock.add(addToListInvoker);
addStatements = false;
}
}
else {
/** return type is ComplexTypes/UserDefined types
if (pojoClass.get<Methodname>()!= null) {
fieldDescriptor = getDescriptor(builder, fieldName);
builder.setField(fieldDescriptor, (<EProtoClass>.newInstance(pojoClass.get<Methodname>)));
}
*/
if(returntypeMapping != null){
StringBuilder builder = new StringBuilder();
builder.append(returntypeMapping.getEprotoName())
.append(".newInstance(")
.append(methodArg).append(".")
.append(method.getName()).append("())");
setFieldSecondArg = JExpr.direct(builder.toString());
}
}
}
JInvocation setFieldInvocation = returnRef.invoke(newMethodName);
if(setFieldSecondArg != null)
setFieldInvocation.arg(setFieldSecondArg);
if(addStatements){
insideMethodBody.add(setFieldInvocation);
}
}
JExpression returnInvocation = returnRef.invoke("build");
newInstanceMethodBody._return(returnInvocation);
return newInstanceMethod;
}
private String getSetterMethodNameForFields(EProtoContext info, Method method){
String newMethodName = null;
String fieldName = CodeGenUtil.makeFirstLetterUpper(info.getGetterToFields().get(method.getName()).replace("_", ""));
if(method.getReturnType().equals(List.class))
newMethodName = "add" + fieldName;
else
newMethodName = "set" + fieldName;
return newMethodName;
}
private String getGetterMethodNameForFields(EProtoContext info, Method method){
String newMethodName = info.getGetterToFields().get(method.getName());
String fieldName = CodeGenUtil.makeFirstLetterUpper(info.getGetterToFields().get(method.getName()).replace("_", ""));
newMethodName = "get" + fieldName;
if(method.getReturnType().equals(List.class))
newMethodName = newMethodName + "List";
return newMethodName;
}
private String getHasFieldMethodNameForFields(EProtoContext info, Method method){
String newMethodName = info.getGetterToFields().get(method.getName());
String fieldName = CodeGenUtil.makeFirstLetterUpper(info.getGetterToFields().get(method.getName()).replace("_", ""));
newMethodName = "has" + fieldName;
return newMethodName;
}
private String getFieldCountMethodNameForFields(EProtoContext info, Method method){
String newMethodName = info.getGetterToFields().get(method.getName());
String fieldName = CodeGenUtil.makeFirstLetterUpper(info.getGetterToFields().get(method.getName()).replace("_", ""));
newMethodName = "get" + fieldName;
if(method.getReturnType().equals(List.class))
newMethodName = newMethodName + "Count";
return newMethodName;
}
}