El API JAXB

Este cap�tulo demuestra c�mo usar JAXB para unir un DTD a un conjunto de clases Java. Para generar la clases, realizamos estos pasos:

  1. Escribir un esquema de uni�n, que contiene las instrucciones de c�mo unir un DTD a las clases.
  2. Ejecutar el compilador de esquema con el DTD y el esquema de uni�n como entradas para generar el c�digo fuente.
  3. Compilar el c�digo fuente para generar las clases.

Los dos cap�tulos siguientes muestran c�mo utilizar las clases para construir representaciones de datos desde documentos XML y trabajar con los datos. El ejemplo que estos cap�tulos usan es la sencilla aplicaci�n de libro de cheques que se describi� en el escenario 1: Balancear un Libro de Cheques. Con esta aplicaci�n, podremos registrar transacciones en un libro de cheques y determinar el balance de la cuenta controlada.

El ejemplo checkbook usa el checkook.dtd, que est� localizado en el directorio examples/checkbook de nuestra instalaci�n de JAXP. La primera secci�n de este cap�tulo explica el DTD checkbook.

.�El DTD de Ejemplo: "checkook.dtd"

Antes de crear la aplicaci�n checkbook, deber�amos entender el DTD en el que est� basada. Esta secci�n describe brevemente el checkook.dtd mostrado aqu�:

