문제

I am trying to create an @XmlAdapter to split words in a mixed List into objects of a Wrapper class called Word. This field may also contain instances of an extension of Word called Group.

The idea is that this:

<span>Some text and a <g>group of words</g> and more<span>

would be equivalent to:

span.getContent().add(new Word("Some");
span.getContent().add(new Word("text");
span.getContent().add(new Word("and");
span.getContent().add(new Word("a");
span.getContent().add(new Group("group of words");
span.getContent().add(new Word("and");
span.getContent().add(new Word("more");

I am fighting with all the possible combinations ox XmlMixed and XmlAdapter I can think of but no luck!

This is my latets adapter which doesn't work at all:

public class SpanAdapter extends XmlAdapter<List<Word>, List> {

@Override
public List<Word> marshal(List v) throws Exception {
    List<Word> list = new ArrayList<>();
    for (Object o : v) {
        if (o instanceof String) {
            String s = (String) o;
            StringTokenizer st = new StringTokenizer(s, " ");
            while (st.hasMoreElements()) {
                Word word = new Word();
                word.setValue(st.nextToken());
                list.add(word);
            }
        } else if (o instanceof Group) {
            list.add((Group) o);
        }
    }
    return list;
}

@Override
public List unmarshal(List<Word> v) throws Exception {
    List list = new ArrayList<>();
    for (Word w : v) {
        if(w instanceof Group){
            list.add(w);
        } else{
            list.add(w.getValue()+ " ");
        }
    }
    return v;
}

}

And my span class:

@XmlRootElement(name = "span")
public class Span extends AudioComponent implements Item.Component {

private List<Word> value = new ArrayList();

@XmlMixed
@XmlElementRefs({
        @XmlElementRef(type = Group.class),
        @XmlElementRef(type = Word.class)
})
@XmlJavaTypeAdapter(SpanAdapter.class)
public List<Word> getValue() {
    return value;
}

public void setValue(List<Word> value) {
    this.value = value;
}

}

Word and Group are just wrappers of String. Group extends Word.

I am using MOXY in case it helps.

Thank you in advance!

도움이 되었습니까?

해결책

In case it helps anyone:

I managed to do this by setting the Adapter in the List field that contains the Span element.

Setting the adapter at package level or the Span class level would not work.

Also the adapter is not converting from List to List but from Span to Span, and modifying the list internally.

The final configuration is:

The place where I define the adapter:

@XmlElementRefs({
        @XmlElementRef(type = Span.class),
        @XmlElementRef(type = Other.class),
        @XmlElementRef(type = Another.class)

})
@XmlJavaTypeAdapter(value = SpanAdapter.class)
public List<Component> getComponents() {
    if (components == null) components = new ArrayList();
    return components;
}

The adapter (can't do it from span to span because I use it in a List field that may contain other classes):

public class SpanAdapter extends XmlAdapter<Object, Object> {

@Override
public Object unmarshal(Object o) throws Exception {
    if (o instanceof Span) {
        Span span = (Span) o;
        List<Span.Component> list = new ArrayList<>();
        for (Object child : span.getValue()) {
            if (child instanceof String) {
                String s = (String) child;
                for (String w : s.split(" ")) {
                    Word word = new Word();
                    word.setValue(w.trim());
                    list.add(word);
                }
            } else if (child instanceof Group) {
                list.add((Group) child);
            }
        }
        span.setValue(list);
        return span;
    }
    return o;
}

@Override
public Object marshal(Object o) throws Exception {
    if(o instanceof Span) {
        Span span = (Span) o;
        List list = new ArrayList<>();
        Iterator<Span.Component> iterator = span.getValue().iterator();
        while (iterator.hasNext()) {
            Span.Component w = iterator.next();
            if (w instanceof Group) {
                list.add(w);
            } else if (w instanceof Word) {
                String value = ((Word) w).getValue();
                list.add(iterator.hasNext() ? value + " " : value);
            }
        }
        span.setValue(list);
        return span;
    }else return o;
}
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top