Revision: 10018
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at December 3, 2008 11:38 by theobriscoe
Initial Code
#! /usr/bin/env groovy import groovy.text.* import groovy.text.GStringTemplateEngine import java.lang.reflect.Field /** * @author Theo Briscoe * @modified by Arsalan S. * @modified by Dan Walker */ class GroovyFileReader { static String IDL_PROJECT_SRC_LOCATION = "C:/Projects/IDL/src/java" static String IDL_PROJECT_CLASS_LOCATION = "C:/Projects/IDL/build/classes" // static String IDL_PROJECT_SRC_EXCLUDED = "Stub,Helper,Holder,Operations,Interface" //Compile and run from ant //Evaluate command line arguments //Build list of java classes //foreach java class //load the class definitions //Use reflection to get list of fields //build the utility class //Place generated clsses in the correct directory //Identify enumerations def subClasses = [] def subClassesCopy= [] def directList = ["SegmentDetailInfo"] def openMethodList = ["com.aaa.travel.idl.Segment"] def importArray = [] String getFields(java.lang.String className){ def stringFields = [] def numericFields=[] def booleanFields = [] // boolean def customFields = [] def stringArrayFields = [] def enumFields = [] //enum fields inside the object def numericArrayFields=[] def booleanArrayFields = [] def customArrayFields = [] def enumArrayFields = [] //1. Load class definition & get all the public fields java.lang.Class c = Class.forName(className) println "Class " + c.getName() java.lang.reflect.Field[] fields = c.getFields() //2. Identify fields and store them in arrays fields.each { field -> print "Type name is "+field.getType().getName()+" -- " //print " " println "Field name is "+ field.getName() def type = field.getType() def typeName = type.getName() switch (type) { case type.isArray(): // Again check for int and boolean arrays // if (field.getType().getName().contains("java.lang.String")){ // stringArrayFields.add(field) // } int startIndex = typeName.indexOf("com.") Class actualClass = null // Dividing the arrays in two categories if (startIndex > 0) { // category 1: custom classes like com.aaa.* typeName = typeName.substring(startIndex,typeName.length()-1) System.out.println("Real type is " + typeName) def lastIndex = typeName.lastIndexOf(".") // def a actualClass = Class.forName(typeName) if(Helper.isCorbaEnum(actualClass)){ // Array of enum type enumFields.add(field) } else { customFields.add(field) if(!openMethodList.contains(typeName)) { subClasses.add(typeName) } } } else { Class classType = field.getType() System.out.println("Real type is "+classType.getComponentType()) actualClass = classType.getComponentType() if (actualClass == String) { stringArrayFields.add(field) } if (actualClass == int || actualClass == double){ numericArrayFields.add(field) } else if (actualClass == boolean) { booleanArrayFields.add(field) } } // println "field name is "+ field.getType().getComponentType() break case String: stringFields.add(field) break case [int, short, double, float]: numericFields.add(field) break case boolean: booleanFields.add(field) break default: println "Class before isCorbaEnum = " + field.getName() print "Type name is "+field.getType().getName()+" -- " //print " " println "Field name is "+ field.getName() if (isCorbaEnum(field.getType())) { println "\t--this is an enum field" enumFields.add(field) } else { //user defined types may need additional checks customFields.add(field) if(!openMethodList.contains(field.getType().getName())) { subClasses.add(field.getType().getName()) } } } } //Build strings def varsList = '' stringFields.each { varsList += buildGeneralMerge(it.getName(),"String") + "\n\t\t" } numericFields.each { varsList += buildNumericMerge(it.getName()) + "\n\t\t" } numericArrayFields.each { def str = buildGeneralMerge(it.getName(),"Numeric") + "\n\t\t" // println str varsList += str } booleanFields.each { varsList += buildBooleanMerge(it.getName()) + "\n\t\t" } booleanArrayFields.each { varsList += buildGeneralMerge(it.getName(),"Boolean") + "\n\t\t" } enumFields.each { varsList += buildEnumMerge(it.getName()) + "\n\t\t" } customFields.each { def customTypeName = "" if (it.getType().isArray()){ customTypeName = it.getType().getName().substring(0,it.getType().getName().length()-1) } else { customTypeName = it.getType().getName() } println "Custom type name is " + customTypeName varsList += buildUserDefinedMerge(it.getName(),customTypeName) + "\n\t\t" } String onlyClassName = getOnlyClassName(className) String fullMethod = buildMethod(onlyClassName, varsList) + "\t\t" return fullMethod } String getOnlyClassName(String input){ int index = input.lastIndexOf(".") return input.substring(index+1, input.length()) } boolean isCorbaEnum(Class c){ try { return c.getDeclaredFields().find { field -> field.getName().equalsIgnoreCase("__value") } } catch(Exception e) { e.printStackTrace() // no need to define the result as it is already false } return result } String buildBooleanMerge(String field){ return "updated.${field} = (newOne.${field} != false) ? newOne.${field} : original.${field};" } String buildEnumMerge(String field){ return "updated.${field} = original.${field};" } String buildEnumArrayMerge(Field[] enumClass){ } String buildNumericMerge(String field){ return "updated.${field} = (newOne.${field} > 0) ? newOne.${field} : original.${field};" } String buildUserDefinedMerge(String name,String fullTypeName){ String type = getOnlyClassName(fullTypeName) Writable outputText = null def substitutionValues = ['name':name, 'type':type] def templateText = "" // checking if the current custom class is in directList - a list of classes that require no merging // for (String value: directList){ // if (type.equ) // } if (directList.contains(type)){ templateText = "updated.${name} = original.${name};" if(!importArray.contains(fullTypeName)) importArray.add(fullTypeName) }else{ templateText = "updated.${name} = merge${type}(original.${name},newOne.${name});" } def templateEngine = new SimpleTemplateEngine() def template = templateEngine.createTemplate(templateText) return template.make(substitutionValues) } String buildStringMerge(String field){ def substitutionValues = ['field':field] def templateText = "updated.${field}=mergeString(original.${field},newOne.${field});" def templateEngine = new SimpleTemplateEngine() def template = templateEngine.createTemplate(templateText) return template.make(substitutionValues) } String buildGeneralMerge(String field,String typeName){ def substitutionValues = ['field':field, 'typeName':typeName] def templateText = "updated.${field}=merge${typeName}(original.${field},newOne.${field});" def templateEngine = new SimpleTemplateEngine() def template = templateEngine.createTemplate(templateText) return template.make(substitutionValues) } String buildMethod(String className, String methods){ def f = new File('C:/projects/GroovyMergeClassGenerator/src/gv/method.template') def templateEngine = new GStringTemplateEngine() //def templateEngine = new SimpleTemplateEngine() // def stringMethods1 = buildStringMerge("type") // def stringMethods2 = buildStringMerge("address1") def substitutionValues = ['className':className, 'methods':methods ] return templateEngine.createTemplate(f).make(substitutionValues).toString() // def opFile = new File("C:/projects/GroovyClassGenerator/outputFiles/MergeUtil.java") // opFile.write(template.toString()) //println template.toString() } String recursiveSubClassCall(String finalStr){ subClassesCopy = subClasses.clone() subClasses = [] subClassesCopy.each { str -> // println "subClass Array: entry is "+str def classAdded = false importArray.find { addedClass -> // println "\t addedClass value is "+ addedClass if (addedClass.equalsIgnoreCase(str)){ // do nothing as that custom class has already been taken care of // println "\t addedClass matched with subClass" classAdded = true } classAdded } if(!classAdded){ finalStr+=getFields(str) importArray.add(str) } } return finalStr } /** * main method to generate the MergeUtil class using templates * @author Arsalan S. * */ boolean buildFile(List classes, String fileName){ def finalStr = "" openMethodList.each { importArray.add(it) } classes.each { finalStr += getFields(it) importArray.add(it) } // Adding the merge methods for custom sub classes if any of them is being used by main classes // Keep it recursive till no more customSubClasses left, in other words generate all subclasses merge methods while (subClasses.size() > 0){ finalStr = recursiveSubClassCall(finalStr) } // generating string for imports def importString = "" final String IMPORTSTR = "import " importArray.each { importString+=(IMPORTSTR + it + ";\n") } // --------------------------------------------------------- def f = new File('C:/projects/GroovyMergeClassGenerator/src/gv/util.template') def templateEngine = new GStringTemplateEngine() def substitutionVal = ['allImports':importString,'allMethods':finalStr] def output = templateEngine.createTemplate(f).make(substitutionVal) def opFile = new File(fileName) opFile.write(output.toString()) } }
Initial URL
Initial Description
Initial Title
Creating Java ClassesDynamically
Initial Tags
Initial Language
Groovy