Matthew Campbell
Matthew Campbell

Reputation: 1884

XJC generate another field type (effect on get method)

Using the latest JAXB (Metro) and generating Java with XJC....

Want to (as other users have asked) generate java.util.Set as a type for fields that represent unbounded sequences. Looks like that type of field is captured by XJC as a UntypedListField and the default behavior is to generate java.util.List (only the getter). If I do something similar to the collection-setter-injector plugin and adjust the field's type like

 public boolean run(Outline model, Options opt, ErrorHandler errorHandler) {
    for (ClassOutline co : model.getClasses()) {
       FieldOutline[] fo = co.getDeclaredFields();

       for ...
          if ((fo[i] instanceof UntypedListField)) {
            --> DO SOMETHING WITH THIS FIELD
          }
    }
 }

How do people adjust the type or is it easier to construct a new field then replace it in the set of declared fields in the class outline? How does messing with the field's type effect the generation of the get method on the property?

Upvotes: 3

Views: 904

Answers (1)

W Almir
W Almir

Reputation: 666

Looks like you're going for your own XJC Plugin. So here's what you need to do. Replace your --> DO SOMETHING WITH THIS FIELD line with the following.

First, figure out what's the parameterization type of fo[i] (which I'm calling f). Then, create the Set JType. And finally set the type of f to setType:

JType inner = ((JClass)f.type()).getTypeParameters().get(0);
JType setType = co.parent().getCodeModel().ref(Set.class).narrow(inner);
f.type(setType);

The method narrow() is used to set the parametrization type.

Looks good so far, the problem however is that the plugin will run after XJC is done generating the classes. Which means that the getter is already there. So we need to replace it.

And here's the replaceGetter() method

private void replaceGetter(ClassOutline co, JFieldVar f, JType inner) {
    //Create the method name
    String get = "get";
    String name  = f.name().substring(0, 1).toUpperCase() 
            + f.name().substring(1);
    String methodName = get+name;

    //Create HashSet JType
    JType hashSetType = co.parent().getCodeModel().ref(HashSet.class).narrow(inner);

    //Find and remove Old Getter!
    JMethod oldGetter = co.implClass.getMethod(methodName, new JType[0]);
    co.implClass.methods().remove(oldGetter);

    //Create New Getter
    JMethod getter = co.implClass.method(JMod.PUBLIC, f.type(), methodName);

    //Create Getter Body -> {if (f = null) f = new HashSet(); return f;}
    getter.body()._if(JExpr.ref(f.name()).eq(JExpr._null()))._then()
    .assign(f, JExpr._new(hashSetType));

    getter.body()._return(JExpr.ref(f.name()));
}

Hope you find this helpful.

Upvotes: 1

Related Questions