/*
* Copyright 2006-2013 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 com.btmatthews.tools.xjc.addon.commons_lang3;
import com.sun.codemodel.*;
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.xml.sax.ErrorHandler;
/**
* Automatically generates the toString(), hashCode() and equals() methods
* using Jakarta's commons-lang3.
* <p/>
* Supports the optional ToStringStyle command line parameter to specify
* the style for use within the toString method.
* <p/>
* <pre>
* Example 1:
*
* -Xcommons-lang3
* -Xcommons-lang3:ToStringStyle=SIMPLE_STYLE
*
* to specify the use of
*
* org.apache.commons.lang.builder.ToStringStyle.SIMPLE_STYLE
*
* Example 2:
*
* -Xcommons-lang3
* -Xcommons-lang3:ToStringStyle=my.CustomToStringStyle
*
* to specify the use of
*
* my.CustomToStringStyle, which must be a subclass of
*
* org.apache.commons.lang.builder.ToStringStyle, and contains a public no-arg constructor.
*
* </pre>
* <p/>
* The default ToStringStyle adopted by this plugin is MULTI_LINE_STYLE.
*
* @author Hanson Char
* @author <a href="mailto:brian@btmatthews.com">Brian Matthews</a>
* @see org.apache.commons.lang3.builder.ToStringStyle
*/
public class XjcCommonsLang3Plugin extends Plugin {
private static final String TOSTRING_STYLE_PARAM = "-Xcommons-lang3:ToStringStyle=";
private String toStringStyle = "MULTI_LINE_STYLE";
private Class<?> customToStringStyle;
@Override
public String getOptionName() {
return "Xcommons-lang3";
}
@Override
public String getUsage() {
return " -Xcommons-lang3 : generate toString(), hashCode() and equals() for generated code using Jakarta's common-lang\n"
+ " [-Xcommons-lang3: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"
;
}
@Override
public boolean run(final Outline outline,
@SuppressWarnings("unused") final Options opt,
@SuppressWarnings("unused") final ErrorHandler errorHandler) {
// Process every pojo class generated by jaxb
for (final ClassOutline classOutline : outline.getClasses()) {
final JDefinedClass implClass = classOutline.implClass;
this.createToStringMethod(implClass);
this.createEqualsMethod(implClass);
this.createHashCodeMethod(implClass);
}
return true;
}
private void createToStringMethod(final JDefinedClass implClass) {
final JCodeModel codeModel = implClass.owner();
final JMethod toStringMethod =
implClass.method(JMod.PUBLIC, codeModel.ref(String.class), "toString");
// Annotate with @Override
toStringMethod.annotate(Override.class);
final JExpression toStringStyleExpr =
customToStringStyle == null
? codeModel.ref(ToStringStyle.class)
.staticRef(toStringStyle)
: JExpr._new(
codeModel.ref(customToStringStyle));
// Invoke ToStringBuilder.reflectionToString(Object,StringStyle)
toStringMethod.body()
._return(
codeModel.ref(ToStringBuilder.class)
.staticInvoke("reflectionToString")
.arg(JExpr._this())
.arg(toStringStyleExpr)
);
return;
}
private void createEqualsMethod(final JDefinedClass implClass) {
final JCodeModel codeModel = implClass.owner();
final JMethod toStringMethod =
implClass.method(JMod.PUBLIC, codeModel.BOOLEAN, "equals");
final JVar that = toStringMethod.param(Object.class, "that");
// Annotate with @Override
toStringMethod.annotate(Override.class);
// Invoke EqualsBuilder.reflectionEquals(Object,Object);
toStringMethod.body()._return(
codeModel.ref(EqualsBuilder.class)
.staticInvoke("reflectionEquals")
.arg(JExpr._this())
.arg(that)
);
}
private void createHashCodeMethod(JDefinedClass implClass) {
final JCodeModel codeModel = implClass.owner();
final JMethod toStringMethod =
implClass.method(JMod.PUBLIC, codeModel.INT, "hashCode");
// Annotate with @Override
toStringMethod.annotate(Override.class);
// Invoke EqualsBuilder.reflectionHashCode(Object);
toStringMethod.body()._return(
codeModel.ref(HashCodeBuilder.class)
.staticInvoke("reflectionHashCode")
.arg(JExpr._this())
);
}
@Override
public int parseArgument(final Options opt, final String[] args, final int i)
throws BadCommandLineException {
// eg. -Xcommons-lang3 ToStringStyle=SIMPLE_STYLE
final String arg = args[i].trim();
if (arg.startsWith(TOSTRING_STYLE_PARAM)) {
toStringStyle = arg.substring(TOSTRING_STYLE_PARAM.length());
try {
ToStringStyle.class.getField(toStringStyle);
return 1;
} catch (final SecurityException e) {
throw new BadCommandLineException(e.getMessage());
} catch (final NoSuchFieldException ignore) {
}
try {
customToStringStyle = Class.forName(toStringStyle);
} catch (final ClassNotFoundException e) {
throw new BadCommandLineException(e.getMessage());
}
return 1;
}
return 0;
}
}