Customizando o Modelo de Dados
Um exemplo anterior neste tutorial mostrou algumas customizações simples de CodeGen. Agora que você viu como CodeGen manipula o esquema HR-XML TimeCard com configurações padrão, chegou a hora de dar uma olhada em alguma customizações mais poderosas.
Customizando o Modelo de Dados
O código do modelo de dados gerado por CodeGen usando configurações padrão possui alguns pontos fracos.
Uma coisa é que os nomes de tipo de esquema terminam com Type e isso é transportado para os nomes de classe gerados correspondentes, tornando os nomes mais longos do que necessário.
O nome do pacote gerado a partir do espaço de nome do esquema, org.hrxml.ns, é razoável, mas seria melhor ter um nome de pacote que indicasse que o modelo de dados é especificamente para documentos TimeCard .
A Listagem 11 mostra outro aspecto estranho das classes de modelo de dados gerado, m que java.math.BigInteger é usado para representar um tipo xs:integer . Essa é a representação mais precisa para xs:integer usando classes Java padrão, mas BigInteger é estanho de usar em comparação oa primitivo simples int ou aos tipos de objetos java.lang.Integer . Infelizmente, os esquemas são frequentemente escritos usando o tipo xs:integer mesmo quando xs:int seria mais apropriado, portanto, desenvolvedores podem ficar emperrados com valores BigInteger no código gerado. Esse é definitivamente o caso aqui, em que os valores reais permitidos para GenderCode são todos de um único dígito (conforme mostrado pelo fragmento de esquema original na parte inferior da listagem).
Listagem 11. Exemplo de Geração de xs:integer
/**
* Fragmentos do esquema para essa classe:
* <pre>
* <xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" type="xs:integer"
* name="GenderCode"/>
* </pre>
*/
public class GenderCode
{
private BigInteger genderCode;
/**
* Obtenha o valor do elemento 'GenderCode'.
*
* @return value
*/
public BigInteger getGenderCode() {
return genderCode;
}
/**
* Configure o valor do elemento 'GenderCode'.
*
* @param genderCode
*/
public void setGenderCode(BigInteger genderCode) {
this.genderCode = genderCode;
}
}
<xsd:simpleType name="GenderCodeType">
<xsd:annotation>
<xsd:documentation>Must conform to ISO 5218 - Representation of Human Sexes
(0 - Not Known; 1 - Male; 2 - Female; 9 - Not specified)</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:integer">
<xsd:pattern value="[0129]"/>
</xsd:restriction>
</xsd:simpleType>
|
A Listagem 12 mostra uma customização para melhorar esses aspectos do modelo de dados gerado.
O atributo package="org.hrxml.timecard" fornece o pacote Java a ser usado para as classes geradas.
O atributo
type-substitutions="xs:integer xs:int" define as substituições de tipo de esquema a serem aplicadas por CodeGen, neste caso, usando o tipo xs:int sempre que xs:integer for referido pelo esquema. É possível definir diversos pares de substituições apenas incluindo mais nomes de tipos na lista, usando espaços como separadores entre os pares, assim como entre os nomes de tipos de cada par.
O elemento name-converter aninhado configura a manipulação de nomes XML que estão sendo convertidos para nomes Java.
Neste caso, o atributo
strip-suffixes="Type" indica a CodeGen para remover
Type sempre que ocorrer no final de um nome. É possível fornecer diversas alternativas para serem removidas com esse atributo, como uma lista separada por espaços.
Você também pode usar um atributo
strip-prefixes para remover texto de orientação desnecessário de nomes, juntamente com diversas outras formas de customização.
É até mesmo possível substituir a classe de conversão de nome padrão com sua própria implementação, se você quiser fazer algo realmente especial nas conversões de nomes.
Para obter os detalhes integrais sobre essas opções
name-converter , consulte a documentação de JiBX CodeGen.
Por fim, o elemento class-decorator aninhado inclui um decorador na sequência de geração de códigos.
Nesse caso, o decorador é um predefinido fornecido como parte da distribuição CodeGen, que inclui métodos de suporte úteis para valores de coleta.
Qualquer decorador de geração de ocódigo configurado é chamado na sequência pelo CodeGen à medida que constrói o código de origem para as classes de modelo de dados e tem a oportunidade de modificar ou incluir no campo, método e construções de classe geradas por CodeGen. Cada uma dessas construções é passada para o decorador como um componente
Árvore de Sintaxe Abstrata (AST), usando a implementação do
Eclipse AST. Os decoradores fornecidos (incluindo o decorador
org.jibx.schema.codegen.extend.CollectionMethodsDecorator
usado aqui para incluir métodos e um
org.jibx.schema.codegen.extend.SerializableDecorator usado para incluir a interface
java.io.Serializable e, como opção, um ID de versão para classes do modelo de dados) fornecem exemplos de trabalhar com o Eclipse AST para estender CodeGen, de forma que o código de origem dessas classes seja um excelente ponto de partida para escrever seus próprios decoradores.
Listagem 12. Exemplo de Customizações de TimeCard
<schema-set xmlns:xs="http://www.w3.org/2001/XMLSchema" package="org.hrxml.timecard"
type-substitutions="xs:integer xs:int">
<name-converter strip-suffixes="Type"/>
<class-decorator class="org.jibx.schema.codegen.extend.CollectionMethodsDecorator"/>
</schema-set> |
Você pode testar a customização da Listagem 12 usando o destino Ant custgen1
ou o destino custom1 para executar a sequência completa de geração, compilação, ligação e teste.
A Listagem 13 mostra o resultado da aplicação das customizações. O nome da classe TimeCardType foi alterado para apenas
TimeCard e, além dos métodos get e set de
List , agora há os métodos added size, add,
indexed get e clear. Na classe GenderCode , a referência
BigInteger foi substituída por um tipo primitivo int simples.
Listagem 13. Modelo de Dados Customizado
/**
* Fragmentos do esquema para essa classe:
* <pre>
* ...
* </pre>
*/
public class TimeCard
{
...
private List<ReportedTime> reportedTimeList = new ArrayList<ReportedTime>();
...
/**
* Obtenha a lista de itens do elemento 'ReportedTime'.
*
* @return list
*/
public List<ReportedTime> getReportedTimes() {
return reportedTimeList;
}
/**
* Configure a lista de itens do elemento 'ReportedTime'.
*
* @param list
*/
public void setReportedTimes(List<ReportedTime> list) {
reportedTimeList = list;
}
/**
* Obtenha o número de itens do elemento 'ReportedTime'.
* @return count
*/
public int sizeReportedTime() {
return reportedTimeList.size();
}
/**
* Inclua um item do elemento 'ReportedTime'.
* @param item
*/
public void addReportedTime(ReportedTime item) {
reportedTimeList.add(item);
}
/**
* Obtenha o item do elemento 'ReportedTime' por posição.
* @return item
* @param index
*/
public ReportedTime getReportedTime(int index) {
return reportedTimeList.get(index);
}
/**
* Remova todos os itens do elemento 'ReportedTime'.
*/
public void clearReportedTime() {
reportedTimeList.clear();
}
...
}
/**
* Fragmentos do esquema para essa classe:
* <pre>
* <xs:element xmlns:xs="http://www.w3.org/2001/XMLSchema" type="xs:int"
* name="GenderCode"/>
* </pre>
*/
public class GenderCode
{
private int genderCode;
/**
* Obtenha o valor do elemento 'GenderCode'.
*
* @return value
*/
public int getGenderCode() {
return genderCode;
}
/**
* Configure o valor do elemento 'GenderCode'.
*
* @param genderCode
*/
public void setGenderCode(int genderCode) {
this.genderCode = genderCode;
}
} |
 |
Eliminando Definições Não Usadas
No primeiro exemplo de customização, usando o esquema original simples, você viu como controlar as definições de tipo incluídas no modelo de dados gerado usando generate-all="false" para desativar a geração de cada definição global e uma lista includes para forçar a geração de definições específicas. A Listagem 14 mostra uma customização modificada para o esquema TimeCard que inclui esses atributos, com apenas o elemento TimeCard a ser incluído no modelo de dados gerado (juntamente com tudo usado pela representação TimeCard , é claro).
Listagem 14. Customização omente com Componentes TimeCard
<schema-set xmlns:xs="http://www.w3.org/2001/XMLSchema" package="org.hrxml.timecard"
type-substitutions="xs:integer xs:int" generate-all="false">
<name-converter strip-suffixes="Type"/>
<class-decorator class="org.jibx.schema.codegen.extend.CollectionMethodsDecorator"/>
<schema name="TimeCard.xsd" includes="TimeCard"/>
</schema-set> |
É possível usar o destino Ant custgen2 para tentar essa customização com CodeGen ou usar o destino custom2 para executar a sequência completa de geração, compilação, ligação e teste. Essa mudança reduz o número de classes de nível superior no modelo de dados de 15 para 10 — nada mal para iniciar a simplificação do modelo de dados.
|