В мире Java библиотека JAXB уже давно (как сообщает нам wikipedia с 2006 года) и по праву является распро­стра­ненным и очень удобным инстру­ментом для XML-cериа­ли­зации объектов и даже объектных моделей. В интернете есть масса примеров и целые сторонние библиотеки, постро­енные на JAXB — взять хотя бы docx4j (http://www.docx4java.org/trac/docx4j), которая работает с моделью документа в Open-XML формате. Так же много инфор­мации можно почерпнуть у самих авторов JAXB — https://jaxb.java.net/. Без труда найдутся в интернете прекрасные готовые исходники для генерации классов Java по XML-модели. Примеров масса и можно увлека­тельно провести время, изучая возмож­ности JAXB.

Но практи­чески все примеры приво­дятся для одного простого класса, который сериа­лизуют в XML, что называется, с нуля. А что делать, если уже есть некая готовая объектная модель со сложной струк­турой насле­до­вания и зависи­мостей, которые запрещены к изменениям? Где следует применить JAXB-аннотации? Куда их добавить — непосред­ственно в каждый из доброй полторы сотни классов, либо в один базовый? Если в каждый класс иерархии, то целесо­об­разна ли такая переделка с точки зрения объема выпол­ненной работы? Если в один-два базовых, то будет ли вообще работать XML-сериа­ли­зация? Да, действи­тельно много вопросов, и посмотрим, как JAXB с этим справ­ляется для конкретной задачи проекта.

Например, есть модель документа: Root – некий корневой элемент, контейнер для других элементов. Он может содержать Paragraph, который также является контей­нером для элементов Text. В свою очередь все элементы являются контей­нерами атрибутов, например у Paragraph это Alignment и Indent, у Text – Bold, Italic, FontName, FontSize и Color. Конечно, это неполный перечень, но в качестве примера доста­точный. Кроме того, условием для контей­неров элементов – Root и Paragraph, является то, что они могут содержать неогра­ни­ченное количество подэле­ментов, т.е. Root содержит много Paragraph, а Paragraph — много Text. Но контейнеры атрибутов могут содержать каждый атрибут в единственном экзем­пляре. Например, зачем элементу Text несколько FontName или Bold?
Таким образом, есть уже готовая модель элементов и атрибутов, со своей специ­фи­ческой бизнес-логикой, полями, методами и т.д.

//Начнем с базового абстрактного атрибута:

public abstract class Attribute<T> {
    protected T value;

    public Attribute(){
        this(null);
    }
    public Attribute(T value){
        this.value = value;
    }
    public T getValue() {
        return value;
    }
    public void setValue(T value) {
        this.value = value;
    }
}

//Его наследники для TextElement:


public class BoldAttribute extends Attribute<Boolean> {
    public BoldAttribute(){
        super(Boolean.FALSE);
    }
    public BoldAttribute(Boolean value){
        super(value);
    }
}
 
public class ItalicAttribute extends Attribute<Boolean> {
    public ItalicAttribute(){
        super(Boolean.FALSE);
    }
    public ItalicAttribute(Boolean value){
        super(value);
    }
}
 
public class FontNameAttribute extends Attribute<String> {
    public FontNameAttribute (){
        super("");
    }
    public FontNameAttribute (String value){
        super(value);
    }
}
 
public class FontSizeAttribute extends Attribute<Integer> {
    public FontSizeAttribute (){
        super(10);
    }
    public FontSizeAttribute (Integer value){
        super(value);
    }
}
 
public class ColorAttribute extends Attribute<java.awt.Color> {
    public ColorAttribute(){
        super(null);
    }
    public ColorAttribute(java.awt.Color value){
        super(value);
    }
} 

//Наследники Attribute для ParagraphElement:

public class AlignmentAttribute extends Attribute<AlignmentAttribute.VALUE> {
    public enum VALUE {
        NONE, LEFT, RIGHT, CENTER
    }
    public AlignmentAttribute() {
        super(VALUE.NONE);
    }
    public AlignmentAttribute(VALUE value) {
        super(value);
    }
}
 
public class IndentAttribute extends Attribute<Integer> {
    public IndentAttribute(){
        super(0);
    }
    public IndentAttribute(Integer value){
        super(value);
    }
}

//Теперь абстрактный терминальный элемент – контейнер атрибутов:

public abstract class TerminalElement {
    public TerminalElement(){
    }
    protected Map<Class, Attribute> attributes = new LinkedHashMap<Class, Attribute>();
    public List<Attribute> getAttributes() {
        return