<!ELEMENT checkbook ( transactions, balance ) > 
<!ELEMENT transactions ( deposit | check | withdrawal )* > 
<!ELEMENT deposit ( date, name, amount )> 
<!ATTLIST deposit category ( salary | interest-income | other ) #IMPLIED > 
<!ELEMENT check ( date, name, amount, ( pending | void | cleared ), memo? ) > 
<!ATTLIST check number CDATA #REQUIRED category ( rent | groceries | other ) #IMPLIED > 
<!ELEMENT withdrawal ( date, amount ) > 
<!ELEMENT balance (#PCDATA) > 
<!ELEMENT date (#PCDATA ) > 
<!ELEMENT name (#PCDATA) > 
<!ELEMENT amount (#PCDATA) > 
<!ELEMENT memo (#PCDATA) > 
<!ELEMENT pending EMPTY > 
<!ELEMENT void EMPTY > 
<!ELEMENT cleared EMPTY >

Un documento XML debe tener exactamente un elemento de ra�z, pero el documento puede seleccionar que elemento utilizar como su elemento ra�z del DTD. Para nuestro ejemplo del checkbook, tanto checkbook como transactions se pueden utilizar como elementos ra�z por documentos XML de este ejemplar de DTD. La secci�n Crear el Esquema de Uni�n M�nimo Requerido muestra c�mo especificar en el esquema de uni�n qu� elementos de un documento XML v�lido pueden utilizarse como elementos ra�z. Seg�n el DTD, un checkbook contiene transacciones que se hacen contra la cuenta y un balance que representa la cantidad de dinero que la cuenta contiene. El conjunto de transacciones, seg�n la definici�n del elemento de las transacciones, contiene cero o m�s dep�sitos, cheques, o reintegros.

Una transaci�n deposit consta de:

  • La fecha en que se hizo.
  • El nombre de la persona o empresa que proporcion� el dinero para el dep�sito.
  • La cantidad depositada.

El elemento deposit tambi�n tiene un atributo, llamado category, que describe la raz�n del dep�sito.

Una transaci�n check consta de :

  • La fecha en la que se firmo el cheque.
  • El nombre de la persona o empresa que recibe el cheque.
  • La cantidad del cheque.
  • El estado del cheque: cleared, void, o pending (todav�a no se ha cobrado).
  • Un memo opcional.

El check tambi�n tiene dos atributos: number y category. El atributo number representa el n�mero de cheque. El atributo category representa el motivo por el que se ha extendido el cheque.

La transaci�n withdrawal (reintegro) consta s�lo de la fecha en la que se hizo y la cantidad reintegrada.

Los elementos balance , date , name , amount , y memo se han definido para tener contenido de car�cter. Este cap�tulo muestra c�mo generar varios tipos para el contenido de los elementos balance, data y amount.

Los elementos pending , void , y cleared no tienen contenido, por lo que se han definido como EMPTY.

.�Escribir el Esquema de Uni�n

No necesitamos proporcionar una declaraci�n de uni�n para cada componente del DTD. El compilador de esquema asume declaraciones de uniones por defecto si no se proporciona una uni�n particular. Sin embargo, si no est�mos satisfechos con las uniones por defecto, necesitamos proporcionar declaraciones de uni�n en el esquema de uni�n para generar las clases que deseamos.

Esta secci�n nos muestra:

  1. C�mo escribir el esquema de uni�n m�nimo, que es un esquema de uni�n que contiene las declaraciones m�nimas que permitir�n al compilador de esquema generar las clases.
  2. Qu� c�digo generar� el compilador de esquema bas�ndose en el esquema de uni�n m�nimo y el DTD.
  3. C�mo a�adir declaraciones al esquema de uni�n m�nimo para que el compilador de esquema genere el c�digo que queremos, no s�lo el c�digo por defecto.

Esta gu�a explica detalladamente c�mo escribir el esquema de uni�n. El esquema de uni�n es lo que utilizamos para controlar qu� tipo de c�digo genera el compilador de esquema. Por lo tanto, es importante que entendamos c�mo el compilador de esquema interpreta las declaraciones que proporcionamos en el esquema de uni�n y lo que el compilador de esquema asume si no proporcionamos las declaraciones de uni�n para una declaraci�n del DTD. Adem�s, el lenguaje de uni�n y el compilador de esquema que interpreta el esquema de uni�n son los suficientemente proderosos como para hacer asunciones razonables, pero todav�a nos permiten mucha flexibilidad para definir c�mo el DTD est� unido a las clases.

Aunque el compilador del esquema puede producir una uni�n razonable en el caso simple, cuando veamos qu� clase de c�digo genera el compilador de esquema basandose en el DTD checkbook y un esquema de uni�n m�nimo, entenderemos la importancia de proporcionar declaraciones de uni�n de modo que podamos generar el c�digo apropiado para nuestra aplicaci�n.

.�Crear el Esquema de Uni�n M�nimo Requerido

Tanto si deseamos o no validar las declaraciones de uni�n por defecto asumidas por el compilador de esquema, necesitamos proporcionar un esquema de uni�n. Para crear el esquema de uni�n para el DTD del checkbook:

  1. Creamos un nuevo fichero de texto llamado checkook.xjs.
  2. En checkook.xjs, escribimos:
    <xml-java-binding-schema version="1.0ea">
    

    Esta etiqueta identifica el fichero como un esquema de uni�n.

  3. Todos los esquemas de uni�n deben declarar al menos un elemento ra�z. En nuestro ejemplo, queremos declarar dos elementos ra�z: checkbook y transactions. Para declarar los elementos raiz, escribimos:
    <element name=checkbook type=class root=true />
    <element name=transactions type=class root=true />
    

    Para declarar estos elementos ra�z, utilizamos la declaraci�n de uni�n del elemento para unir un tipo de elemento a una clase. El valor del atributo debe ser el nombre del elemento tal como aparece en el DTD. El valor del tipo de atributo es class en este caso porque �stos son elementos ra�z y se deben limitar a las clases. El atributo root debe ser igual a true porque queremos que los ejemplares del documento XML del DTD checkbook pudieran declarar checkbook o transactions como elementos ra�z.

  4. Introducimos la etiqueta final para el elemento xml-java-binding-schema:
    </xml-java-binding-schema>
    

    Ahora tenemos un esquema de uni�n legal desde el cual el compilador de esquema puede generar clases. De acuerdo con el DTD, el compilador de esquema hace asunciones con respecto a c�mo unir las otras declaraciones del DTD para los cuales no proporcionamos declaraciones de uni�n. La siguiente secci�n explica las declaraciones de uni�n asumidas por el compilador de esquema bas�ndose en el DTD checkbook y el esquema de uni�n actual. Una vez que entendamos qu� tipo de c�digo se produce desde un esquema de uni�n m�nimo, la escritura el resto del esquema de uni�n es f�cil.

.�Entender las Declaraciones por Defecto

Las declaraciones de uni�n que el compilador de esquema asume bas�ndose en el DTD checkbook y el esquema de uni�n m�nimo son:

<element name="checkbook" type="class" root=true> 
    <content> 
        <element-ref name="transactions"/> 
        <element-ref name="balance"/>
    </content>
</element> 
<element name="transactions" type="class" root=true> 
    <content property="content"/>
</element> 
<element name="deposit" type="class"> 
    <attribute name="category"/>
    <content> 
        <element-ref name="date"/> 
        <element-ref name="name"/> 
        <element-ref name="amount"/>
    </content>
</element> 
<element name="check" type="class"> 
    <attribute name="number"/> 
    <attribute name="category"/> 
    <content property="content"/>
</element> 
<element name="withdrawal" type="class"> 
    <content> 
        <element-ref name="date"/> 
        <element-ref name="amount"/>
    </content>
</element> 
<element name="balance" type="value"/> 
<element name="date" type="value"/> 
<element name="name" type="value"/> 
<element name="amount" type="value"/> 
<element name="memo" type="value"/> 
<element name="pending" type="class"/> 
<element name="void" type="class"/> 
<element name="cleared" type="class"/>

El resto de esta secci�n explica cada una de estas declaraciones de union.

.�Declaraci�n de Uni�n de Elementos

El compilador de esquema asume diversas declaraciones de uni�n para los elementos dependiendo de qu� tipo de contenido tienen o si tienen atributos. Para los elementos simples, que tienen solamente el contenido del tipo car�cter y ningun atributo, el compilador de esquema asume que los elementos est�n unidos a las propiedades dentro de la clase de su elemento padre. Los elementos balance, date, name y amount son elementos simples y por eso el compilador de esquema asume estas uniones para ellos:

<element name="balance" type="value"/> 
<element name="date" type="value"/> 
<element name="name" type="value"/> 
<element name="amount" type="value"/> 
<element name="memo" type="value"/>

El nombre de los atributos debe ser el nombre del elemento tal como aparece en el DTD. El tipo del atributo es value en estos casos porque estos elementos est�n unidos a propiedades, no a clases. �stas declaraciones de uni�n har�n que compilador de esquema genere estas propiedades:

String getBalance(); 
void setBalance(String x); 
String getDate(); 
void setDate(String x); 
String getName(); 
void setName(String x); 
String getAmount(); 
void setAmount(String x);
String getMemo(); 
void setMemo(String x);

Una propiedad String est� muy bien para los elementos name y memo. Sin embargo, para balance y amount, necesitamos un tipo que represente mejor valores de moneda. De forma similar date se debe limitar a una propiedad que acepte y devuelva una cierta clase de tipo que represente mejor una fecha. La secci�n Especificar Tipos mostrar� c�mo generar las propiedades que aceptan y devuelven diferentes tipos.

Para el resto de los tipos de elementos, el compilador de esquema asume que los elementos est�n unidos a clases. Si un elemento contiene cualquier cosa distinta de contenido de caracteres o tiene atributos, el compilador de esquema lo unir� a una clase. Los elementos deposit, check, y withdrawal tienen elementos de contenido, y deposit y check tiene atributos. Estos elementos tambi�n est�n unidos a clases. Las uniones por defecto para estos elementos son:

<element name="deposit" type="class" > 
<element name="check" type="class" > 
<element name="withdrawal" type="class" >

Observa que no necesitamos especificar el atributo root como hicimos en la secci�n Crear el Esquema de Uni�n M�nimo Requerido. El compilador de esquema asume que el valor de este atributo es false. S�lo necesitamos especificar el valor de este atributo como true si queremos el ejemplar del documento XML tenga la posibilidad de usar ese elemento como elemento ra�z. De la declaraci�n de uni�n del elemento deposit el compilador de esquema genera esta definici�n de clase y este constructor:

public class Deposit extends MarshallableObject { 
    public void Deposit();

Las clases Check , y Withdrawal se parecer�n mucho a �sta.

Los elementos pending , void , y cleared tienen contenido EMPTY y est�n includos en un modelo de grupo de elecci�n, y por eso est�n unidos a clases, como se especifica en sus declaraciones de tipos de atributos:

<element name="pending" type="class"/> 
<element name="void" type="class"/> 
<element name="cleared" type="class"/>

.�Declaraci�n de Uni�n de Atributos

El DTD checkbook define tres atributos. El elemento deposit tiene un atributo category, y el elemento check tiene un atributo number y tambi�n un atributo category:

<!ELEMENT deposit ... 
<!ATTLIST deposit category ( salary | interest-income | other ) #IMPLIED > 
<!ELEMENT check ... 
<!ATTLIST check number CDATA #REQUIRED category ( rent | groceries | other ) #IMPLIED >

Todos estos atributos toman valores at�micos, en vez de valores compuestos, y por eso el compilador de esquema asume que estos atributos est�n unidos a propiedades String, como se especifica en esta declaraciones de uni�n por defecto:

<element name=deposit type=class > 
    <attribute name=category />
... 
<element name="check" type="class"> <attribute name=number />
    <attribute name=category />
...

Dentro de la clase Deposit, el compilador de esquema genera esta propiedad para representar el atributo category:

void setCategory(String x); 
String getCategory();

Dentro de la clase Check, el compilador de esquema genera estas propiedades para representar a los atributos number y category:

void setNumber(String x); 
String getNumber(); 
void setCategory(String x); 
String getCategory();

Observa que la propiedad number acepta y devuelve un String. La secci�n Especificar Tipos mostrar� c�mo modificar el esquema para requisitos de uniones particulares de modo que el compilador de esquema genere una propiedad number que acepte y devuelva un int. Asimismo, la secci�n Crear Tipos Enumerados mostrar� c�mo generar un tipo enumerado para la propiedad category.

.�Declaraci�n de Uni�n de Contenido

El declaraci�n de uni�n de contenido es lo m�s complicado, reflejando el n�mero infinito de maneras en que podemos especificar el contenido XML, pero JAXB lo hace f�cil para nosotros. El tipo m�s com�n de modelo de contenido es una secuencia simple, no-repetitiva, por ejemplo (a, b, c, d). Si utilizamos este tipo de modelo de contenido, muy probablemente no necesitaremos especificar un declaraci�n de uni�n para �l porque el compilador de esquema genera una propiedad separada para cada elemento de la secuencia, que es generalmente lo que deseamos.

La mayor�a de los elementos que hay en checkook.dtd tienen contenido secuencial simple y no repetitivo. Para estos elementos, el compilador de esquema asume las declaraciones de uni�n mostradas en negrita:

<element name="checkbook" type="class" root=true> 
    <content>
        <element-ref name="transactions"/>
        <element-ref name="balance"/>
    </content> 
</element> 
<element name="deposit" type="class"> 
    <attribute name="category"/> 
    <content>
        <element-ref name="date"/>
        <element-ref name="name"/>
        <element-ref name="amount"/>
    </content> 
</element> 
<element name="withdrawal" type="class"> 
    <content>
        <element-ref name="date"/>
        <element-ref name="amount"/>
    </content> 
</element>

El declaraci�n de uni�n element-ref se utiliza para unir un ejemplar de un elemento en un modelo de contenido a una propiedad en la clase del elemento padre. La declaraci�n del elemento que corresponde al ejemplar del elemento une el elemento a s� mismo, incluyendo la uni�n del elemento a su tipo. Por defecto, el compilador de esquema genera propiedades String desde todas las declaraciones de uniones element-ref que se refieran a elementos simples. La propiedad por defecto para el elemento name es:

public class Deposit { 
    ... 
    String getName();
    void setName(String x);

El compilador de esquema tambi�n genera una propiedad String para balance, date, y amount. La clase Checkbook contiene una propiedad para el elemento balance. Las clases Deposit y Withdrawal tienen propiedades para los elementos date y amount. En la secci�n Especificar Tipos veremos que los tipos de estas propiedades cambian cuando utilizamos el atributo convert en las declaraciones de uni�n correspondientes al elemento.

Como especificamos que el elemento transactions est� unido a una clase, la declaraci�n de uni�n element-ref para el elemento transactions har� que el compilador de esquema genere esta propiedad en el clase Checkbook:

Transactions getTransactions(); 
void setTransactions(Transactions x);

Si un elemento contiene algo distinto a una secuencia simple no repetitiva, el compilador de esquema asumir� la declaraci�n de uni�n de la propiedad general-content, que es:

<content property=content />

Los elementos transactions y check no tienen secuencias simples y no repetitivas como contenidos, por eso el compilador de esquema asume estas declaraciones de uni�n para ellos:

<element name="transactions" type="class" root=true> 
    <content property="content"/> 
</element> 
... 
<element name="check" type="class"> 
    <attribute name="number"/> 
    <attribute name="category"/> 
    <content property="content"/> 
</element>

Se usa la declaraci�n general-content para unir un modelode grupo completo, incluyendo modelos de grupos anidados, a una propiedad. Este declaraci�n no es muy �til para nuestros prop�sitos porque deseamos tener acceso a los elementos individuales en estos modelos de contenido. Esta declaraci�n es �til para definir uniones m�s flexibles si anticipamos que nuestro DTD cambiar� en el futuro. Para m�s informaci�n sobre esta declaraci�n, puedes ver la secci�n Manejar la Evoluci�n del Esquema.

Desde estas declaraciones de uni�n, el compilador de esquema genera esta propiedad en las clases Transactions y Check:

List getContent(); 
void emptyContent(); 
void deleteContent();

El m�todo getContent devuelve una lista modificable que contiene el valor actual de las propiedades. El m�todo emptyContent descarta los valores de la lista y crea una nueva lista, vac�a. El m�todo deleteContent borra la lista.

.�Personalizar el Esquema de Uni�n

Ahora que entendemos las declaraciones de uni�n que el compilador del esquema asumir� bas�ndose en el DTD y el esquema de uni�n m�nimo, es f�cil escribir el esquema de uni�n: Todo lo que necesitamos escribir son las declaraciones de uniones que no son asumidas por el compilador de esquema. Esta secci�n explica cada una de las personalizaciones para requisitos particulares que podemos hacer al esquema de uni�n para conseguir las clases que deseamos.

El esquema de uni�n que usaremos para la aplicaci�n checkbook es:

<xml-java-binding-schema version="1.0ea"> 
<element name="checkbook" type="class" root="true" /> 
<element name="transactions" type="class" root="true"> 
    <content> 
        <choice property="entries" collection="list" supertype="Entry" /> 
    </content> 
</element> 
<element name="balance" type="value" convert="BigDecimal"/> 
<element name="amount" type="value" convert="BigDecimal" /> 
<element name="date" type="value" convert="TransDate" /> 
<element name="deposit" type="class" > 
    <attribute name="category" convert="DepCategory" /> 
</element> 
<element name="check" type="class" > 
    <content> 
        <element-ref name="date"/> 
        <element-ref name="name" /> 
        <element-ref name="amount" /> 
        <choice property="pend-void-clrd"/> 
    </content> 
    <attribute name="number" convert="int" /> 
    <attribute name="category" convert="CheckCategory" />
</element> 
<conversion name="BigDecimal" type="java.math.BigDecimal" /> 
<conversion name="TransDate" type="java.util.Date" parse="TransDate.parseDate" 
				print="TransDate.printDate" /> 
<enumeration name="DepCategory" members="salary interest-income other"/> 
<enumeration name="CheckCategory" members="rent groceries other"/> 
<interface name="Entry" members="Deposit Check Withdrawal" properties="date amount" /> 
</xml-java-binding-schema>

Esta secci�n nos lleva a trav�s de este esquema de uni�n como si lo hubieramos escrito desde �l principio. Ya hemos incorporado las uniones del elemento de ra�z en la secci�n Crear el Esquema de Uni�n M�nimo Requerido, por eso empecemos con ella:

  1. Reemplazamos la etiqueta de elemento vac�o (/>) con un angulo a la derecha (>) y a�adimos una etiqueta final para la declaraci�n de elemento ra�z transactions porque le vamos a a�adir declaraciones de contenido:
    <xml-java-binding-schema version="1.0ea">
        <element name="checkbook" type="class" root="true" />
        <element name="transactions" type="class" root="true" > 
        </element> 
    
  2. Antes de que empezar a escribir la declaraci�n de uni�n personalizada, las primeras declaraciones que necesitamos en nuestro esquema de uni�n son las declaraciones de uni�n de elemento para los elementos deposit y check porque especificaremos tipos para sus atributos y personalizaremos el modelo de contenido del elemento check . El compilador de esquema necesita estas declaraciones para poder generar las propiedads para los atributos y el contenido de elecci�n en la clase correcta y para los elementos correctos.

    Detntro del elemeno ra�z de nuestro esquema de uni�n, despu�s de las declariones de uni�n de elementos ra�ces, introducimos:

    <element name=deposit type=class >
    
    </element>
    ...
    <element name=check type=class >
    
    </element>
    

    M�s tarde a�adiremos el atributo personalizado y las declaraciones de uni�n de contenidos dentro de estos elementos.

.�Especificar Tipos

Por defecto, el compilador de esquema genera m�todos get que devuelven un String y m�todos set que aceptan un String para todos los elementos y atributos simples. Por ejemplo, consideremos estas declaraciones de uni�n por defecto:

<element-ref name=amount /> 
... 
<element name=amo unt type=value />

Desde estas declaraciones de uni�n, el compilador de esquema genera estos dos m�todos:

public String getAmount(); 
public void setAmount(String amount);

Si deseamos realizar algunos c�lculos con amount, necesitamos convertirla de un String a un alg�n otro tipo que permita que lo utilicemos en un c�lculos. Para los c�lculos que implican valores de moneda, el tipo BigDecimal es una buena opci�n porque representa n�meros decimales con signo de precisi�n arbitrar�a, y la clase BigDecimal proporciona los m�todos para aritm�tica b�sica.

Para especificar un tipo, utilizamos el declaraci�n de conversi�n para definir la conversi�n y el atributo convert de la declaraci�n de elemento o de atributo, dependiendo de si est�mos convirtiendo el tipo de una propiedad de elemento o de una propiedad de atributo, para referenciar la declaraci�n de conversi�n.

Especificar Tipos No Primitivos

Para definir una conversi�n de String a BigDecimal:

  1. A�adimos esta declaraci�n de conversi�n en cualquier lugar en el nivel superior (entre de las etiquetas <xml-java-binding-schema version="1.0ea">) de nuestro esquema de uni�n, quiz�s despu�s de la declaraci�n de uni�n del elemento check:
    <conversion name=BigDecimal type=java.math.BigDecimal />
    

    Cualquier declaraci�n de uni�n de elemento o de atributo que utilice esta conversi�n se refiere a ella por el nombre BigDecimal, seg�n lo especificado por el nombre del atributo. El valor del tipo de atributo es el tipo real al cual se convierte una propiedad.

  2. Para instruir al compilador de esquema para que genere una propiedad amount con un tipo BigDecimal:
    • A�adimos una declaraci�n de uni�n de elemento para el elemento amount en la parte superior de nuestro esquema de uni�n:
      <element name=amount type=value />
      
    • A�adimos un atributo convert a la uni�n del elemento amount y seleccionamos su valor a BigDecimal:
      <element name=amount type=value convert=BigDecimal />
      

    Estas declaraciones de uni�n producen est�s firmas de m�todos:

    public java.math.BigDecimal getAmount(); 
    public void setAmount(java.math.BigDecimal amount);
    

    Declarar por separado la conversi�n de una uni�n de elemento nos permite reutilizar una conversi�n con otras uniones de elemento. Podemos hacer esto con el elemento balance, que tambi�n necesita estar unido a una propiedad BigDecimal.

    Para instruir al compilador de esquema para que genere una propiedad balance con un tipo BigDecimal:

    1. >A�adimos una declaraci�n de uni�n de elemento para el elemento amount en la parte superior de nuestro esquema de uni�n, y asignamos BigDecimal a su atributo convert:
      <element name=balance type=value convert=BigDecimal />
      

    Tambi�n podemos convertir el tipo de la propiedad del elemento date a un java.util.Date. Puesto que una fecha se puede escribir de muchas formas distintas, necesitamos especificar c�mo se debe analizar la fecha cuando se desempaquete y c�mo debe imprimirse cuando se empaquete. La declaraci�n de conversi�n incluye los atributos parse y print para este prop�sito.

    Para convertir los elementos date a un java.util.Date:

    1. A�adimos esta declaraci�n de conversi�n al esquema de uni�n:
      <conversion name=TransDate type=java.util.Date
          parse=TransDate.parseDate print=TransDate.printDate/>
      

      El nombre TransDate se refiere a una clase Java que necesitamos proporcionar. Esta clase contiene un m�todo est�tico parseDate que especifica c�mo analizar la fecha y un m�todo est�tico printDate que especifica c�mo imprimir la fecha.

  3. Para instruir al compilador de esquema para que genere una propiedad date con la clase TransDate, a�adimos un atributo convert a la declaraci�n de uni�n del elemento date y seleccionamos su valor a TransDate:
    <element name=date type=value convert=TransDate />
    

    Estas declaraciones de uni�n producen estas firmas de m�todos:

    public java.util.Date getDate(); 
    public void setDate(java.util.Date x);
    

En el ejemplo de conversi�n BigDecimal, no necesitamos especificar un m�todo de an�lisis o de impresi�n porque la clase java.math.BigDecimal especifica un constructor que acepta un String y devuelve un BigDecimal y un m�todo toString que acepta un BigDecimal y devuelve un String. Para aplicar la conversi�n, el compilador de esquema genera c�digo para invocar al constructor y al m�todo toString.

Especificar Tipos Primitivos

Cuando especificaamos tipos primitivos, tales como int, no necesitamos proporcionar una declaraci�n de uni�n de conversi�n separada; simplemente a�adimos el atributo convert a la declaraci�n de uni�n del elemento o del atributo y asignamos el valor al tipo primitivo.

Dentro de la declaraci�n de uni�n del elemento check, a�adimos una declaraci�n de uni�n de atributo para el atributo number y especificamos un tipo int para su propiedad:

<element name=check type=class > 
<attribute name=number convert=int /> 
</element>

.�Crear Tipos Enumerados

El atributo convert tambi�n se puede utilizar para especificar un tipo enumerado. En el lenguaje de programaci�n Java, representamos tipos enumerados con un tipo seguro enum, que es una clase cuyos ejemplares representan un conjunto fijo de valores.

Un atributo cuyo valor s�lo se pueda fijar a uno de un conjunto fijo de valores es un buen candidato para un tipo enumerado. El DTD checkbook tiene dos de estos atributos: el atributo category del elemento deposit y el atributo category del elemento check:

<!ATTLIST deposit ... category ( salary | interest-income | other ) #IMPLIED >

<!ATTLIST check ... category ( rent | groceries | other ) #IMPLIED >

Para generar los tipos para estos atributos:

  1. Introducimos dos etiqueutas enumeration para cada conversi�n en el nivel superior del esquema de uni�n, quiz�s detr�s de la declaraci�n de conversi�n de TransDate:
    <conversion name=TransDate ...
    <enumeration
    <enumeration
    
  2. Para el atributo name de las etiquetas enumeration, necesitamos un nombre �nico para cada enumeraci�n porque �mbas enumeraciones est�n al mismo nivel en el esquema de uni�n. Introducimos DepCategory para la categoria de deposit y CheckCategory para la categor�a de check.
    <enumeration name="DepCategory"
    <enumeration name=CheckCategory
    

    Estos nombres ser�n los nombres de las clases para representar los tipos seguros enums.

  3. A�adimos un atributo members a cada declaraci�n de enumeraci�n, y les asignamos los posibles valores de cada atributo:
    <enumeration name="DepCategory" members=salary interest-income other />
    <enumeration name=CheckCategory members=rent groceries other />
    
  4. A�adimos las declaraciones de uni�n de attribute dentro de las declaraciones de uni�n de los elementos deposit y check y asignamos el nombre de la declaraci�n de enumeraci�n apropiada a cada atrributo convert de la declaraci�n de uni�n de attribute:
    <element name=deposit ...
        <attribute name=category convert=DepCategory />
    ...
    <element name=check ...
        <attribute name=category convert=CheckCategory />
    

    El compilador de esquema generar� esta clase desde la uni�n del atributo category de check:

    public final class CheckCategory { 
        public final static CheckCategory RENT; 
        public final static CheckCategory GROCERIES; 
        public final static CheckCategory OTHER; 
        public static CheckCategory parse(String x); 
        public String toString(); 
    }
    

    Veremos como trabajar con esta clase en el cap�tulo Construir Representaciones de Datos.

.�Personalizar el Modelo de Declaraci�n de Uni�n de Contenido

Los modelos de contenido pueden ser muy complejos, y por eso el lenguaje de uni�n define muchas declaraciones diferentes de uniones para manejar diversos tipos de modelos de contenido. Definimos estas uniones con la declaraci�n de uni�n de contenido.

Podemos utilizar la declaraci�n de uni�n de contenido para definir dos tipos de declaraciones de modelo de contenido: la propiedad general-content y la propiedad de cotenido basado en modelos. Una propiedad general-content se utiliza para unir un modelo de contenido completoo a una propiedad. Esta declaraci�n no se utiliza para unir cualquier cosa en el DTD checkbook, pero es �til para definir uniones m�s flexibles si nos anticipamos a que el DTD cambiar� en el futuro. Para m�s informaci�n sobre esta declaraci�n, puedes ir a la secci�n Manejar la Evoluci�n del Esquema.

La declaraci�n de propiedad de contenido basado en modelo puede contener cuatro tipos de declaraciones para especificar diferentes tipos de uniones de grupos de modelo:

  • element-ref, que especifica la uni�n de un ejemplar element dentro de otros elementos content. El constructor del elemento especifica la uni�n del propio elemento.
  • choice, que especifica la uni�n de un grupo de modelo de elecci�n anidado a una propiedad.
  • sequence, que especifica la uni�n de un grupo de modelo de elecci�n anidado a una propiedad.
  • rest, que es una declaraci�n de uni�n m�s flexible que podemos utilizar para especificar cualquier tipo de contenido. Puedes econtrar m�s informaci�n en la secci�n Manejar la Evoluci�n del Esquema.

Recordamos de la secci�n Entender las Declaraciones de Uni�n por Defecto que el compilador de esquema asume una declaraci�n de uni�n de la propiedad general-content para los contenidos de los elemento check y transactions porque estos elementos no tienen modelos de contenido simples, con secuencias no repetitivas. En su lugar, estos elementos tienen grupos de modelos de elecci�n en sus declaraciones de contenido:

<!ELEMENT transactions ( deposit | check | withdrawal )* > 
... 
<!ELEMENT check ( date, name, amount, ( pending | void | cleared ), memo? ) > 
...

Esta secci�n muestra c�mo utilizar la declaraci�n de uni�n de elecci�n para hacer que el compilador de esquema genere propiedads m�s �tiles para el contenido de estos elementos. En el caso del contenido del elemento transactions, deseamos asignar el grupo entero a una propiedad de elecci�n. Para especificar la uni�n del contenido del elemento transactions:

  1. Dentro de la declaraci�n de uni�n del elemento transactions, introducimos una etiqueta content y una declaraci�n de uni�n choice, y asignamos el valor entries al atributo property:
    <element name=transactions type=class root=true >
        <content>
            <choice property=entries
    

    El compilador de esquema generar� una propiedad llamada Entries. Por ejemplo, el m�todo get se llamar� getEntries. La raz�n por la que utilizamos el nombre entries, es porque el nombre se refiere a un declaraci�n de interface, que la secci�n Crear Interfaces nos ense�ar� como crear.

  2. Como el modelo de contenido tiene un indicador de ocurrencia *, necesitamos unir este contenidos a una propiedad collection. Introducimos el atributo collection y le damos el valor list:
    <choice property=entries collection=list />
    

    Una propiedad collection puede representar un array o una List. En este caso, deber�amos unir el contenido a una List, porque �sta, al contrario que el array, nos permite a�adir m�s entradas durante la ejecuci�n.

  3. Introducimos la etiqueta final para la declaraci�n de uni�n content:
    </content>
    

Estas declaraciones de uni�n producir�n est� propiedad en la clase Transactions:

public List getEntries(); 
public void deleteEntries(); 
public void emptyEntries();

El m�todo getEntry devuelve la lista de entradas completa. Una vez que consigamos la lista, podemos iterar a trav�s de la lista como lo har�amos con cualquier lista para llegar a una entrada determinada. La lista devuelta por getEntries es modificable: si modificamos una entrada en esta lista, cambiar� la entrada en el �rbol de contenido. El m�todo emptyEntries desecha los valores de la lista y crea una nueva lista, vac�a. El m�todo deleteEntries borra la lista.

Para especificar la uni�n del grupo del modelo de alecci�n anidado en el modelo de elecci�n del elemento check, dentro de la declaraci�n de uni�n del elemento check:

  1. Introducimos las declaraciones de uni�n element-ref para los elementos date, name, y amount, e insertamos la declaraci�n de uni�n de elecci�n como se muestra en negrita en la declaraci�n de uni�n del elemento check:
    <element name=check type=class >
        <attribute name=number convert=int />
        <attribute name=category convert=CheckCategory />
        <content>
            <element-ref name=date />
            <element-ref name=name />
            <element-ref name=amount />
            <choice property=pend-void-clrd />
        </content>
    </element>
    

El valor del atributo property es el nombre de la propiedad generada. Por ejemplo, el m�todo get se llamar� getPendVoidClrd. Si el contenido tambi�n contiene una opci�n, una secuencia, o un declaraci�n de uni�n de resto de contenido, necesitamos especificar las declaraciones de uni�n por defecto de element-ref para los elementos que preceden a este contenido; si no, el compilador de esquema no sabe qu� elementos se han pensado para dichas declaraciones de uni�n.

.�Crear Interfaces

Puede ser que hayas notado que los elementos deposit, check, withdrawal tienen cierto contenido com�n. Puede que tambi�n hayas notado que cada uno representa una entrada en una lista de transacciones. Cuando tenemos un grupo de clases que proporcionan funciones similares y tienen alg�n comportamiento y propiedades comunes, podemos utilizar un interface para capturar las semejanzas entre las clases. En el caso de deposit, check, y withdrawal, todas tienen los elementos date y amount. Estos elementos ser�n propiedads comunes en el interface.

Para hacer que el compilador de esquema genere un inteface, con Deposit, Check, y Withdrawal implementaremos:

  1. En cualquier lugar del nivel m�s alto de nuestro esquema de uni�n, quiz�s despu�s de las declaraciones de enumeraci�n, introducimos esta declaraci�n de interface:
    <interface name=Entry members=Deposit Check Withdrawal
    	properties=date amount />
    

    El atributo members representa todas las clases que implementan el interface. El atributo properties representa el contenido com�n compartido por los miembros del interface.

Como los elementos deposit, check, withdrawal ocurren en el modelo contenido de las transacciones como un grupo de elecci�n, necesitamos referenciar Entry desde la uni�n del grupo de elecci�n. Previamente asignamos el nombre del interface al atributo de la propiedad y al valor list del atributo collection. Asignamos el nombre del interface al atributo supertype:

<element name=transactions type=class class=Transactions > 
<content> 
    <choice property=entries collection=list supertype=Entry />
</content> 
</element>

El atributo supertype indica una clase o interface declarada en el esquema de uni�n que cada clase de elemento incl�ida en la propiedad choice implementa.

Estas declaraciones de uni�n producir�n un interface llamado Entry, que incluir� las propiedades date y amount:

public interface Entry { 
    ... 
    public int getAmount(); 
    public void setAmount(int x); 
    public Date getDate(); 
    public void setDate(Date d);

.�Manejar la Evoluci�n del Esquema

Como con cualquier recurso que genere c�digo, un desarrollador que escriba aplicaciones b�sadas en el c�digo necesita asegurarse de que el c�digo recientemente generado no rompa las aplicaciones. Si nos anticipamos a que el DTD cambiar�, podemos utilizar las declaraciones de uni�n m�s flexibles en el lenguaje de uni�n para proteger la integridad de las aplicaciones.

La manera m�s f�cil de manejar la evoluci�n del esquema es aceptar los uniones por defecto que el compilador de esquema produce. Estas uniones son definiciones muy flojas de las declaraciones del DTD, y as� son m�s flexibles a los cambios del DTD. Por ejemplo, cualquier grupo de modelo que no consista en elementos distintos en una secuencia no-repetitiva se unir� usando una declaraci�n de propiedad de contenido general, que une todo el contenido a una propiedad. Si agregaramos elementos a este grupo de modelo, estos elementos todav�a ser�an representados por la propiedad, y las clases no cambiar�an.

Podemos usar la declaraci�n de propiedad de contenido general para cualquier grupo de modelo. Para unir content usando esta declaraci�n, usamos la construcci�n content:

<content property=mygroup />

Esta uni�n gener� esta propiedad:

public List getMygroup(); 
public void deleteMygroup(); 
public void emptyMygroup();

Otra declaraci�n de uni�n que podemos utilizar para manejar la evoluci�n del esquema es la declaraci�n de uni�n rest. Esta declaraci�n de uni�n es similar a la declaraci�n de la propiedad de contenido general en que puede representar cualquier tipo de contenido. A�adiendo una declaraci�n rest sobre una declaraci�n de uni�n de elemento content, podemos a�adir otros elementos y grupos al modelo de contenido del DTD en el futuro sin afectar a las clases generadas. Por ejemplo, podemos a�adir una construcci�n rest a la uni�n de contenido del elemento withdrawal:

<content> 
    ... 
<rest property=rest />

</content>

como ya tenemos la propiedad rest, podemos a�adir otro contenido al elemento withdrawal sin romper la aplicaci�n. Adem�s, todav�a podemos tener acceso individualmente al viejo contenido con las propiedads generadas por las otras declaraciones dentro de la declaraci�n de contenido. Solamente el nuevo contenido, definido por la propiedad rest, ser� representado por una propiedad List.

.�Generar las Clases Java

Ahora que hemos terminado el esquema de uni�n, podemos ejecutar el compilador de esquema para generar las clases Java. Esta gu�a asume que hemos seguido las instrucciones en las notas de liberaci�n, situadas en el directorio doc de la instalaci�n y hemos configura los classpaths correctamente.

Para generar las clases Java:

  1. Ejecutamos el compilador de esquema con checkook.dtd y checkook.xjs, el esquema de uni�n que hemos creado:
    xjc checkook.dtd checkook.xjs
    

    Ahora deber�amos ver los ficheros Checkbook.java y Entry.java en nuestro directorio actual.

  2. Compilamos los ficheros fuentes en clases Java:
    javac *.java
    

    El resto de esta secci�n explica el c�digo generado en estos ficheros. Si no necesitas una explicaci�n del c�digo, puedes ir al siguiente cap�tulo Construir Representaciones de Datos para construir �rboles de contenido usando las clases.

.�Los Ficheros Fuente Java Generados

Esta secci�n explica abreviadamente algunos de los m�todos y de las clases p�blicas generadas por el compilador de esquema basadas en el DTD checkbook y el esquema de uni�n que creamos en la secci�n anterior. Puesto que las clases Deposit, Check, y Withdrawal son tan similares, entre estas clases, esta secci�n explica solamente la clase Check. Asimismo, esta secci�n explica solamente la clase enumerada CheckCategory, y entre las clases Pending, void, Cleared, esta secci�n explica solamente la clase pending.

.�El fichero Checkbook.java

El elemento checkbook del DTD transactions.dtd est� unido a la clase Checkbook cuya firma es:

public class Checkbook extends MarshallableRootElement implements RootElement

Como checkbook es un elemento ra�z, la clase Checkbook extiende MarshallableRootElement, que es la clase que representa objetos elemento ra�z que pueden ser empaquetados y desempaquetados, e implementa RootElement.

Como cada clase generada, la clase Checkbook contiene un constructor sin argumentos:

public Checkbook();

Recuerda que el elemento checkbook contiene un elemento transactions y un elemento balance:

<!ELEMENT checkbook ( transactions, balance ) >

Estos elementos est�n unidos a �stas propiedades en el clase Checkbook:

// the transactions property 
public void setTransactions(Transactions x); 
public Transactions getTransactions();

// the balance property 
public void setBalance(java.math.BigDecimal x); 
public java.math.BigDecimal getBalance();

La propiedad transactions acepta y devuelve un objeto transactions porque el elemento transactions tambi�n est� representado por una clase. La propiedad balance acepta y devuelve un java.math.BigDecimal debido a �stas declaraciones de uni�n que especificamos en la secci�n Especificar Tipos:

<element name="balance" type="value" convert="BigDecimal"/> 
... 
<conversion name="BigDecimal" type="java.math.BigDecimal" />

Aunque MarshallableRootElement define m�todos marshal, que la clase Checkbook usa por extensi�n, no define ning�n m�todo unmarshal. As�, el compilador de esquema genera estos m�todos unmarshal est�ticos en la clase Checkbook:

public static Checkbook unmarshal(InputStream in)
public static Checkbook unmarshal(XMLScanner xs)
public static Checkbook unmarshal(XMLScanner xs, Dispatcher d)

Cuando despempaquetamos un documento XML, podemos invocar a unmarshal(InputStream) o a unmarshal(XMLScanner) en los que InputStream o XMLScanner representan nuestro documento XML.

Aunque el desempaquetamiento realiza la validaci�n por nosotros, necesitamos realizar validaci�n despu�s de editar el �rbol de contenido y antes de empaquetarlo en un documento XML. Para este prop�sito, el compilador de esquema genera estos m�todos:

public void validateThis(); 
public void validate();

Despu�s de editar una parte del �rbol de contenido, podemos usar validateThis para validar el objeto editado. Antes de empaquetar el arbol de contenido a un documento XML, debemos usar validate para validar todos el �rbol de contenido.

.�El Fichero Transactions.java

El elemento transactions de checkokk.dtd est� unido a la clase Transactions cuya firma es:

public class Transactions extends MarshallableRootElement implements RootElement

Al igual que checkbook , transactions es un elemento ra�z, y por eso la clase Transactions extiende MarshallableRootElement, e implementa RootElement. La clase Transactions contiene un constructor sin argumentos:

public Transactions();

El elemento transactions contiene cero o m�s elementos deposit, check, o withdrawal:

<!ELEMENT transactions (deposit | check | withdrawal)* >

Cuando seguimos las instrucciones de Personalizar las Declaraciones de Uni�n del Modelo de Contenido, especificamos que el compilador de esquema uniera el contenido del elemento transactions a una propiedad de colecci�n List llamada entries. En la secci�n Crear Interfaces, especificamos que el supertype de la propiedad entries es el interface Entry:

<element name=transactions type=class class=Transactions > 
<content> 
    <choice property=entries collection=list supertype=Entry />
</content> 
</element>

El declaraci�n de uni�n del interface hizo que el compilador de esquema uniera el contenido de transactions a una lista de deposit, check, y withdrawals. La declaraci�n de uni�n del interface hizo que el compilador de esquema generara un interface Entry, que implementaban las clases Deposit, Check, y Withdrawal. El interface Entry se explica en la siguiente secci�n.

La propiedad entries consta de tres m�todos que usamos para aceder al contenido del elemento transactions:

public List getEntries(); 
public void deleteEntries(); 
public void emptyEntries();

El m�todo getEntry devuelve la lista de entradas completa. Una vez que consigamos la lista, podemos iterar a trav�s de la lista como lo har�amos con cualquier lista para obtener una entrada determinada. La lista devuelta por getEntries es modificable: Si cambiamos una entrada de esta lista, cambiar� la entrada en el �rbol de contenido. El m�todo deleteEntries suprime la lista de entradas actual. El m�todo emptyEntries suprime los valores de la lista.

Cualquier contenido de transactions (tanto si son dos dep�sitos o un dep�sito y cinco reintegros) implementa Entry. Por lo tanto, no necesitamos realizar pruebas de instanceof o forzados de tipo en los items de lista que representan entradas, a menos que estemos trabajando con un elemento contenido en deposit, check, o withdrawal que no sea un miembro del interface Entry.

Al igual que la clase Checkbook, la clase Transactions contiene los m�todos marshal, unmarshal y validate que un usuario deber�a invocar.

.�El Fichero Entry.java

El supertype del contenido del elemento transactions es el inteface Entry, como se especifica en esta declaraci�n de uni�n de inteface:

<element name=transactions type=class class=Transactions > 
    <content> 
        <choice property=entries collection=list supertype=Entry />
    </content> 
</element>

La firma del inteface Entry es:

public interface Entry {

El �nico contenido de elementos comunes entre los elementos deposit, check, y withdrawal son date y amount, y por eso asignamos estos elementos al atributo properties de la construcci�n del interface en la secci�n Crear Interfaces

<interface name=Entry members=Deposit Check Withdrawal properties=date amount />

Por lo tanto, el interface Entry, incluye las propiedades para los elementos date y amount:

public int getAmount(); 
public void setAmount(int x); 
public Date getDate(); 
public void setDate(Date d);

La propiedad amount devuelve y acepta un int porque escribimos una declaraci�n de conversi�n de uni�n para convertir desde String a BigDecimal y utilizamos el atributo convert en la declaraci�n de uni�n del elemento amount y le asignamos el valor BigDecimal:

<element name=amount type=value convert=BigDecimal /> 
<conversion name="BigDecimal" type="java.math.BigDecimal" />

.�El Fichero Check.java

El elemento check est� unido a la clase Check, que tiene la firma:

public interface Check extends MarshallableObject implements Element, Entry{

La clase Check extiende MarshallableObject, que es la clase abstracta que representa cualquier objeto que se pueda empaquetar o despempaquetar pero no sea necesariamente un elemento ra�z. La clase Check debe implementar Element porque, al contrario que MarshallableRootElement, un MarshallableObject no tiene que ser un objeto derivado de un elemento y por lo tanto no implementa Element en si mismo. Finalmente, Check implementa Entry porque especificamos Entry como el supertype del contenido del elemento transaction en la secci�n Crear Interfaces. El elemento check tiene dos atributos y contiene seis elementos:

<!ELEMENT check ( date, name, (pending | void | cleared), memo? ) >
<!ATTLIST check
        number CDATA #IMPLIED
        category ( rent | groceries | other ) #IMPLIED >

El elemento date est� unido a una propiedad y devuelve un objeto Date:

public Date getDate(); 
public void setDate(Date x);

Los elementos name, y memo, que s�lo contienen texto est�n unidos a estas propiedades:

public String getName(); 
public void setName(String x); 
public String getMemo(); 
public void setMemo(String x);

En la secci�n Especificar Tipos, especificamos un tipo int para el atributo number, produciendo esta propiedad:

public int getNumber(); 
public void setNumber(int x);

En la secci�n Personalizar Declaraciones de Uni�n de Modelos de Contenido especificamos que el modelo de grupo de elecci�n, (pending | void | cleared), est� unido a una propiedad, produciendo estos m�todos:

public MarshallableObject getPendVoidClrd(); 
public void setPendVoidClrd(MarshallableObject x);

La propiedad pend-void-clrd devuelve y acepta un MarshallableObject, que representa objetos que pueden ser empaquetados y desempaquetado. La raz�n por la que este tipo de propiedad no es un String es porque no podemos determinar si un String se supone que es un elmento pend, void, cleared; con MarshallableObject, si podemos porque el MarshallableObject ser� un objeto Pend, Void, o Cleared. La clase Check tambi�n contiene una propiedad para la enumeraci�n checkCategory, que especificamos en la secci�n Crear Tipos Enumerados:

<enumeration name=CheckCategory members=rent groceries other />
... 
<attribute name=category convert=CheckCategory />

La propiedad que genera est� declaraci�n de uni�n es:

public CheckCategory getCheckCategory();
public void setCheckCategory(CheckCategory x);

Esta propiedad acepta y devuelve un objeto CheckCategory, que es un interface de la clase CheckCategory. Esta clase se explica en la siguiente secci�n.

.�El Fichero CheckCategory.java

El atributo category toma un valor de un conjunto fijo de valores representado por un grupo de elecci�n en la definici�n de atributo:

<!ATTLIST check ... category ( rent | groceries | other ) #IMPLIED >

Cuando seguimos las instrucciones de la secci�n Crear Tipos Enumerados, especificamos una unid�n de este atributo a un tipo seguro enum:

<enumeration name=CheckCategory members=rent groceries other />
... 
<attribute name=category convert=CheckCategory />

Un tipo seguro enum es una clase que representa una enumeraci�n que consta de un elemento o un atributo y la lista de los posibles valores, s�lo uno de los cuales puede asignarse a la clase. El nombre de la clase corresponde al del elemento o del atributo, y los campos est�ticos representan los valores. Las clases de tipo seguro enum tienen muchas ventajas, incluyendo controlar el tipo en tiempo de compilaci�n. El tipo seguro enum generado desde el atributo category es:

public final class CheckCategory { 
    public final static CheckCategory RENT; 
    public final static CheckCategory GROCERIES; 
    public final static CheckCategory OTHER; 
    public static CheckCategory parse(String x); 
    public String toString(); 
}

El m�todo parse intenta mapear un argumento String a uno de los valores aceptados. El m�todo toString devuelve el valor actual de un CheckCategory como un String.

.�El Fichero Pending.java

La clase Pending representa uno de los miembros del modelo de grupo de elecci�n contenido en la declaraci�n del elemento check:

<!ELEMENT check ( date, name, ( pending | void | cleared), memo? ) >

Este elemento, as� como los elementos void o cleared, est�n unidos a sus propias clases porque son parte de este grupo modelo de elecci�n. Seg�n lo explicado en el secci�n del fichero Check.java, la propiedad a la que est� unido este grupo debe devolver un MarshallableObject, que debe tambi�n ser un objeto Pend, Void o Cleared, de modo que la aplicaci�n sepa qu� elemento encontrar� durante el empaquetamiento o despempaquetamiento. Las clases Pend, Void y Clearedtienen un constructor sin argumentos.

El siguiente cap�tulo nos mostrar� como trabajar con estas clases para construir representaciones de datos.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO