[java] Как бы вы писали генератор классов из xml

pitrik2

есть некое описание классов в xml
собсна нужно сгенерить классы для разных языков (пока что java и c#, потом наверна еще c++ будет)
структуру через xstream в бины загнал
а вот как терь в файло вывести...
стал делать в лоб - чето как-то фигово выходит...
либо огромное число повторяющегося кода, либо огромное число однострочковых мелких методов
потом к ним еще надо форматтер прикрутить
для java нашел jalopy
а для c# не подскажите чегонить?

katrin2201

Хотелось бы увидеть пример решения в лоб.
А то непонятно какой именно "в лоб" у тебя, и почему там возникают проблемы с повторяющимся кодом.

Dasar

есть некое описание классов в xml
это описание во что-нибудь стандартное (wsdl, xsd и т.д.) сконвертнуть реально?

pitrik2

xsd
схема?
ну она есть у меня...
пример описания:

<struct name="Foo">
<constructor>
<param name="id"/>
</constructor>
<constructor>
<param name="id"/>
<param name="bar"/>
</constructor>
<field name="id" type="int"/>
<field name="bar" type="Bar"/>
</struct>

из этого дела генерится такой код:

package lalala;

public class Foo implements lalala,lalala,lalala,lalala {
public static final String IdFieldName = "id";
public static final String BarFieldName = "bar";

private static final int IdFieldIndex = 0;
private static final int BarFieldIndex = 1;

public static final String[] Fields = new String[]{
"id",
"bar"
};

private java.util.BitSet mask = new java.util.BitSet(2);

private static final java.util.Map<String, lalala.iFieldAccessor<Foo>> Accessors = new java.util.HashMap<String, lalala.iFieldAccessor<Foo>>

private int id;
private Bar bar;

static {
Accessors.put(IdFieldName, new iFieldAccessor<Foo> {
lalala;
});

Accessors.put(BarFieldName, new iFieldAccessor<Foo> {
lalala;
});
}

public Foo {
}

public Foo(Msg message) throws MsgException {
load(message);
}

public Foo(int id) {
setId(id);
}

public Foo(int id, Bar bar) {
setId(id);
setBar(bar);
}

@Override
public void setField(String fieldName, Object value) {
Accessors.get(fieldName).setValue(this, value);
}

@Override
public Object getField(String fieldName) {
return Accessors.get(fieldName).getValue(this);
}

@Override
public String[] getFields {
return Fields;
}

public int getId {
return id;
}

public void setId(int value) {
this.mask.set(IdFieldIndex);
this.id = value;
}

public Bar getBar {
return bar;
}

public void setBar(Bar value) {
this.mask.set(BarFieldIndex);
this.bar = value;
}


и так далее, там еще много чего
для c# код примерно похож

Dasar

<constructor>
<param name="id"/>
</constructor>
<constructor>
<param name="id"/>
<param name="bar"/>
</constructor>
конструкторы - это плохо, afaik - стандартные генераторы обычно конструкторы не держат

pitrik2

А то непонятно какой именно "в лоб" у тебя, и почему там возникают проблемы с повторяющимся кодом.
ну там около 20 циклов for(struct.fields)
во многих этих for часто встречается
if(field.type = array) do
else if(field.type = enum) do
else if(field.type = primitive) do
else do
работать то оно работает
но код противный уж очень :(
щас вот стал пробовать на velocity сделать
непонятно как там во время исполнения контекст менять, может ему можно свой контекст подсунуть?
пока что придумал токо врапперы писать:

// java/cs init
context.set("fieldWrapper", new java/cs wrapper);

// java.vm
#for ($field in $struct.fields) {
$javaFieldWrapper.name(field);
$javaFieldWrapper.typename(field);
$javaFieldWrapper.packagename(field);
#end

// cs.vm
#for ($field in $struct.fields) {
$csFieldWrapper.name(field);
$csFieldWrapper.typename(field);
$csFieldWrapper.namespacename(field);
#end

bansek

а стандартные решения не прокатывают? типа jaxb вроде что то похожее делал

freezer

ну вот у меня из вещей типа такого:

<struct id="IDL:xxx.ru/NotificationService/PersonInfo:1.0" name="PersonInfo" kind="tk_struct">
<member_names>
<name>ID</name>
<name>ProxyCardId</name>
<name>PersonName</name>
<name>Photo</name>
</member_names>
<member_types>
<alias id="IDL:xxx.ru/NotificationService/PersonInfoKey:1.0" name="PersonInfoKey" kind="tk_alias">
<content>
<primitive kind="tk_long" />
</content>
</alias>
<string kind="tk_string" bound="0" />
<string kind="tk_string" bound="0" />
<alias id="IDL:xxx.ru/NotificationService/ImageBlob:1.0" name="ImageBlob" kind="tk_alias">
<content>
<array kind="tk_sequence" length="0">
<content>
<primitive kind="tk_octet" />
</content>
</array>
</content>
</alias>
</member_types>
</struct>

делает набор нечитаемых классов на C#. То что код получается хреновый - не страшно, т.к. люди его всё равно не читают (разве что я, когда что-то не работает а компилятор и JIT потом всё оптимизируют

pitrik2

не понял
чем и как парсится этот xml-ник?

freezer

System.Xml.Serializer + последующая обработка, на выходе получается CORBA::TypeCode, по которому уже строятся классы
Оставить комментарий
Имя или ник:
Комментарий: