Skip to content

Commit

Permalink
Optimized internal API to copy annotation members.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmak committed Jan 23, 2023
1 parent 57ece44 commit 4c200e7
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 246 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
target/
playground/
.project
.classpath
.settings/
Expand Down
15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ To use the plugin from Ant you will need something like the following in your bu
<path id="xjc.classpath">
<fileset dir="libs">
<include name="jaxb2-basics-tools-3.0.0.jar" />
<include name="jaxb-xew-plugin-2.0.jar" />
<include name="jaxb-xew-plugin-2.1.jar" />
</fileset>
</path>
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
Expand Down Expand Up @@ -421,7 +421,7 @@ dependencies {
compile "org.glassfish.jaxb:jaxb-xjc:${jaxbVersion}"
compile "org.glassfish.jaxb:jaxb-runtime:${jaxbVersion}"
xjc "com.github.jaxb-xew-plugin:jaxb-xew-plugin:2.0"
xjc "com.github.jaxb-xew-plugin:jaxb-xew-plugin:2.1"
xjc "codes.rafael.jaxb2_commons:jaxb2-fluent-api:3.0.0"
}
Expand Down Expand Up @@ -594,12 +594,10 @@ The plugin flow consists of the following parts:

There are many pitfalls in JAXB Code Model API which are forcing the developer to use dirty tricks (like accessing private fields) in order to implement the manipulation of code model. Among others:

