Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/maven-build-action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
branches: [ master, jaxb-tools-4.0.x, jaxb-tools-3.x, jaxb-tools-2.x, 0.15.x ]
pull_request:
branches: [ master, jaxb-tools-4.0.x, jaxb-tools-3.x, jaxb-tools-2.x, 0.15.x ]
workflow_dispatch:
## Allow's manual runs

jobs:
build_and_test:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.jvnet.jaxb.plugin.commons_lang;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.ErrorHandler;

import com.sun.codemodel.JCodeModel;
Expand All @@ -32,7 +34,7 @@

/**
* Automatically generates the toString(), hashCode() and equals() methods
* using Jakarta's commons-lang.
* using org.apache.commons:commons-lang3.
*
* Supports the optional ToStringStyle command line parameter to specify
* the style for use within the toString method.
Expand All @@ -50,11 +52,11 @@
* Example 2:
*
* -Xcommons-lang
* -Xcommons-lang:ToStringStyle=my.CustomToStringStyle
* -Xcommons-lang:ToStringStyle=my.CustomToStringStyleClass
*
* to specify the use of
*
* my.CustomToStringStyle, which must be a subclass of
* my.CustomToStringStyleClass, which must be a subclass of
*
* org.apache.commons.lang3.builder.ToStringStyle, and contains a public no-arg constructor.
*
Expand All @@ -71,8 +73,11 @@ public class XjcCommonsLangPlugin extends Plugin
private static final String EQUALSBUILDER_CLASSNAME = "org.apache.commons.lang3.builder.EqualsBuilder";
private static final String HASHCODEBUILDER_CLASSNAME = "org.apache.commons.lang3.builder.HashCodeBuilder";
private static final String TOSTRINGBUILDER_CLASSNAME = "org.apache.commons.lang3.builder.ToStringBuilder";

protected Log logger = LogFactory.getLog(getClass());

private String toStringStyle = "MULTI_LINE_STYLE";
private Class<?> customToStringStyle;
private String toStringClass = null;

@Override
public String getOptionName()
Expand All @@ -83,13 +88,20 @@ public String getOptionName()
@Override
public String getUsage()
{
return " -Xcommons-lang : generate toString(), hashCode() and equals() for generated code using Jakarta's common-lang\n"
+ " [-Xcommons-lang:ToStringStyle=MULTI_LINE_STYLE\n\t"
+ "| DEFAULT_STYLE\n\t"
+ "| NO_FIELD_NAMES_STYLE\n\t"
+ "| SHORT_PREFIX_STYLE\n\t"
+ "| SIMPLE_STYLE\n\t"
+ "| <Fully qualified class name of a ToStringStyle subtype>]\n"
return " -Xcommons-lang : generate toString(), hashCode() and equals() for generated code using Jakarta's common-lang "
+ "[\n"
+ "\t -Xcommons-lang:ToStringStyle=MULTI_LINE_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=DEFAULT_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=NO_FIELD_NAMES_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=SHORT_PREFIX_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=SIMPLE_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=NO_CLASS_NAME_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=JSON_STYLE\n"
+ "\t| -Xcommons-lang:ToStringStyle=<any static final variables inside org.apache.commons.lang3.builder.ToStringStyle following regex ^[A-Z0-9_]+>$\n"
+ "\t| -Xcommons-lang:ToStringStyle=<Fully qualified class name of a ToStringStyle subtype>\n"
+ "]\n"
+ " Note: custom ToStringStyle class is needed if you wish to turn off setUseIdentityHashCode on top of MULTI_LINE_STYLE"
+ "\n"
;
}

Expand All @@ -115,22 +127,25 @@ private void createToStringMethod(JDefinedClass implClass)
implClass.method(JMod.PUBLIC, codeModel.ref(String.class), "toString");
// Annotate with @Override
toStringMethod.annotate(Override.class);
final JExpression toStringStyleExpr =
customToStringStyle == null
? codeModel.ref(TOSTRINGSTYLE_CLASSNAME)
.staticRef(toStringStyle)
: JExpr._new(
codeModel.ref(customToStringStyle))
;

//Build body of method
final JExpression toStringStyleExpr;
if (toStringClass == null) {
// Call Static Reference i.e. ToStringStyle.JSON_STYLE;
toStringStyleExpr = codeModel.ref(TOSTRINGSTYLE_CLASSNAME).staticRef(toStringStyle);
} else {
//Direct class passed and calls new on it;
toStringStyleExpr = JExpr._new(codeModel.ref(toStringClass));
}

// Invoke ToStringBuilder.reflectionToString(Object,StringStyle)
toStringMethod.body()
._return(
codeModel.ref(TOSTRINGBUILDER_CLASSNAME)
.staticInvoke("reflectionToString")
.arg(JExpr._this())
.arg(toStringStyleExpr)
);
return;
._return(
codeModel.ref(TOSTRINGBUILDER_CLASSNAME)
.staticInvoke("reflectionToString")
.arg(JExpr._this())
.arg(toStringStyleExpr)
);
}

private void createEqualsMethod(JDefinedClass implClass)
Expand Down Expand Up @@ -171,24 +186,31 @@ private void createHashCodeMethod(JDefinedClass implClass)
public int parseArgument(Options opt, String[] args, int i)
throws BadCommandLineException
{
// eg. -Xcommons-lang ToStringStyle=SIMPLE_STYLE
// eg.
// -Xcommons-lang:ToStringStyle=SIMPLE_STYLE
// or
// -Xcommons-lang:ToStringStyle=<Fully qualified class name of a ToStringStyle subtype>
String arg = args[i].trim();

if (arg.startsWith(TOSTRING_STYLE_PARAM))
{
toStringStyle = arg.substring(TOSTRING_STYLE_PARAM.length());
try {
Class.forName(TOSTRINGSTYLE_CLASSNAME).getField(toStringStyle);
String value = arg.substring(TOSTRING_STYLE_PARAM.length());

if (value.matches("^[A-Z0-9_]+$")) {
try {
Class.forName(TOSTRINGSTYLE_CLASSNAME).getField(value);
} catch (NoSuchFieldException | ClassNotFoundException | SecurityException e) {
logger.error("Could not verify : '" + TOSTRINGSTYLE_CLASSNAME + "." + value + "'. Assume it's not visible to generator.", e);
}
toStringStyle = value;
return 1;
} catch (ClassNotFoundException | SecurityException e) {
throw new BadCommandLineException(e.getMessage());
} catch (NoSuchFieldException ignore) {
}
try {
customToStringStyle = Class.forName(toStringStyle);
Class.forName(value);
} catch (ClassNotFoundException e) {
throw new BadCommandLineException(e.getMessage());
logger.warn("Could not find class: '" + value + "'. Assume it's not visible to generator.");
}
toStringClass = value;
return 1;
}
return 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright 2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jvnet.jaxb.plugin.commons_lang;

import com.sun.codemodel.*;
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.model.CClassInfo;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.xml.sax.ErrorHandler;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

class XjcCommonsLangPluginTest {

@Mock
private Outline outline;
@Mock
private Options options;
@Mock
private ErrorHandler errorHandler;
@Mock
private CClassInfo cClassInfo;

private JDefinedClass implClass;
private XjcCommonsLangPlugin plugin;

@BeforeEach
void setUp() throws Exception {
MockitoAnnotations.openMocks(this);

JCodeModel codeModel = new JCodeModel();
implClass = codeModel._class("TestGeneratedClass");

ClassOutline classOutline = new TestableClassOutline(cClassInfo, implClass);
when(outline.getClasses()).thenReturn((Collection) Collections.singletonList(classOutline));

plugin = new XjcCommonsLangPlugin();
}

@Test
void testGetOptionName() {
assertEquals("Xcommons-lang", plugin.getOptionName());
}

@Test
void testGetUsage() {
String usage = plugin.getUsage();
assertNotNull(usage);
assertEquals(" -Xcommons-lang : generate toString(), hashCode() and equals() for generated code using Jakarta's common-lang [\n\t"
+ " -Xcommons-lang:ToStringStyle=MULTI_LINE_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=DEFAULT_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=NO_FIELD_NAMES_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=SHORT_PREFIX_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=SIMPLE_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=NO_CLASS_NAME_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=JSON_STYLE\n\t"
+ "| -Xcommons-lang:ToStringStyle=<any static final variables inside org.apache.commons.lang3.builder.ToStringStyle following regex ^[A-Z0-9_]+>$\n\t"
+ "| -Xcommons-lang:ToStringStyle=<Fully qualified class name of a ToStringStyle subtype>\n"
+ "]\n"
+ " Note: custom ToStringStyle class is needed if you wish to turn off setUseIdentityHashCode on top of MULTI_LINE_STYLE\n", usage);
}

@Test
void testRunGeneratesAllMethods() throws Exception {
plugin.run(outline, options, errorHandler);

assertTrue(hasMethod(implClass, "toString"), "toString() should be generated");
assertTrue(hasMethod(implClass, "equals"), "equals() should be generated");
assertTrue(hasMethod(implClass, "hashCode"), "hashCode() should be generated");
}

@Test
void testParseArgumentToStringStyleStandard() throws BadCommandLineException {
String arg = "-Xcommons-lang:ToStringStyle=SIMPLE_STYLE";
assertEquals(1, plugin.parseArgument(options, new String[]{arg}, 0));

plugin.run(outline, options, errorHandler);

assertTrue(hasMethod(implClass, "toString"), "toString() should be generated");
}

@Test
void testParseArgumentToStringStyleCustom() throws BadCommandLineException {
String arg = "-Xcommons-lang:ToStringStyle=java.lang.String";
assertEquals(1, plugin.parseArgument(options, new String[]{arg}, 0));

plugin.run(outline, options, errorHandler);

assertTrue(hasMethod(implClass, "toString"), "toString() should be generated");
}

@Test
void testParseArgumentUnknown() throws BadCommandLineException {
assertEquals(0, plugin.parseArgument(options, new String[]{"-Xunknown-param"}, 0));

plugin.run(outline, options, errorHandler);

assertTrue(hasMethod(implClass, "toString"), "toString() should be generated");
assertTrue(hasMethod(implClass, "equals"), "equals() should be generated");
assertTrue(hasMethod(implClass, "hashCode"), "hashCode() should be generated");
}


@Test
void testCreateToStringMethodWithCustomClassBranch() throws Exception {
String arg = "-Xcommons-lang:ToStringStyle=java.lang.String";
plugin.parseArgument(options, new String[]{arg}, 0);

assertTrue(plugin.run(outline, options, errorHandler));

assertTrue(hasMethod(implClass, "toString"), "toString() should be generated using custom class branch");
}

private boolean hasMethod(JDefinedClass clazz, String methodName) {
for (JMethod m : clazz.methods()) {
if (m.name().equals(methodName)) {
return true;
}
}
return false;
}

private Optional<JMethod> getMethod(JDefinedClass clazz, String methodName) {
return clazz.methods().stream()
.filter(anno -> anno.name().equals(methodName))
.findFirst();
}

public static class TestableClassOutline extends ClassOutline {
public TestableClassOutline(CClassInfo target, JDefinedClass implClass) {
super(target, null, null, implClass);
}

@Override
public Outline parent() {
return null;
}
}
}
47 changes: 47 additions & 0 deletions jaxb-plugins-parent/tests/commons_lang_custom_class/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-plugins-tests</artifactId>
<version>4.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>jaxb-plugins-test-commons_lang_custom_class</artifactId>
<packaging>jar</packaging>
<name>JAXB Tools :: JAXB Plugins :: Test [commons_lang_custom_class]</name>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-maven-plugin-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-maven-plugin</artifactId>
<configuration>
<extension>true</extension>
<args>
<arg>-Xcommons-lang</arg>
<arg>-Xcommons-lang:ToStringStyle=com.example.CustomToStringStyle</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb</groupId>
<artifactId>jaxb-plugins</artifactId>
</plugin>
</plugins>
</configuration>
</plugin>
</plugins>
</build>
</project>
Loading
Loading