diff --git a/plugin/src/main/java/com/kscs/util/plugins/xjc/BuilderGenerator.java b/plugin/src/main/java/com/kscs/util/plugins/xjc/BuilderGenerator.java
index dcd31ef..e9d7ddb 100755
--- a/plugin/src/main/java/com/kscs/util/plugins/xjc/BuilderGenerator.java
+++ b/plugin/src/main/java/com/kscs/util/plugins/xjc/BuilderGenerator.java
@@ -106,7 +106,7 @@ class BuilderGenerator {
this.builderClass = new GenerifiedClass(builderOutline.getDefinedBuilderClass(), BuilderGenerator.PARENT_BUILDER_TYPE_PARAMETER_NAME);
this.resources = ResourceBundle.getBundle(BuilderGenerator.class.getName());
this.implement = !this.builderClass.raw.isInterface();
- if (builderOutline.getClassOutline().getSuperClass() == null || !builderOutline.getClassOutline().getSuperClass().isLocal()) {
+ if (!isSuperClassBuildable(builderOutline.getClassOutline())) {
final JMethod endMethod = this.builderClass.raw.method(JMod.PUBLIC, this.builderClass.typeParam, this.settings.getEndMethodName());
if (this.implement) {
this.parentBuilderField = this.builderClass.raw.field(JMod.PROTECTED | JMod.FINAL, this.builderClass.typeParam, BuilderGenerator.PARENT_BUILDER_PARAM_NAME);
@@ -212,7 +212,7 @@ private void generateAddMethods(final PropertyOutline propertyOutline,
if (childBuilderOutline != null && !childBuilderOutline.getClassOutline().getImplClass().isAbstract()) {
final JClass builderWithMethodReturnType = childBuilderOutline.getBuilderClass().narrow(this.builderClass.type.wildcard());
addMethod = this.builderClass.raw.method(JMod.PUBLIC, builderWithMethodReturnType, PluginContext.ADD_METHOD_PREFIX + propertyName);
- generateBuilderMethodJavadoc(addMethod, "add", fieldName, schemaAnnotation);
+ generateBuilderMethodJavadoc(addMethod, ADD_METHOD_PREFIX, fieldName, schemaAnnotation);
} else {
addMethod = null;
}
@@ -478,10 +478,10 @@ void generateBuilderMemberOverride(final PropertyOutline superPropertyOutline, f
final BuilderOutline childBuilderOutline = getBuilderDeclaration(fieldType);
if (childBuilderOutline != null && !childBuilderOutline.getClassOutline().getImplClass().isAbstract()) {
final JClass builderFieldElementType = childBuilderOutline.getBuilderClass().narrow(this.builderClass.type.wildcard());
- final JMethod addMethod = this.builderClass.raw.method(JMod.PUBLIC, builderFieldElementType, WITH_METHOD_PREFIX + superPropertyName);
- generateBuilderMethodJavadoc(addMethod, WITH_METHOD_PREFIX, superPropertyOutline.getFieldName(), propertyOutline.getSchemaAnnotationText().orElse(null));
+ final JMethod withChildBuilderMethod = this.builderClass.raw.method(JMod.PUBLIC, builderFieldElementType, WITH_METHOD_PREFIX + superPropertyName);
+ generateBuilderMethodJavadoc(withChildBuilderMethod, WITH_METHOD_PREFIX, superPropertyOutline.getFieldName(), propertyOutline.getSchemaAnnotationText().orElse(null));
if (this.implement) {
- addMethod.body()._return(JExpr.cast(builderFieldElementType, JExpr._super().invoke(addMethod)));
+ withChildBuilderMethod.body()._return(JExpr.cast(builderFieldElementType, JExpr._super().invoke(withChildBuilderMethod)));
}
}
}
@@ -535,7 +535,7 @@ JMethod generateNewBuilderMethod() {
}
JMethod generateCopyOfMethod(final TypeOutline paramType, final boolean partial) {
- if (paramType.getSuperClass() != null && paramType.getSuperClass().isLocal()) {
+ if (isSuperClassBuildable(paramType)) {
generateCopyOfMethod(paramType.getSuperClass(), partial);
}
final JMethod copyOfMethod = this.definedClass.method(JMod.PUBLIC | JMod.STATIC, this.builderClass.raw.narrow(Void.class), this.pluginContext.buildCopyMethodName);
@@ -563,7 +563,7 @@ JMethod generateNewCopyBuilderMethod(final boolean partial) {
copyBuilderMethod.body()._return(copyGenerator.generatePartialArgs(this.pluginContext._new((JClass)copyBuilderMethod.type()).arg(parentBuilderParam).arg(JExpr._this()).arg(JExpr.TRUE)));
copyBuilderConvenienceMethod.body()._return(copyConvenienceGenerator.generatePartialArgs(this.pluginContext.invoke(this.settings.getNewCopyBuilderMethodName()).arg(JExpr._null())));
}
- if (this.typeOutline.getSuperClass() != null && this.typeOutline.getSuperClass().isLocal()) {
+ if (isSuperClassBuildable(this.typeOutline)) {
copyBuilderMethod.annotate(Override.class);
copyBuilderConvenienceMethod.annotate(Override.class);
}
@@ -571,7 +571,7 @@ JMethod generateNewCopyBuilderMethod(final boolean partial) {
}
private JMethod generateConveniencePartialCopyMethod(final TypeOutline paramType, final JMethod partialCopyOfMethod, final String methodName, final JExpression propertyTreeUseArg) {
- if (paramType.getSuperClass() != null && paramType.getSuperClass().isLocal()) {
+ if (isSuperClassBuildable(paramType)) {
generateConveniencePartialCopyMethod(paramType.getSuperClass(), partialCopyOfMethod, methodName, propertyTreeUseArg);
}
final JMethod conveniencePartialCopyMethod = this.definedClass.method(JMod.PUBLIC | JMod.STATIC, this.builderClass.raw.narrow(Void.class), methodName);
@@ -604,7 +604,7 @@ final void generateCopyToMethod(final boolean partial) {
final CopyGenerator cloneGenerator = this.pluginContext.createCopyGenerator(copyToMethod, partial);
final JBlock body = copyToMethod.body();
final JVar otherRef;
- if (this.typeOutline.getSuperClass() != null && this.typeOutline.getSuperClass().isLocal()) {
+ if (isSuperClassBuildable(this.typeOutline)) {
body.add(cloneGenerator.generatePartialArgs(this.pluginContext.invoke(JExpr._super(), copyToMethod.name()).arg(otherParam)));
}
otherRef = otherParam;
@@ -620,14 +620,14 @@ final void generateCopyConstructor(final boolean partial) {
final JVar otherParam = constructor.param(JMod.FINAL, this.typeOutline.getImplClass(), BuilderGenerator.OTHER_PARAM_NAME);
final JVar copyParam = constructor.param(JMod.FINAL, this.pluginContext.codeModel.BOOLEAN, BuilderGenerator.COPY_FLAG_PARAM_NAME);
final CopyGenerator cloneGenerator = this.pluginContext.createCopyGenerator(constructor, partial);
- if (this.typeOutline.getSuperClass() != null && this.typeOutline.getSuperClass().isLocal()) {
+ if (isSuperClassBuildable(this.typeOutline)) {
constructor.body().add(cloneGenerator.generatePartialArgs(this.pluginContext._super().arg(parentBuilderParam).arg(otherParam).arg(copyParam)));
} else {
constructor.body().assign(JExpr._this().ref(this.parentBuilderField), parentBuilderParam);
}
final JConditional ifNullStmt = constructor.body()._if(otherParam.ne(JExpr._null()));
final JBlock body;
- if (!this.settings.isCopyAlways() && (this.typeOutline.getSuperClass() == null || !this.typeOutline.getSuperClass().isLocal())) {
+ if (!this.settings.isCopyAlways() && !isSuperClassBuildable(this.typeOutline)) {
final JConditional ifCopyStmt = ifNullStmt._then()._if(copyParam);
ifCopyStmt._else().assign(this.storedValueField, otherParam);
ifNullStmt._else().assign(this.storedValueField, JExpr._null());
@@ -702,7 +702,6 @@ private void generateFieldCopyExpressions(final CopyGenerator cloneGenerator, fi
}
public void buildProperties() throws SAXException {
- final TypeOutline superClass = this.typeOutline.getSuperClass();
final JMethod initMethod;
final JVar productParam;
final JBlock initBody;
@@ -726,9 +725,11 @@ public void buildProperties() throws SAXException {
}
}
}
- if (superClass != null && superClass.isLocal()) {
+ if (isSuperClassBuildable(this.typeOutline)) {
+ final TypeOutline superClass = this.typeOutline.getSuperClass();
BuilderOutline superClassBuilder = getBuilderDeclaration(superClass.getImplClass());
- if (superClassBuilder == null) throw new RuntimeException("Cannot find builder class name " + this.settings.getBuilderClassName().getClassName() + " of: " + superClass.getImplClass());
+ if (superClassBuilder == null)
+ throw new RuntimeException("Cannot find builder class name " + this.settings.getBuilderClassName().getClassName() + " of: " + superClass.getImplClass());
generateExtendsClause(superClassBuilder);
if (this.implement) initBody._return(JExpr._super().invoke(initMethod).arg(productParam));
generateBuilderMemberOverrides(superClass);
@@ -806,7 +807,7 @@ BuilderOutline getReferencedBuilderDeclaration(final PropertyOutline propertyOut
if(referencedDefinedClass != null) {
return this.builderOutlines.get(referencedDefinedClass.fullName());
} else {
- return getReferencedBuilderOutline(propertyOutline.getRawType());
+ return getBuilderDeclaration(propertyOutline.getRawType());
}
}
@@ -888,7 +889,9 @@ private BuilderOutline getReferencedBuilderOutline(final JType type) {
if (this.pluginContext.getClassOutline(type) == null && this.pluginContext.getEnumOutline(type) == null && type.isReference() && !type.isArray() && type.fullName().contains(".")) {
final Class> runtimeParentClass;
try {
- runtimeParentClass = Class.forName(type.binaryName());
+ // The Context ClassLoader is used to allow for tests to include files from previous runs on the classpath.
+ // PluginRunTest#testGenerateNetex contains an example.
+ runtimeParentClass = Class.forName(type.binaryName(), true, Thread.currentThread().getContextClassLoader());
} catch (final ClassNotFoundException e) {
return null;
}
@@ -917,4 +920,11 @@ private String getMessage(final String resourceKey, final Object... args) {
return MessageFormat.format(this.resources.getString(resourceKey), args);
}
+ private boolean isSuperClassBuildable(TypeOutline classOutline) {
+ var superClass = classOutline.getSuperClass();
+ if (superClass == null) {
+ return false;
+ }
+ return superClass.isLocal() || getReferencedBuilderOutline(superClass.getImplClass()) != null;
+ }
}
diff --git a/plugin/src/test/java/com/kscs/util/test/PluginRunTest.java b/plugin/src/test/java/com/kscs/util/test/PluginRunTest.java
index f44f448..66d17cf 100644
--- a/plugin/src/test/java/com/kscs/util/test/PluginRunTest.java
+++ b/plugin/src/test/java/com/kscs/util/test/PluginRunTest.java
@@ -24,6 +24,8 @@
package com.kscs.util.test;
import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -134,6 +136,44 @@ public void generateAndCompile(final String subDir, final String... pluginArgs)
compileTestCode(subDir);
}
+ @Test
+ public void testGenerateSiri() throws Exception {
+ generateAndCompile("siri",
+ inFile("siri.xsd"),
+ "-Xfluent-builder"
+ );
+ }
+
+ @Test
+ public void testGenerateNetex() throws Exception {
+ final var subDir = "netex";
+ final var episodeFile = generatedSourcesDir.resolve(subDir).resolve("siri.episode");
+ final var compiledCodeSubDir = compiledCodeDir.resolve(subDir);
+
+ generateAndCompile(subDir,
+ "-episode", episodeFile.toString(),
+ inFile("siri.xsd"),
+ "-Xfluent-builder"
+ );
+
+ ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader testClassLoader =
+ URLClassLoader.newInstance(new URL[]{compiledCodeSubDir.toUri().toURL()}, previousClassLoader);
+
+ try {
+ Thread.currentThread().setContextClassLoader(testClassLoader);
+
+ runPlugin(subDir,
+ "-b", episodeFile.toString(),
+ inFile("netex.xsd"),
+ "-Xfluent-builder"
+ );
+ compileTestCode(subDir);
+ } finally {
+ Thread.currentThread().setContextClassLoader(previousClassLoader);
+ }
+ }
+
@Test
public void testGenerateAll() throws Exception {
generateAndCompile("all","-b", inFile("binding-config.xjb"),
diff --git a/plugin/src/test/resources/netex.xsd b/plugin/src/test/resources/netex.xsd
new file mode 100644
index 0000000..9e89dfe
--- /dev/null
+++ b/plugin/src/test/resources/netex.xsd
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/plugin/src/test/resources/siri.xsd b/plugin/src/test/resources/siri.xsd
new file mode 100644
index 0000000..c7958bd
--- /dev/null
+++ b/plugin/src/test/resources/siri.xsd
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+ Requested end time for subscription.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Type for reference to a TRAIN NUMBER
+
+
+
+
+
+
+
+ Type for identifier of an TRAIN NUMBER
+
+
+
+