* [JAXB-784](https://github.com/javaee/jaxb-v2/issues/784) is about NPE in `JAnnotationUse#getAnnotationMembers()` method.
* [JAXB-884](https://github.com/javaee/jaxb-v2/issues/884) is about ClassCastException in `JAnnotationArrayMember#annotations()` method.
* [JAXB-878](https://github.com/javaee/jaxb-v2/issues/878) and [JAXB-879](https://github.com/javaee/jaxb-v2/issues/879) describe the lack of public getters for class fields.
* [JAXB-957](https://github.com/javaee/jaxb-v2/issues/957) mentions what need to be added to make it possible for the inner class to be moved to another class or package.
* [JAXB-883](https://github.com/javaee/jaxb-v2/issues/883) does not allow to learn if "simpleMode" setting is enabled, which in its turn controls plural form for collection property names. There are however some more difficulties to overcome.
* [JAXB-1107](https://github.com/javaee/jaxb-v2/issues/1107) – marshalling of text nodes for mixed-mode contents
* [issue #957](https://github.com/eclipse-ee4j/jaxb-ri/issues/957) mentions what need to be added to make it possible for the inner class to be moved to another class or package.
* [issue #883](https://github.com/eclipse-ee4j/jaxb-ri/issues/883) does not allow to learn if "simpleMode" setting is enabled, which in its turn controls plural form for collection property names. There are however some more difficulties to overcome.
* [issue #1677](https://github.com/eclipse-ee4j/jaxb-ri/issues/1677) add/implement JVar.annotate(JAnnotationUse annotation).
* [issue #1679](https://github.com/eclipse-ee4j/jaxb-ri/issues/1679) add/implement JAnnotationUse.param(String name, JAnnotationValue annotationValue).

## Authors

Expand All @@ -612,6 +610,7 @@ Original code by [Bjarne Hansen](http://www.conspicio.dk/blog/bjarne/jaxb-xmlele
* [Colin Fairless](https://github.com/colin-yell/)
* [Patrick Crocker](https://github.com/patrickcrocker/)
* [Kermit The Frog](https://github.com/kermit-the-frog/)
* [Dominik Broj](https://github.com/thetric)
* and others...

## License
Expand Down
93 changes: 31 additions & 62 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,60 +113,6 @@
</plugins>
</build>
</profile>
<profile>
<id>test-coverage</id>
<activation>
<jdk>[,9)</jdk>
</activation>

<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.7</version>
<configuration>
<formats>
<format>xml</format>
<format>html</format>
</formats>
<check />
</configuration>
<executions>
<execution>
<id>cobertura-report</id>
<phase>verify</phase>
<goals>
<goal>cobertura</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- This profile publishes code coverage report generated by Cobertura on https://coveralls.io. -->
<profile>
<id>coveralls</id>

<build>
<plugins>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>4.4.1</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<developers>
Expand All @@ -189,12 +135,11 @@

<dependencyManagement>
<dependencies>
<!-- Remove this dependency management after https://github.com/highsource/jaxb2-basics/pull/119 is resolved -->
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.8.2</version>
<type>pom</type>
<scope>import</scope>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
</dependencyManagement>
Expand Down Expand Up @@ -242,23 +187,24 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.22.0</version>
<version>3.24.2</version>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-assertj3</artifactId>
<version>2.9.0</version>
<version>2.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-jakarta-jaxb-impl</artifactId>
<version>2.9.0</version>
<version>2.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -290,5 +236,28 @@
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>create-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
2 changes: 1 addition & 1 deletion samples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<packaging>pom</packaging>

<properties>
<jaxb-xew-plugin.version>2.0-SNAPSHOT</jaxb-xew-plugin.version>
<jaxb-xew-plugin.version>2.1</jaxb-xew-plugin.version>
<jakarta-api.version>3.0.1</jakarta-api.version>
<jaxb2-basics.version>3.0.0</jaxb2-basics.version>
<jaxb2-maven-plugin.version>3.1.0</jaxb2-maven-plugin.version>
Expand Down
18 changes: 8 additions & 10 deletions src/main/java/com/sun/tools/xjc/addon/xew/Candidate.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.sun.tools.xjc.addon.xew;

import static com.sun.tools.xjc.addon.xew.CommonUtils.generableToString;
import static com.sun.tools.xjc.addon.xew.CommonUtils.getAnnotation;
import static com.sun.tools.xjc.addon.xew.CommonUtils.getAnnotationMemberExpression;
import static com.sun.tools.xjc.addon.xew.CommonUtils.getAnnotationMemberValue;
import static com.sun.tools.xjc.addon.xew.CommonUtils.getXsdDeclaration;
import static com.sun.tools.xjc.addon.xew.CommonUtils.isHiddenClass;
import static com.sun.tools.xjc.addon.xew.XmlElementWrapperPlugin.FACTORY_CLASS_NAME;
Expand All @@ -16,7 +15,6 @@
import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.tools.xjc.model.CClassInfo;
Expand Down Expand Up @@ -81,10 +79,10 @@ private String getTargetNamespace(CClassInfo candidateClassInfo, JClass xmlSchem
// see com.sun.tools.xjc.generator.bean.PackageOutlineImpl#calcDefaultValues()
for (JDefinedClass objectFactoryClass : objectFactoryClasses.values()) {
JAnnotationUse schemaAnnotation = getAnnotation(objectFactoryClass.getPackage(), xmlSchemaModelClass);
JExpression elementFormDefault = getAnnotationMemberExpression(schemaAnnotation, "elementFormDefault");
String elementFormDefault = getAnnotationMemberValue(schemaAnnotation, "elementFormDefault");

if (elementFormDefault != null && generableToString(elementFormDefault).endsWith(".QUALIFIED")) {
return generableToString(getAnnotationMemberExpression(schemaAnnotation, "namespace"));
if (elementFormDefault != null && elementFormDefault.endsWith(".QUALIFIED")) {
return getAnnotationMemberValue(schemaAnnotation, "namespace");
}
}
}
Expand All @@ -98,15 +96,15 @@ private void collectScopedElementInfos(JClass xmlElementDeclModelClass) {
// Only value Object Factory methods are inspected:
for (JMethod method : objectFactoryClasses.values().iterator().next().methods()) {
JAnnotationUse xmlElementDeclAnnotation = getAnnotation(method, xmlElementDeclModelClass);
JExpression scope = getAnnotationMemberExpression(xmlElementDeclAnnotation, "scope");
String scope = getAnnotationMemberValue(xmlElementDeclAnnotation, "scope");

if (scope == null || !dotClazz.equals(generableToString(scope))) {
if (scope == null || !dotClazz.equals(scope)) {
continue;
}

scopedElementInfos.put(method.name(),
new ScopedElementInfo(getAnnotationMemberExpression(xmlElementDeclAnnotation, "name"),
getAnnotationMemberExpression(xmlElementDeclAnnotation, "namespace"),
new ScopedElementInfo(getAnnotationMemberValue(xmlElementDeclAnnotation, "name"),
getAnnotationMemberValue(xmlElementDeclAnnotation, "namespace"),
method.params().get(0).type()));
}
}
Expand Down
63 changes: 35 additions & 28 deletions src/main/java/com/sun/tools/xjc/addon/xew/CommonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

Expand All @@ -12,8 +13,6 @@
import com.sun.codemodel.JAnnotationValue;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFormatter;
import com.sun.codemodel.JGenerable;
import com.sun.codemodel.JType;
Expand Down Expand Up @@ -76,38 +75,54 @@ public static JAnnotationValue getAnnotationMember(JAnnotationUse annotation, St
return null;
}

// FIXME: Workaround for https://java.net/jira/browse/JAXB-1040:
Map<String, JAnnotationValue> memberValues = getPrivateField(annotation, "memberValues");
Map<String, JAnnotationValue> memberValues = annotation.getAnnotationMembers();

if (memberValues == null) {
if (memberValues.isEmpty()) {
return null;
}

return memberValues.get(annotationMember);
}

/**
* Returns the value of annotation element as {@link JExpression}. For example, for annotation
* Copies the annotation member with a given name from source annotations to target annotations. If given member
* does not exist, then default value is used.
*/
public static void copyAnnotationMemberValue(JAnnotationUse sourceAnnotation, String annotationMember,
String defaultAnotationValue, JAnnotationUse targetAnnotation) {
JAnnotationValue annotationValue = getAnnotationMember(sourceAnnotation, annotationMember);

if (annotationValue == null) {
if (defaultAnotationValue != null) {
targetAnnotation.param(annotationMember, defaultAnotationValue);
}
return;
}

Map<String, JAnnotationValue> memberValues = getPrivateField(targetAnnotation, "memberValues");

if (memberValues == null) {
memberValues = new LinkedHashMap<>();
setPrivateField(targetAnnotation, "memberValues", memberValues);
}

memberValues.put(annotationMember, annotationValue);
}

/**
* Returns the value of annotation element as string. For example, for annotation
* <code>@XmlElementRef(name = "last-name", namespace = "http://mycompany.org/exchange", type = JAXBElement.class)</code>
* for member <code>name</code> the value <code>last-name</code> will be returned.
* for member <code>name</code> the value <code>"last-name"</code> will be returned, for member <code>type</code>
* the value <code>"jakarta.xml.bind.JAXBElement.class"</code> will be returned.
*/
public static JExpression getAnnotationMemberExpression(JAnnotationUse annotation, String annotationMember) {
public static String getAnnotationMemberValue(JAnnotationUse annotation, String annotationMember) {
JAnnotationValue annotationValue = getAnnotationMember(annotation, annotationMember);

if (annotationValue == null) {
return null;
}

// FIXME: Pending for https://java.net/jira/browse/JAXB-878
try {
// In most cases the value is some expression...
return getPrivateField(annotationValue, "value");
}
catch (IllegalArgumentException e) {
// ... and in some cases (like enum) do the conversion from JGenerable to JExpression
// (a bit unoptimal, since this expression is going to be converted back to string)
return JExpr.lit(generableToString(annotationValue));
}
return generableToString(annotationValue);
}

/**
Expand All @@ -119,17 +134,9 @@ public static void addAnnotation(JVar field, JAnnotationUse annotation) {
}

/**
* Remove the given {@code annotation} from the list of annotations for the given {@code field}.
*/
public static void removeAnnotation(JVar field, JAnnotationUse annotation) {
List<JAnnotationUse> annotations = getPrivateField(field, "annotations");
annotations.remove(annotation);
}

/**
* Check that given field property has name customization ({@code <jaxb:property name="..." />}).
* Check that given field property has name customization ({@code <jaxb:property name="..." />}). See also
* {@code org.glassfish.jaxb.core.api.impl.NameUtil}.
*
* @see <code>com.sun.xml.bind.api.impl.NameUtil</code>
* @see com.sun.codemodel.JJavaName
* @see com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty#getCustomization(XSComponent)
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.sun.tools.xjc.addon.xew;

import com.sun.codemodel.JExpression;
import com.sun.codemodel.JType;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
Expand Down Expand Up @@ -29,19 +28,19 @@ public final class ScopedElementInfo {
/**
* Element name ("post-office").
*/
public final JExpression name;
public final String name;

/**
* Element namespace ("http://foo.bar").
*/
public final JExpression namespace;
public final String namespace;

/**
* Element type ({@link String}).
*/
public final JType type;
public final JType type;

public ScopedElementInfo(JExpression name, JExpression namespace, JType type) {
public ScopedElementInfo(String name, String namespace, JType type) {
this.name = name;
this.namespace = namespace;
this.type = type;
Expand Down
Loading

0 comments on commit 4c200e7

Please sign in to comment.