|
El API JAXB |
Trabajar con los Datos
Este capítulo muestra cómo utilizar extensión para añadir funcionalidades específicas de la aplicacion a nuestra aplicación JAXB. Continuaremos con el CheckbookApp que creamos en el capítulo anterior. En este capítulo, crearemos una nueva clase, llamada CheckbookBalance. Esta nueva clase extenderá la clase Checkbook generada y contendrá un método que añada las transacciones al checkbook y calcule el nuevo balance. La clase CheckbookApp llama a este nuevo método para añadir las transacciones de Marzo y Abril (representadas por los árboles de contenido que creamos en el capítulo anterior) al checkbook. En este capítulo, trabajaremos con el documento checkbook.xml, que representa el libro de cheques. La lista de transacciones y el balance de la cuenta.
El Documetno XML de Ejemplo: checkbook.xml
El documento de checkbook.xml define un checkbook, que contiene un conjunto de transacciones y un balance, así que en vez de definir transactions como el elemento raíz, este documento define el elemento checkbook como el elemento raíz, que contiene la lista de transacciones y el balance:
<?xml version="1.0" encoding="US-ASCII"?>
<checkbook>
<transactions>
<deposit category=salary>
<date>02-09-2001</date>
<name>Me</name>
<amount>2500.00</amount>
</deposit>
<check number="90" category="other">
<date>02-12-2001</date>
<name>My Local Bookstore</name>
<amount>34.95</amount>.
<pending/>
<memo>Dukes Book</memo>
</check>
<check number="91" category="rent">
<date>02-28-2001</date>
<name>Landlord</name>
<amount>1500.00</amount>
<void/>
<memo>February</memo>
</check>
</transactions>
<balance>50000.00</balance>
</checkbook>
Observa que checkbook sólo tiene las transacciones de Febrero. Este capítulo mostrará cómo añadir las transacciones de Marzo y de Abril al checkbook y poner al día el balance. El fichero checkbook.xml también está situado en el directorio examples/checkbook de la instalación.
Configurar la Clase CheckbookBalance
Para crear la clase CheckbookBalance:
- Creamos un fichero llamado CheckbookBalance.java.
- Importamos estos paquetes:
import java.io.*; import java.util.*; import java.math.*;
- Declaramos la clase CheckbookBalance para que extienda Checkbook:
public class CheckbookBalance extends Checkbook { } - Dentro de CheckbookBalance, creamos el método balanceCheckbook:
public class CheckbookBalance extends Checkbook { void balanceCheckbook(Transactions trans) throws Exception { } }Este método contendrá todo el código para agregar transacciones al checkbook y para calcular el nuevo balance. La clase CheckbookApp pasará la lista completa de transacciones que creamos en la sección anterior al método balanceCheckbook.
Extender las clases Derivadas
En el capítulo Construir Representaciones de Datos, aprendimos cómo utilizar directamente las clases derivadas. Otra manera de usar las clases derivadas es con la extensión. La extensión implica la subclasificación de una clase derivada para proporcionar funciones específicas. Esta sección explica la extensión mostrando cómo balancear el checkbook y agregar las entradas de transacciones al checkbook.
Desempaquetar
Antes de que podamos realizar los cálculos, necesitamos desempaquetar el fichero que contiene las transacciones en un árbol de contenido, como hizimos en la sección Desempaquetamiento del capítulo anterior. Sin embargo, este vez estamos extendiendo checkbook en vez de utilizarlo directamente, lo que significa que desempaquetamos un objeto CheckbookBalance, no un objeto Checkbook. Si no especificamos que CheckbookBalance debe ser desempaquetado, el proceso de desempaquetamiento devuelve un objeto Checkbook, no un objeto CheckbookBalance. Para solucionar este problema, necesitamos registrar CheckbookBalance con un Dispatcher.
Despachar
Un dispatcher asocia nombres de elementos con nombres de clases y nombres de sublases con nombres de clases. El proceso de desempaquetamiento comienza con la llamada de los métodos unmarshal de un dispatcher. Un dispatcher por defecto desempaqueta contenido XML XML en ejemplares de las clases generadas. Para nuestro ejemplo, esto significa que el método unmarshal devolvería un checkbook, no un CheckbookBalance. Para devolver un CheckbookBalance, necesitamos registrar CheckbookBalance con el Dispatcher. Para hacer esto:
- En la parte superior de CheckbookApp.java , inicializamos un objeto
CheckbookBalance:
public static CheckbookBalance chBook = new CheckbookBalance();
- Creamos un nuevo método en CheckbookApp.java llamado unmarshalSubclass:
public static void unmarshalSubclass() throws Exception{} - En este nuevo método, adquirimos el Dispatcher por defecto de Checkbook:
Dispatcher d = Checkbook.newDispatcher();
- Registramos CheckbookBalance con el Dispatcher devuelto:
d.register(Checkbook.class, CheckbookBalance.class);
Este método registra la subclase CheckbookBalance con el Dispatcher para que pueda desempaquetar un CheckbookBalance en lugar de un Checkbook.
- Llamamos a unmarshalSubclass desde el método main:
unmarshalSubclass();
Desempaquetar las Subclases
Como registramos CheckbookBalance con un Dispatcher, necesitamos llamar al método unmarshal del dispatcher, no al método unmarshal del objeto CheckbookBalance. Para desempaquetar CheckbookBalance:
- En el método unmarshalSubclass, leemos checkbook.xml en un
FileInputStream:
File checkbookNew = new File(checkbook.xml); FileInputStream fNewIn = new FileInputStream(checkbookNew);
- Forzamos el objeto devuelto por el método unmarshal a un objeto
CheckbookBalance:
try{ chBook = (CheckbookBalance)(d.unmarshal(fNewIn)); } finally { fNewIn.close(); }
La siguiente sección demuestra cómo implementar los cálculos del balance del libro de cheques en CheckbookBalance.java.
Añadir Funcionalidad
El fichero CheckbookBalance.java sólo contiene un método: balanceCheckbook. Esta sección muestra cómo implementar balanceCheckbook para calcular el nuevo balance basándose en el balance del més anterior y añadiendo las transacciones de Marzo y Abril. Para implementar el método balanceCheckbook en la clase CheckbookBalance:
- Obtenemos el balance actual grabado en nuestro checkbook:
BigDecimal balance = this.getBalance();
- Obtenemos la lista de entradas de los objetos Transactions qu se pasa a este método:
List tEntries = trans.getEntries();
- Inicializamos un BigDecimal para guardar la cantidad de cada transación:
BigDecimal amt;
- Creamos un bucle para iterar a través de la lista de transaciones y obtener la cuantía de cada una:
for (ListIterator i = tEntries.listIterator(); i.hasNext(); ) { Entry entry = (Entry)i.next(); amt = entry.getAmount(); - Si la entrada es un Deposit, añadimos la cuantía del depósito al
balance del checkbook; de otro modo, restamos la cuantía de
la transación al balance:
if (entry instanceof Deposit){ balance = balance.add(amt); } else { balance = balance.subtract(amt); } - después de recalcular el balance basado en la transacción, añadimos la transación a la lista de transaciones del
checkbook:
this.getTransactions().getEntries().add(entry); }
- Después de haber iterado por la lista de transaciones, chequemos si el balance es negativo. Si es así, avisamos al usuario
de que está en números rojos:
if(balance.compareTo(new BigDecimal(0.00)) == -1){ System.out.println("You are overdrawn."); } - Imprimimos el nuevo balance y seleccionamos el balance del
checkbook al nuevo balance:
System.out.println("Your balance is: "+balance); this.setBalance(balance);
La siguiente sección muestra cómo invocar la nueva funcionalidad en CheckbookBalance desde CheckbookApp.java.
Usar las Nuevas Funcionalidades en Nuestra Aplicación
Esta sección muestra cómo utilizar el método balanceCheckbook de CheckbookApp para balancear checkbook y para añadir las transacciones a de Marzo y Abril al checkbook. La clase CheckbookBalance está escritá de una forma genérica de modo que pueda tomar cualquier objeto transactions y añadir las transacciones a un checkbook y calcular el nuevo balance. Todo lo que necesitamos hacer desde neustra aplicación es llamar al método balanceCheckbook con un objeto Transactions particular y empaquetar el resultado en un nuevo fichero checkbook. Para poner al día el checkbook con las nuevas transacciones y balancear:
- En el método main de la clase CheckbookApp, llamamos al
método balanceCheckbook con el objeto marchTrans:
chBook.balanceCheckbook(marchTrans);
Este objeto contiene la lista de transaciones de Marzo y Abril que creamos en la sección Añadir Árboles de Contenido. El objeto chBook ahora contiene las transaciones y el balance actualizados.
- Creamos un nuevo método en CheckbookApp llamado
validateAndMarshalCheckbook:
public static void validateAndMarshalCheckbook() throws Exception {} - Como editamos el árbol de contenido del checkbook, realizamos la validación sobre
chBook dentro del nuevo método que acabamos de crear:
chBook.validate();
- Creamos un nuevo fichero XML para el checkbook actualizado:
File checkbook_new = new File("checkbook_new.xml"); FileOutputStream fCOut = new FileOutputStream(checkbook_new); - Empaquetamos el checkbook actualizado en el nuevo fichero XML:
try { chBook.marshal(fCOut); } finally { fCOut.close(); } - Llamamos a validateAndMarshalCheckbook desde el método main
de CheckbookApp:
validateAndMarshalCheckbook();
- Grabamos CheckbookBalance.java y CheckbookApp.java y recompilamos:
javac *.java
- Ejecutamos de nuevo CheckbookApp:
java CheckbookApp
Nuestro fichero checkbook_new.xml tiene un balance actualizado de $48065.72 y contiene nuestras transaciones de Febrero, Marzo y Abril.
















































