com.sun.tools.xjc.addon.xew.config.AbstractConfigurablePlugin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jaxb-xew-plugin Show documentation
Show all versions of jaxb-xew-plugin Show documentation
This JAXB plugin utilizes the power of @XmlElementWrapper annotation. Originally xjc trends to create wrapper classes which are the containers for collections. This plugin goes through all properties to find ones which can be represented in the model in more optimal way.
The newest version!
package com.sun.tools.xjc.addon.xew.config;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import javax.xml.namespace.QName;
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.addon.xew.config.CommonConfiguration.ConfigurationOption;
import com.sun.tools.xjc.model.CCustomizations;
import com.sun.tools.xjc.model.CPluginCustomization;
import com.sun.tools.xjc.outline.Outline;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.apache.commons.logging.LogFactory;
import org.jvnet.jaxb2_commons.plugin.AbstractParameterizablePlugin;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
/**
* Plugin base class that only contains code for plugin initalization and logging.
*/
public abstract class AbstractConfigurablePlugin extends AbstractParameterizablePlugin {
private static final String PLUGIN_NAME = "Xxew";
private static final QName XEW_QNAME = new QName(
"http://github.com/jaxb-xew-plugin", "xew");
protected GlobalConfiguration globalConfiguration = new GlobalConfiguration();
public static final String COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY = "org.apache.commons.logging.simplelog.defaultlog";
public AbstractConfigurablePlugin() {
// Reset logger in parent because it should be re-initialized with correct loglevel threshold:
logger = null;
}
@Override
public String getOptionName() {
return PLUGIN_NAME;
}
@Override
public String getUsage() {
return " " + getArgumentName("")
+ " Replace collection types with fields having the @XmlElementWrapper and @XmlElement annotations.";
}
@Override
public Collection getCustomizationElementNames() {
return Collections.singletonList(XEW_QNAME);
}
private void initLoggerIfNecessary(Options opts) {
if (logger != null) {
return;
}
// Allow the caller to control the log level by explicitly setting this system variable:
if (System.getProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY) == null) {
String logLevel = "WARN";
if (opts.quiet) {
logLevel = "FATAL";
}
else if (opts.debugMode) {
logLevel = "DEBUG";
}
else if (opts.verbose) {
logLevel = "INFO";
}
System.setProperty(COMMONS_LOGGING_LOG_LEVEL_PROPERTY_KEY, logLevel);
}
// The logger needs to be re-created and not taken from cache:
LogFactory.getFactory().release();
logger = LogFactory.getLog(getClass());
globalConfiguration.setLogger(logger);
}
protected final void writeSummary(String s) {
globalConfiguration.writeSummary(s);
}
@Override
public void onActivated(Options opts) {
initLoggerIfNecessary(opts);
}
/**
* Generate argument name from option name.
*/
private static String getArgumentName(String optionName) {
return "-" + PLUGIN_NAME + ":" + optionName;
}
/**
* Parse argument at a given index and apply it to global configuration. Option value may go within the same
* argument (separated with equals), or as a following argument.
*
* @param args
* list of arguments
* @param index
* current index
* @param optionName
* the option to match
* @return number of arguments processed
*/
private int parseArgument(String[] args, int index, ConfigurationOption option) throws BadCommandLineException {
int recognized = 0;
String arg = args[index];
String argumentName = getArgumentName(option.optionName());
if (arg.startsWith(argumentName)) {
recognized++;
try {
if (arg.length() > argumentName.length()) {
applyConfigurationOption(globalConfiguration, option, arg.substring(argumentName.length()).trim());
}
else {
applyConfigurationOption(globalConfiguration, option, args[index + 1].trim());
recognized++;
}
}
catch (ClassNotFoundException e) {
throw new BadCommandLineException("Invalid class", e);
}
catch (IOException e) {
throw new BadCommandLineException("Failed to read from file", e);
}
}
return recognized;
}
/**
* Parse and apply plugin configuration options.
*
* @return number of consumed argument options
*/
@Override
public int parseArgument(Options opts, String[] args, int i) throws BadCommandLineException {
initLoggerIfNecessary(opts);
int recognized = 0;
String arg = args[i];
logger.trace("Argument[" + i + "] = " + arg);
if (arg.equals(getArgumentName(ConfigurationOption.APPLY_PLURAL_FORM.optionName()))) {
globalConfiguration.setApplyPluralForm(true);
return 1;
}
else if ((recognized = parseArgument(args, i, ConfigurationOption.CONTROL)) == 0
&& (recognized = parseArgument(args, i, ConfigurationOption.SUMMARY)) == 0
&& (recognized = parseArgument(args, i, ConfigurationOption.COLLECTION_INTERFACE)) == 0 // longer option name comes first
&& (recognized = parseArgument(args, i, ConfigurationOption.COLLECTION_IMPLEMENTATION)) == 0
&& (recognized = parseArgument(args, i, ConfigurationOption.INSTANTIATION_MODE)) == 0) {
if (arg.startsWith(getArgumentName(""))) {
throw new BadCommandLineException("Invalid argument " + arg);
}
}
return recognized;
}
/**
* Try to apply the {@code value} for the given configuration {@code option} to the given {@code configuration}.
* Note that depending on configuration level (global, class, property) not every option is applicable (in that case
* {@link IllegalArgumentException} is thrown).
*/
private static void applyConfigurationOption(CommonConfiguration configuration, ConfigurationOption option,
String value) throws IOException, ClassNotFoundException {
switch (option) {
case CONTROL:
if (!(configuration instanceof GlobalConfiguration)) {
throw new IllegalArgumentException("The option " + option + " is not applicable");
}
((GlobalConfiguration) configuration).readControlFile(value);
break;
case SUMMARY:
if (!(configuration instanceof GlobalConfiguration)) {
throw new IllegalArgumentException("The option " + option + " is not applicable");
}
((GlobalConfiguration) configuration).initSummaryWriter(value);
break;
case COLLECTION_IMPLEMENTATION:
configuration.setCollectionImplClass(Class.forName(value));
break;
case COLLECTION_INTERFACE:
configuration.setCollectionInterfaceClass(Class.forName(value));
break;
case INSTANTIATION_MODE:
try {
configuration.setInstantiationMode(CommonConfiguration.InstantiationMode.valueOf(value.toUpperCase()));
}
catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Unknown instantiation mode \"" + value + "\"");
}
break;
case APPLY_PLURAL_FORM:
configuration.setApplyPluralForm(Boolean.parseBoolean(value));
break;
case ANNOTATE:
if (!(configuration instanceof ClassConfiguration)) {
throw new IllegalArgumentException("The option " + option + " is not applicable");
}
((ClassConfiguration) configuration).setAnnotatable(Boolean.parseBoolean(value));
break;
}
}
/**
* Clone given configuration and apply settings from global/class/field JAXB customization.
*/
protected static T applyConfigurationFromCustomizations(
CommonConfiguration configuration, CCustomizations customizations, boolean cloneClassConfiguration)
throws IOException, ClassNotFoundException {
CPluginCustomization customization = customizations.find(XEW_QNAME.getNamespaceURI(), XEW_QNAME.getLocalPart());
if (customization == null) {
if (cloneClassConfiguration) {
return (T) new ClassConfiguration(configuration);
}
return (T) configuration;
}
customization.markAsAcknowledged();
NamedNodeMap attributes = customization.element.getAttributes();
if (cloneClassConfiguration) {
configuration = new ClassConfiguration(configuration);
}
for (int i = 0; i < attributes.getLength(); i++) {
Node attribute = attributes.item(i);
if (attribute.getNamespaceURI() == null) {
applyConfigurationOption(configuration, ConfigurationOption.byOption(attribute.getNodeName()),
attribute.getNodeValue());
}
}
return (T) configuration;
}
/**
* Implements exception handling.
*/
@Override
public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) throws SAXException {
try {
runInternal(outline);
return true;
}
catch (IOException e) {
logger.error("Failed to read the file", e);
throw new SAXException(e);
}
catch (ClassNotFoundException e) {
logger.error("Invalid class", e);
throw new SAXException(e);
}
}
/**
* Actual work is done in this method.
*/
protected abstract void runInternal(Outline outline) throws ClassNotFoundException, IOException;
@Override
public String toString() {
ToStringBuilder sb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
sb.append("globalConfiguration", globalConfiguration);
return sb.toString();
}
}