JAXB, XJC: создание поля для структуры класса

Мой вопрос касается написания плагинов JAXB, в частности ClassOutline Внутренности.

В com.sun.tools.xjc.outline.ClassOutline Есть поля:

  • цель
  • ссылка
  • implClass
  • implRef

Код:

/**
 * This {@link ClassOutline} holds information about this {@link CClassInfo}.
 */
public final @NotNull CClassInfo target;

/**
 * The exposed aspect of the a bean.
 *
 * implClass is always assignable to this type.
 * <p>
 * Usually this is the public content interface, but
 * it could be the same as the implClass.
 */
public final @NotNull JDefinedClass ref;

/**
 * The implementation aspect of a bean.
 * The actual place where fields/methods should be generated into.
 */
public final @NotNull JDefinedClass implClass;

/**
 * The implementation class that shall be used for reference.
 * <p>
 * Usually this field holds the same value as the {@link #implClass} method,
 * but sometimes it holds the user-specified implementation class
 * when it is specified.
 * <p>
 * This is the type that needs to be used for generating fields.
 */
public final @NotNull JClass implRef;

Насколько я знаю ( ТАК Ответ):

  • target - содержит информацию в Model, который представляет проанализированный и проанализированный файл схемы (.xsd)
  • ref обычно равняется implClass и оба держат Code Model
  • implClass это правильное место для размещения вновь сгенерированных полей, методов и т. д.
  • implRef - что это?

Я хочу добавить новое поле в класс, описанный ClassOutlineпоэтому код выглядит так:

JDefinedClass dstClass = classOutline.ref;
JFieldVar dstField = dstClass.field(srcField.mods().getValue(),
                        srcField.type(), srcField.name());

Он прекрасно работает, пока не появится другой плагин, который работает после того, как приведенный выше код выполняется и использует com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields() метод.

Представить - Plugin1 создает новые поля, а затем выполняется CopyablePlugin и хочет добавить clone() метод, который копирует каждое поле. Но CopyablePlugin не видит поля, недавно сгенерированные Plugin1 - потому что получить все поля из ClassOutline CopyablePlugin использования com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields() метод, который выглядит так:

/**
 * Gets all the {@link FieldOutline}s newly declared
 * in this class.
 */
public final FieldOutline[] getDeclaredFields() {
    List<CPropertyInfo> props = target.getProperties();
    // ...

Заметить, что getDeclaredFields() извлекает свойства из ClassOutline.target поле (это Model - проанализировал схему XSD) и полностью игнорирует код, сгенерированный для ClassOutline.implClass,

Это ошибка или особенность?

На данный момент я нашел обходной путь. Это же поле также добавляется в качестве свойства target:

classOutline.target.addProperty(prop);

Вопросы

  1. Не могли бы вы объяснить, какова роль ref/implClass/implRef?
  2. Где я должен генерировать совершенно новые поля / метод? В ref/implClass?
  3. Нужно ли соблюдать согласованность между ref/implClass а также target? Новое поле добавлено в implClass следует также добавить к target, право?
  4. Является com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields() правильный? Или Как правильно извлечь все поля из ClassOutline? Может быть, это должен быть союз target а также implClass содержание?

1 ответ

Решение

Я бы посоветовал не добавлять поля в ClassOutline, Слишком поздно и слишком много проблем. Поверьте мне, я пробовал это.

То, что я обнаружил, что гораздо проще и элегантнее, это добавить свойства CClassInfo, Это на один шаг раньше, здесь вы манипулируете моделью. Затем на следующем шаге из модели будет сгенерирован контур, так что вам даже не нужно заботиться о добавлении чего-либо в ClassOutline,

Чтобы добавить свойство к CClassInfo вы просто создаете экземпляр свойства (например, new CAttributePropertyInfo(...)), а затем просто добавьте его в CClassInfo: myClassInfo.addProperty(myPropertyInfo);,

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

Теперь на ваши вопросы.

  1. ref/implClass/implRef все обычно просто целевой сгенерированный класс. Разделение происходит из-за некоторых модов поколения, где XJC генерировал "открытый интерфейс" и "реализующий класс" отдельно. Я не знаю что implRef является то, что JavaDoc говорит что-то о пользовательских классов, так что я думаю о jaxb:class/@ref связывание. Никогда не занимался этим, хотя.

  2. Лучше всего будет дополнить модель (если вы хотите добавить новые свойства / поля). Если вы хотите добавить некоторый не связанный с моделью код (например, clone метод из Copyable плагин), я просто добавлю его в classOutline.implClass,

  3. Технически нет необходимости сохранять модель кода (classOutline.implClass) и модель (classOutline.target) в синхронизации. Если вы этого не сделаете, это не сломает XJC. Я могу представить, что это может сломать некоторые плагины XJC. Например, плагин может перебирать поля в JDefinedClass и попробуйте найти соответствующие свойства модели. Но опасность скорее теоретическая.

  4. ClassOutline.getDeclaredFields() правильно, но он дает только поля, объявленные в этом классе - без полей из суперкласса. Но довольно просто собрать все поля рекурсивно. getDeclaredFields() производит FieldOutlineна основе свойств из targetCClassInfo, Забудь implClassэто просто представление ClassOutline, Итак "союз target а также implClass"не имеет особого смысла.

Другие вопросы по тегам