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);
Вопросы
- Не могли бы вы объяснить, какова роль
ref/implClass/implRef
? - Где я должен генерировать совершенно новые поля / метод? В
ref/implClass
? - Нужно ли соблюдать согласованность между
ref/implClass
а такжеtarget
? Новое поле добавлено вimplClass
следует также добавить кtarget
, право? - Является
com.sun.tools.xjc.outline.ClassOutline.getDeclaredFields()
правильный? Или Как правильно извлечь все поля из ClassOutline? Может быть, это должен быть союзtarget
а такжеimplClass
содержание?
1 ответ
Я бы посоветовал не добавлять поля в ClassOutline
, Слишком поздно и слишком много проблем. Поверьте мне, я пробовал это.
То, что я обнаружил, что гораздо проще и элегантнее, это добавить свойства CClassInfo
, Это на один шаг раньше, здесь вы манипулируете моделью. Затем на следующем шаге из модели будет сгенерирован контур, так что вам даже не нужно заботиться о добавлении чего-либо в ClassOutline
,
Чтобы добавить свойство к CClassInfo
вы просто создаете экземпляр свойства (например, new CAttributePropertyInfo(...)
), а затем просто добавьте его в CClassInfo
: myClassInfo.addProperty(myPropertyInfo);
,
В случае с Copyable
плагин, если ваш плагин добавляет свойства к модели, и ваш плагин вызывается до Copyable
плагин, последний увидит вновь добавленные поля. Именно поэтому я рекомендую дополнить модель, а не взламывать схему или модель кода.
Теперь на ваши вопросы.
ref
/implClass
/implRef
все обычно просто целевой сгенерированный класс. Разделение происходит из-за некоторых модов поколения, где XJC генерировал "открытый интерфейс" и "реализующий класс" отдельно. Я не знаю чтоimplRef
является то, что JavaDoc говорит что-то о пользовательских классов, так что я думаю оjaxb:class/@ref
связывание. Никогда не занимался этим, хотя.Лучше всего будет дополнить модель (если вы хотите добавить новые свойства / поля). Если вы хотите добавить некоторый не связанный с моделью код (например,
clone
метод изCopyable
плагин), я просто добавлю его вclassOutline.implClass
,Технически нет необходимости сохранять модель кода (
classOutline.implClass
) и модель (classOutline.target
) в синхронизации. Если вы этого не сделаете, это не сломает XJC. Я могу представить, что это может сломать некоторые плагины XJC. Например, плагин может перебирать поля вJDefinedClass
и попробуйте найти соответствующие свойства модели. Но опасность скорее теоретическая.ClassOutline.getDeclaredFields()
правильно, но он дает только поля, объявленные в этом классе - без полей из суперкласса. Но довольно просто собрать все поля рекурсивно.getDeclaredFields()
производитFieldOutline
на основе свойств изtarget
CClassInfo
, ЗабудьimplClass
это просто представлениеClassOutline
, Итак "союзtarget
а такжеimplClass
"не имеет особого смысла.