package org.jvnet.jaxb2_commons.plugin.setters; import java.util.Arrays; import java.util.Collection; import javax.xml.namespace.QName; import org.apache.commons.lang3.Validate; import org.jvnet.jaxb2_commons.plugin.AbstractParameterizablePlugin; import org.jvnet.jaxb2_commons.plugin.CustomizedIgnoring; import org.jvnet.jaxb2_commons.plugin.Ignoring; import org.jvnet.jaxb2_commons.plugin.util.FieldOutlineUtils; import org.xml.sax.ErrorHandler; import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JExpr; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JMethod; import com.sun.codemodel.JMod; import com.sun.codemodel.JType; import com.sun.codemodel.JVar; import com.sun.tools.xjc.Options; import com.sun.tools.xjc.outline.ClassOutline; import com.sun.tools.xjc.outline.FieldAccessor; import com.sun.tools.xjc.outline.FieldOutline; import com.sun.tools.xjc.outline.Outline; public class SettersPlugin extends AbstractParameterizablePlugin { private static final JType[] ABSENT = new JType[0]; @Override public String getOptionName() { return "Xsetters"; } @Override public String getUsage() { return "Generates setters for collections."; } public boolean run(Outline outline, Options opt, ErrorHandler errorHandler) { for (final ClassOutline classOutline : outline.getClasses()) if (!getIgnoring().isIgnored(classOutline)) { processClassOutline(classOutline); } return true; } protected void processClassOutline(ClassOutline classOutline) { final JDefinedClass theClass = classOutline.implClass; generateSetters(classOutline, theClass); } public static enum Mode { accessor { @Override public void generateSetter(FieldOutline fieldOutline, JDefinedClass theClass, JMethod setter, JVar value) { final FieldAccessor accessor = fieldOutline.create(JExpr ._this()); accessor.unsetValues(setter.body()); accessor.fromRawValue(setter.body(), "draft", value); } }, direct { @Override public void generateSetter(FieldOutline fieldOutline, JDefinedClass theClass, JMethod setter, JVar value) { final JFieldVar field = theClass.fields().get( fieldOutline.getPropertyInfo().getName(false)); if (field != null) { setter.body().assign(JExpr._this().ref(field), value); } else { // Fallback to the accessor Mode.accessor.generateSetter(fieldOutline, theClass, setter, value); } } }; public abstract void generateSetter(FieldOutline fieldOutline, JDefinedClass theClass, JMethod setter, JVar value); } private Mode mode = Mode.accessor; public String getMode() { return mode.name(); } public void setMode(String mode) { Validate.notNull(mode); try { this.mode = Mode.valueOf(mode); } catch (IllegalArgumentException iaex) { throw new IllegalArgumentException( "Unsupported mode [" + mode + "]." + " Supported modes are [accessor] (uses JAXB-generated accessors, default)" + " and [direct] (assigns the value to the field directly)."); } } private void generateSetters(ClassOutline classOutline, JDefinedClass theClass) { final FieldOutline[] declaredFields = FieldOutlineUtils.filter( classOutline.getDeclaredFields(), getIgnoring()); for (final FieldOutline fieldOutline : declaredFields) { final String publicName = fieldOutline.getPropertyInfo().getName( true); final String getterName = "get" + publicName; final JMethod getter = theClass.getMethod(getterName, ABSENT); if (getter != null) { final JType type = getter.type(); final JType rawType = fieldOutline.getRawType(); final String setterName = "set" + publicName; final JMethod boxifiedSetter = theClass.getMethod(setterName, new JType[] { rawType.boxify() }); final JMethod unboxifiedSetter = theClass.getMethod(setterName, new JType[] { rawType.unboxify() }); final JMethod setter = boxifiedSetter != null ? boxifiedSetter : unboxifiedSetter; if (setter == null) { final JMethod generatedSetter = theClass.method( JMod.PUBLIC, theClass.owner().VOID, setterName); final JVar value = generatedSetter.param(type, "value"); mode.generateSetter(fieldOutline, theClass, generatedSetter, value); } } } } private Ignoring ignoring = new CustomizedIgnoring( org.jvnet.jaxb2_commons.plugin.setters.Customizations.IGNORED_ELEMENT_NAME); public Ignoring getIgnoring() { return ignoring; } public void setIgnoring(Ignoring ignoring) { this.ignoring = ignoring; } @Override public Collection<QName> getCustomizationElementNames() { return Arrays .asList(org.jvnet.jaxb2_commons.plugin.setters.Customizations.IGNORED_ELEMENT_NAME); } }