From c41f05dea92727b62548e00f6acd94096f1f2561 Mon Sep 17 00:00:00 2001 From: Laurent SCHOELENS <61973605+laurentschoelens@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:08:05 +0100 Subject: [PATCH] [#JAP-57] : add javadoc from with-method from fluent-api plugin see https://github.com/highsource/jaxb2-annotate-plugin/issues/57 --- .../plugin/fluent_api/FluentMethodType.java | 255 +++++++++--------- 1 file changed, 131 insertions(+), 124 deletions(-) diff --git a/jaxb-plugins-parent/jaxb-plugins/src/main/java/org/jvnet/jaxb/plugin/fluent_api/FluentMethodType.java b/jaxb-plugins-parent/jaxb-plugins/src/main/java/org/jvnet/jaxb/plugin/fluent_api/FluentMethodType.java index fef779084..302cc8382 100644 --- a/jaxb-plugins-parent/jaxb-plugins/src/main/java/org/jvnet/jaxb/plugin/fluent_api/FluentMethodType.java +++ b/jaxb-plugins-parent/jaxb-plugins/src/main/java/org/jvnet/jaxb/plugin/fluent_api/FluentMethodType.java @@ -22,6 +22,7 @@ import com.sun.codemodel.JClass; import com.sun.codemodel.JConditional; import com.sun.codemodel.JDefinedClass; +import com.sun.codemodel.JDocComment; import com.sun.codemodel.JExpr; import com.sun.codemodel.JForEach; import com.sun.codemodel.JInvocation; @@ -29,138 +30,144 @@ import com.sun.codemodel.JMod; import com.sun.codemodel.JType; import com.sun.codemodel.JVar; +import com.sun.tools.xjc.generator.bean.field.Messages; /** * @author Hanson Char */ public enum FluentMethodType { - FLUENT_SETTER - { - /** - * Adds a fluent api method, which invokes the given setter method, to the given class. - * This applies to both simple property setter method and - * indexed property setter method. - */ - @Override - public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) - { - JMethod setterMethod = fluentMethodInfo.getJmethod(); - String name = setterMethod.name(); - // Create a with* method for the respective set* method. - int mods = JMod.PUBLIC | setterMethod.mods().getValue() & JMod.FINAL; - JMethod fluentMethod = implClass.method(mods, implClass, - FLUENT_SETTER_METHOD_PREFIX + name.substring(SETTER_METHOD_PREFIX_LEN)); - if (fluentMethodInfo.isOverride()) - fluentMethod.annotate(Override.class); - JVar[] jvars = setterMethod.listParams(); - // jvars.length == 1 means simple property setter method. - // jvars.length == 2 means indexed property setter method. - assert jvars.length == 1 || jvars.length == 2; - // with the same parameter(s) as the set* method - for (JVar jvar : jvars) - fluentMethod.param(jvar.mods().getValue(), jvar.type(), jvar.name()); - JBlock jblock = fluentMethod.body(); - // The with* method in turn invoke the setter method - JInvocation jinvocation = jblock.invoke(setterMethod); - // passing the same list of arguments - for (JVar jvar : jvars) - jinvocation.arg(jvar); - // and return "this" - jblock._return(JExpr._this()); - return; - } - }, - FLUENT_LIST_SETTER - { - /** - * Create a fluent setter method for List, with support of variable arguments. - */ - @Override - public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) - { - JMethod listGetterMethod = fluentMethodInfo.getJmethod(); - String name = listGetterMethod.name(); - // Create a with* method for the respective List get* method. - int mods = JMod.PUBLIC | listGetterMethod.mods().getValue() & JMod.FINAL; - JMethod fluentMethod = implClass.method(mods, implClass, - FLUENT_SETTER_METHOD_PREFIX + name.substring(GETTER_METHOD_PREFIX_LEN)); - if (fluentMethodInfo.isOverride()) - fluentMethod.annotate(Override.class); - JType returnJType = listGetterMethod.type(); - // As is already checked in isListGetterMethod(JMethod): - // 1) the return type must be a subtype of JClass; and - // 2) the number of type parameters must be 1 - JClass returnJClass = JClass.class.cast(returnJType); - List typeParams = returnJClass.getTypeParameters(); - assert typeParams.size() == 1; - JClass typeParam = typeParams.get(0); - // Support variable arguments - JVar jvarParam = fluentMethod.varParam(typeParam, VALUES); - JBlock body = fluentMethod.body(); - JConditional cond = body._if( - jvarParam.ne( - JExpr._null())); - JForEach forEach = cond._then() - .forEach( - typeParam, VALUE, JExpr.ref(VALUES)); - JInvocation addInvocation = forEach.body() - .invoke( - JExpr.invoke(listGetterMethod), "add"); - addInvocation.arg( - JExpr.ref(VALUE)); - // and return "this" - body._return( - JExpr._this()); - return; - } - }, - FLUENT_COLLECTION_SETTER - { + FLUENT_SETTER { + /** + * Adds a fluent api method, which invokes the given setter method, to the given class. + * This applies to both simple property setter method and + * indexed property setter method. + */ + @Override + public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) { + JMethod setterMethod = fluentMethodInfo.getJmethod(); + String name = setterMethod.name(); + String propName = name.substring(GETTER_METHOD_PREFIX_LEN); + // Create a with* method for the respective set* method. + int mods = JMod.PUBLIC | setterMethod.mods().getValue() & JMod.FINAL; + JMethod fluentMethod = implClass.method(mods, implClass, + FLUENT_SETTER_METHOD_PREFIX + propName); + fluentMethod.javadoc().add(setterMethod.javadoc()); + if (fluentMethodInfo.isOverride()) { + fluentMethod.annotate(Override.class); + } + JVar[] jvars = setterMethod.listParams(); + // jvars.length == 1 means simple property setter method. + // jvars.length == 2 means indexed property setter method. + assert jvars.length == 1 || jvars.length == 2; + // with the same parameter(s) as the set* method + for (JVar jvar : jvars) { + fluentMethod.param(jvar.mods().getValue(), jvar.type(), jvar.name()); + fluentMethod.javadoc().addParam(jvar) + .append("allowed object is\n") + .append(jvar.type().isPrimitive() || jvar.type().isArray() ? jvar.type().fullName() : jvar.type()); + } + JBlock jblock = fluentMethod.body(); + // The with* method in turn invoke the setter method + JInvocation jinvocation = jblock.invoke(setterMethod); + // passing the same list of arguments + for (JVar jvar : jvars) { + jinvocation.arg(jvar); + } + + // and return "this" + jblock._return(JExpr._this()); + fluentMethod.javadoc().addReturn().append("The class instance"); + return; + } + }, + FLUENT_LIST_SETTER { + /** + * Create a fluent setter method for List, with support of variable arguments. + */ + @Override + public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) { + JMethod listGetterMethod = fluentMethodInfo.getJmethod(); + String name = listGetterMethod.name(); + String propName = name.substring(GETTER_METHOD_PREFIX_LEN); + // Create a with* method for the respective List get* method. + int mods = JMod.PUBLIC | listGetterMethod.mods().getValue() & JMod.FINAL; + JMethod fluentMethod = implClass.method(mods, implClass, + FLUENT_SETTER_METHOD_PREFIX + propName); + if (fluentMethodInfo.isOverride()) { + fluentMethod.annotate(Override.class); + } + fluentMethod.javadoc().add("Adds objects to the list of " + propName + " using add method"); + JType returnJType = listGetterMethod.type(); + // As is already checked in isListGetterMethod(JMethod): + // 1) the return type must be a subtype of JClass; and + // 2) the number of type parameters must be 1 + JClass returnJClass = JClass.class.cast(returnJType); + List typeParams = returnJClass.getTypeParameters(); + assert typeParams.size() == 1; + JClass typeParam = typeParams.get(0); + // Support variable arguments + JVar jvarParam = fluentMethod.varParam(typeParam, VALUES); + fluentMethod.javadoc().addParam(VALUES).add("objects to add to the list " + propName); + + JBlock body = fluentMethod.body(); + JConditional cond = body._if(jvarParam.ne(JExpr._null())); + JForEach forEach = cond._then().forEach(typeParam, VALUE, JExpr.ref(VALUES)); + JInvocation addInvocation = forEach.body().invoke(JExpr.invoke(listGetterMethod), "add"); + addInvocation.arg(JExpr.ref(VALUE)); + + // and return "this" + body._return(JExpr._this()); + fluentMethod.javadoc().addReturn().append("The class instance"); + return; + } + }, + FLUENT_COLLECTION_SETTER { // Originally proposed by Alex Wei ozgwei@dev.java.net: // https://jaxb2-commons.dev.java.net/issues/show_bug.cgi?id=12 - /** - * Create a fluent setter method for List, with support of a java.util.Collection argument. - */ - @Override - public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) - { - JMethod listGetterMethod = fluentMethodInfo.getJmethod(); - String name = listGetterMethod.name(); - // Create a with* method for the respective List get* method. - int mods = JMod.PUBLIC | listGetterMethod.mods().getValue() & JMod.FINAL; - JMethod fluentMethod = implClass.method(mods, implClass, - FLUENT_SETTER_METHOD_PREFIX + name.substring(GETTER_METHOD_PREFIX_LEN)); - if (fluentMethodInfo.isOverride()) - fluentMethod.annotate(Override.class); - JType returnJType = listGetterMethod.type(); - // As is already checked in isListGetterMethod(JMethod): - // 1) the return type must be a subtype of JClass; and - // 2) the number of type parameters must be 1 - JClass returnJClass = JClass.class.cast(returnJType); - List typeParams = returnJClass.getTypeParameters(); - assert typeParams.size() == 1; - JClass typeParam = typeParams.get(0); - // Support Collection with type parameter - JClass narrowedCollectionJClass = implClass.owner().ref(Collection.class).narrow(typeParam); - JVar jvarParam = fluentMethod.param(narrowedCollectionJClass, VALUES); - JBlock body = fluentMethod.body(); - JConditional cond = body._if( - jvarParam.ne( - JExpr._null())); - JInvocation addInvocation = cond._then() - .invoke( - JExpr.invoke(listGetterMethod), "addAll"); - addInvocation.arg(jvarParam); - // and return "this" - body._return( - JExpr._this()); - return; - } - } - ; + /** + * Create a fluent setter method for List, with support of a java.util.Collection argument. + */ + @Override + public void createFluentMethod(JDefinedClass implClass, FluentMethodInfo fluentMethodInfo) { + JMethod listGetterMethod = fluentMethodInfo.getJmethod(); + String name = listGetterMethod.name(); + String propName = name.substring(GETTER_METHOD_PREFIX_LEN); + // Create a with* method for the respective List get* method. + int mods = JMod.PUBLIC | listGetterMethod.mods().getValue() & JMod.FINAL; + JMethod fluentMethod = implClass.method(mods, implClass, + FLUENT_SETTER_METHOD_PREFIX + propName); + if (fluentMethodInfo.isOverride()) { + fluentMethod.annotate(Override.class); + } + fluentMethod.javadoc().add("Adds objects to the list of " + propName + " using addAll method"); + JType returnJType = listGetterMethod.type(); + // As is already checked in isListGetterMethod(JMethod): + // 1) the return type must be a subtype of JClass; and + // 2) the number of type parameters must be 1 + JClass returnJClass = JClass.class.cast(returnJType); + List typeParams = returnJClass.getTypeParameters(); + assert typeParams.size() == 1; + JClass typeParam = typeParams.get(0); + // Support Collection with type parameter + JClass narrowedCollectionJClass = implClass.owner().ref(Collection.class).narrow(typeParam); + JVar jvarParam = fluentMethod.param(narrowedCollectionJClass, VALUES); + fluentMethod.javadoc().addParam(VALUES).add("objects to add to the list " + propName); + + JBlock body = fluentMethod.body(); + JConditional cond = body._if(jvarParam.ne(JExpr._null())); + JInvocation addInvocation = cond._then().invoke(JExpr.invoke(listGetterMethod), "addAll"); + addInvocation.arg(jvarParam); + + // and return "this" + body._return(JExpr._this()); + fluentMethod.javadoc().addReturn().append("The class instance"); + return; + } + }; + private static final String VALUE = "value"; - private static final String VALUES = "values"; - public static final String GETTER_METHOD_PREFIX = "get"; + private static final String VALUES = "values"; + public static final String GETTER_METHOD_PREFIX = "get"; public static final String SETTER_METHOD_PREFIX = "set"; public static final String FLUENT_SETTER_METHOD_PREFIX = "with"; public static final String PARAMETERIZED_LIST_PREFIX = List.class.getName() + "<";