Index: maven-commandline-plugin/src/java/org/codelutin/util/Generator.java diff -u maven-commandline-plugin/src/java/org/codelutin/util/Generator.java:1.1 maven-commandline-plugin/src/java/org/codelutin/util/Generator.java:1.2 --- maven-commandline-plugin/src/java/org/codelutin/util/Generator.java:1.1 Thu Nov 29 10:32:25 2007 +++ maven-commandline-plugin/src/java/org/codelutin/util/Generator.java Thu Nov 29 22:27:22 2007 @@ -20,14 +20,7 @@ package org.codelutin.util; -import javassist.CannotCompileException; -import javassist.ClassClassPath; -import javassist.ClassPath; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtField; -import javassist.Modifier; -import javassist.NotFoundException; +import javassist.*; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; @@ -35,10 +28,12 @@ import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.AnnotationMemberValue; import javassist.bytecode.annotation.ArrayMemberValue; +import javassist.bytecode.annotation.ClassMemberValue; import javassist.bytecode.annotation.EnumMemberValue; import javassist.bytecode.annotation.IntegerMemberValue; import javassist.bytecode.annotation.MemberValue; import javassist.bytecode.annotation.StringMemberValue; +import org.apache.commons.lang.StringUtils; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; @@ -134,6 +129,11 @@ * @parameter expression="${commandLine.backupClass}" default-value="false" */ protected boolean backupClass; + /** + * @description flag to generate or not specialized Option + * @parameter expression="${commandLine.generateOptionImplementation}" default-value="false" + */ + protected boolean generateOptionImplementation; /** le parseur de définition */ protected OptionDefinitionParser parser; @@ -142,7 +142,9 @@ private CtClass optionDefinitionAClazz; private CtClass optionArgumentDefinitionAClazz; private CtClass typeClazz; + private CtClass optionClazz; private CtClass valueTypeClazz; + private ClassPool pool; public void execute() throws MojoExecutionException, MojoFailureException { @@ -159,11 +161,11 @@ log.info(_("commandline.parser.result.info", parser, parser.getDefinitions().length)); - ClassPool pool = new ClassPool(null); + pool = new ClassPool(null); if (backupClass) { // backup previously generated classes - backupPreviousGeneratedClass(pool, parserFullyQualifiedName); + backupPreviousGeneratedClass(parserFullyQualifiedName); } // we need the classpath of OptionParser, since @@ -176,6 +178,7 @@ optionDefinitionAClazz = pool.get(OptionDefinitionA.class.getName()); optionArgumentDefinitionAClazz = pool.get(OptionArgumentDefinitionA.class.getName()); typeClazz = pool.get(OptionArgumentType.class.getName()); + optionClazz = pool.get(Option.class.getName()); valueTypeClazz = pool.get(OptionArgumentValueType.class.getName()); //TODO Make it works! pool.importPackage(optionParserAClazz.getPackageName()); @@ -225,6 +228,7 @@ } } + protected void generateOptionParser(ClassPool pool) throws NotFoundException, CannotCompileException, IOException { CtClass superClazz = pool.get(OptionParser.class.getName()); @@ -255,7 +259,7 @@ cf.addAttribute(attribute); //TODO why do we need this? cf.setVersionToJava5(); - + // save it in out clazz.writeFile(out.getAbsolutePath()); @@ -270,7 +274,8 @@ } } - private void generateOptionAnnotation(CtClass clazz, ConstPool constPool, OptionDefinition definition, String name) throws CannotCompileException, NotFoundException { + private void generateOptionAnnotation(CtClass clazz, ConstPool constPool, OptionDefinition definition, String name) throws CannotCompileException, NotFoundException, IOException { + String fieldName = StringUtil.convertToConstantName(name); log.info(_("commandline.parser.field.build.info", fieldName, name, parser)); CtField fld; @@ -297,11 +302,110 @@ annotation.addMemberValue("alias", value); value = generateArgumentAnnotation(definition, fieldInfo, field_cp); - annotation.addMemberValue("arguments", value); + if (generateOptionImplementation) { + CtClass impl = generateOptionImpl(clazz, fieldName, definition); + annotation.addMemberValue("impl", new ClassMemberValue(impl.getName(), constPool)); + } attribute.setAnnotation(annotation); } + private CtClass generateOptionImpl(CtClass clazz, String fieldName, OptionDefinition definition) throws NotFoundException, CannotCompileException, IOException { + String clazzName = clazz.getPackageName() + '.' + optionClazz.getSimpleName() + '_' + fieldName; + CtClass impl = pool.makeClass(clazzName, optionClazz); + + try { + // add constructors (following super ones) + CtConstructor[] superCtConstructor = clazz.getConstructors(); + for (CtConstructor ctConstructor : superCtConstructor) { + CtConstructor newConstructor = new CtConstructor(ctConstructor.getParameterTypes(), impl); + impl.addConstructor(newConstructor); + } + + for (OptionArgumentDefinition optionArgumentDefinition : definition.getArguments()) { + String argumentKey = optionArgumentDefinition.getKey(); + String argumentKeyCap = StringUtils.capitalize(argumentKey); + int position = optionArgumentDefinition.getPos(); + OptionArgumentValueType valueType = optionArgumentDefinition.getValueType(); + + String typeAsStr = valueType.getClazz().getName(); + boolean isBooleanValueType = valueType == OptionArgumentValueType._boolean; + String prefix = "public "; + if (isBooleanValueType|| optionArgumentDefinition.getType()== OptionArgumentType.constant) { + typeAsStr="Boolean"; + } + if (typeAsStr.startsWith("java.lang.")) { + typeAsStr = typeAsStr.substring("java.lang.".length()); + } + prefix+=typeAsStr; + String positionTypeParameters = position + "," + typeAsStr + ".class"; + String positionTypeKeyParameters = positionTypeParameters + ",\"" + argumentKey + "\""; + boolean multi = optionArgumentDefinition.getMax() == -1 || optionArgumentDefinition.getMax() > 1; + switch (optionArgumentDefinition.getType()) { + case constant: + // add a boolean getter + addMethod(impl, + prefix, + buildMethodName(optionArgumentDefinition, true, argumentKeyCap), + "return Boolean.valueOf(\"" + argumentKey + "\".equals(getConstantArgumentValue(" + position + ")));"); + break; + case namedAndValued: + // add a typed getter T getArgument + addMethod(impl, + prefix, + buildMethodName(optionArgumentDefinition,isBooleanValueType, argumentKeyCap), + "return (" + typeAsStr + ") getNamedAndValuedArgumentValue(" + positionTypeKeyParameters+ ");"); + if (multi) { + // add a typed getter T[] getArguments + addMethod(impl, + prefix+"[]", + buildMethodName(optionArgumentDefinition, false, argumentKeyCap + "s"), + "return (" + typeAsStr + "[]) getNamedAndValuedArgumentValues(" + positionTypeKeyParameters+ ");"); + } + break; + case valued: + // add a typed getter T getArgument + addMethod(impl, + prefix, + buildMethodName(optionArgumentDefinition, isBooleanValueType, argumentKeyCap), + "return (" + typeAsStr + ") getValuedArgumentValue(" + positionTypeParameters + ");"); + if (multi) { + // add a typed getter T[] getArguments + addMethod(impl, + prefix+"[]", + buildMethodName(optionArgumentDefinition, false, argumentKeyCap+"s"), + "return (" + typeAsStr + "[]) getValuedArgumentValues(" + positionTypeParameters + ");"); + } + break; + } + } + log.info(_("commandline.parser.impl.build.info", fieldName, impl.getName(), parser)); + + impl.writeFile(out.getAbsolutePath()); + return impl; + } finally { + if (impl != null) { + impl.detach(); + } + } + } + + private String buildMethodName(OptionArgumentDefinition definition, boolean booleanValueType, String methodName) { + methodName = (booleanValueType?"is":"get")+methodName; + if (definition.isMandatory()) { + methodName = methodName+ definition.getPos(); + } + return methodName; + } + + private void addMethod(CtClass impl, String prefix, String methodName, String body) throws CannotCompileException { + CtMethod method; + String b = prefix + " " + methodName + "() {" + body + "}"; + log.info(b); + method = CtMethod.make(b, impl); + impl.addMethod(method); + } + private ArrayMemberValue generateArgumentAnnotation(OptionDefinition definition, FieldInfo fieldInfo, ConstPool field_cp) throws NotFoundException { ArrayMemberValue value; value = new ArrayMemberValue(new AnnotationMemberValue(field_cp), field_cp); @@ -370,7 +474,7 @@ } } - protected void backupPreviousGeneratedClass(ClassPool pool, String... classNames) throws NotFoundException, CannotCompileException, IOException { + protected void backupPreviousGeneratedClass(String... classNames) throws NotFoundException, CannotCompileException, IOException { ClassPath cp = pool.insertClassPath(out.getAbsolutePath());