MOXy XmlNameTransformer для нескольких пакетов

1

Я пытаюсь использовать MOXy для настройки алгоритма именования для XML-маршалинга и генерации схемы для классов в нескольких пакетах.

Я следую документации Eclipse и могу заставить его работать для одного класса:

@XmlNameTransformer(com.example.test.NameGenerator.class)
public class Customer

или один пакет:

@XmlNameTransformer(com.example.test.NameGenerator.class)
package com.example.test;

(также работает внешний файл привязок, но снова вы можете указать только пакет для каждого файла привязки)

Однако, поскольку у меня есть объекты, связанные с несколькими пакетами, я не хочу определять трансформатор для каждого пакета. Кроме того, я хотел бы сделать это динамически (т.е. отдельные пакеты неизвестны до выполнения).

Я попытался определить трансформатор в родительском пакете (com.example), но это не сработает - похоже, что это должен быть точный пакет, в котором находятся аннотированные классы.

Есть идеи?

Обновление - дополнительная информация

Возможно, я должен упомянуть, что основная причина, по которой я пытаюсь сделать это, чтобы я мог контролировать процесс генерации XML/XSD, и, в частности, я хочу, чтобы сложные типы были в прописном, а не по умолчанию ниже (без необходимости комментировать каждый один класс), например

@XmlRootElement
public class Test ...

должен генерировать:

<Test>
...
</Test>

вместо

<test>
...
</test>

Из других исследований, которые я сделал, единственный способ, которым я нашел это, - это XmlNameTransformer. Но если есть другой способ, и я лаю неправильное дерево... определенно дайте мне знать!

Теги:
jaxb
marshalling
moxy

2 ответа

0
Лучший ответ

Уровень пакета - это самый большой объем, на котором вы можете указать метаданные MOXy/JAXB. Вы можете использовать ту же реализацию XmlNameTransformer но вам нужно будет указать ее для каждого пакета, к которому вы хотите применить.

Однако, поскольку у меня есть объекты, связанные с несколькими пакетами, я не хочу определять трансформатор для каждого пакета. Кроме того, я хотел бы сделать это динамически (т.е. отдельные пакеты неизвестны до выполнения).

Вы можете программно создать объектную модель, соответствующую внешнему картографическому документу. Затем вы можете передать экземпляр этого при создании JAXBContext.

  • 1
    Это фантастика - спасибо! Я не могу поверить, что пропустил MetadataSource как тип свойства OXM_METADATA_SOURCE. Я расширю ваше решение в другом ответе.
1

Развернувшись на ответ Блейз, вот как выглядит моя реализация. Это достигается использованием трансформатора для динамического набора пакетов.

import org.eclipse.persistence.jaxb.metadata.MetadataSourceAdapter;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema;

public class NameTransformerAdapter extends MetadataSourceAdapter {

    private XmlBindings bindings;

    /**
     * @param packageName Fully qualified package name, like {@code com.example.test}
     */
    public NameTransformerAdapter(String packageName) {
            bindings = new XmlBindings();
            bindings.setPackageName(packageName);
            bindings.setXmlNameTransformer(XmlNameTransformer.class.getName());
            bindings.setXmlSchema(new XmlSchema()); // this is necessary
    }
    @Override
    public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) {
            return bindings;
    }
}

Указанный трансформатор довольно прост:

import org.eclipse.persistence.oxm.XMLNameTransformer;

public class XmlNameTransformer implements XMLNameTransformer {

    /** Uses capitalized name of class */
    public String transformTypeName(String name) {
            return name.substring(name.lastIndexOf('.') + 1);
    }
    public String transformElementName(String name) {
            return name;
    }
    public String transformAttributeName(String name) {
            return name;
    }
    public String transformRootElementName(String name) {
            return transformTypeName(name);
    }
}

Пакеты определяются во время выполнения и отслеживаются как таковые:

List<MetadataSource> adapters = new ArrayList<MetadataSource>();
adapters.add(new NameTransformerAdapter(packageName));

Наконец, JAXBContext может быть получен с использованием вышеперечисленных адаптеров:

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

private JAXBContext getContext(Class<?>[] classes) throws JAXBException {
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, adapters);
    return JAXBContextFactory.createContext(classes, properties);
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню