Primi Passi con BeanIO (parte 3)

Proseguiamo la serie dedicata al framework BeanIO con questo terzo articolo in cui illustriamo ulteriori aspetti della libreria.

Raggruppamento dei Record

Già nel precedente post Primi Passi con BeanIO (parte 2) abbiamo introdotto la gestione dei record multipli, che ci ha consentito di produrre uno stream suddiviso in tre parti: un header, un insieme di record di dettaglio ed un trailer. Il problema che vogliamo ora risolvere è quello di dover raggruppare i record, ripetendoli più volte nello stream. Immaginiamo ad esempio di voler produrre uno stream in cui per ogni Customer vogliamo riportare gli ordini associati. Lo stream dovrà quindi avere la seguente struttura:

BeanIO consente di definire gruppi di record utilizzando il tag <group> per wrappare i tipi di record che appartengono al gruppo. Il tag supportano gli stessi attributi order, minOccurs e maxOccurs, sebbene il significato sia applicato all’intero gruppo. Una volta che un tipo di record è riconosciuto come appartenente a un gruppo, tutti gli altri record in quel gruppo in cui minOccurs è maggiore di 1, devono essere letti dallo stream prima che il gruppo possa ripetersi o possa essere letto un altro record. Si noti che in un certo senso anche il tag <stream> è un tag di raggruppamento.

L’xml che definisce il layout richiesto sarà quello mostrato di seguito, in cui è stata dettagliata solamente la definizione del nuovo bean Order:

Come già detto la scrittura dei record deve seguire l’ordine definito nel layout, quindi la classe  CustomerOrderWriter sarà del tipo:

Il file prodotto, infine, sarà:

La classe CustomerOrderReader non è molto diversa da quella già vista per la lettura di record multipli, in cui però dovremmo tenere conto della nuova tipologia di record. Per completezza riporto la sola porzione di codice che esegue la lettura dallo stream:

Gestione delle Proprietà dei Bean

Abbiamo visto come nel file di mapping le proprietà dei bean vengono descritte per mezzo del tag <field> il cui solo attributo obbligatorie è il nome della proprietà associata. Nel caso in cui i metodi getter e setter per il recupero della proprietà dal bean non sia del tipo get/set+<fieldName> è anche possibile valorizzare gli attributi getter e setter del tag:

L’aspetto più interessante però nella trattazione delle proprietà è la type conversion. Il tipo di un campo è determinato dall’introspezione dell’oggetto bean a cui appartiene la proprietà. Se la classe bean è di tipo java.util.Map o java.util.Collection, BeanIO assumerà che il campo sia di tipo java.lang.String, a meno che un tipo di campo non venga dichiarato esplicitamente utilizzando l’attributo type di <field>. L’attributo type può essere impostato su qualsiasi nome di classe completo o su uno degli alias di tipi supportati: string, boolean, byte, char, short, etc. Si segua il link FieldTypeConversion per l’elenco completo.

Infine è anche possibile valorizzare l’attributo format per quelle proprietà che per loro natura possono risultare ambigue, come accade ad esempio per il tipo Data.

Sintetizzando BeanIO include i gestori di i più comuni tipi Java ma consente anche di creare il proprio gestore implementando l’interfaccia org.beanio.types.TypeHandler illustrata di seguito.

Supponiamo ad esempio di voler definire un handler per il tipo boolean, i cui valori sono normalmente convertiti nelle stringhe true e false, al fine di serializzare il tipo nelle stringhe Y (per il valore true) e N (per il valore false). L’handler avrà il seguente aspetto:

Si noti che nello sviluppare un handler di tipo custom, si deve fare attenzione alla gestione dei valori nulli e stringhe vuote.

Per utilizzare l’hander appena definito si utilizza il tag <typeHandler> nel file di mapping, mentre per legarlo alla proprietà da convertire abbiamo due possibilità. La prima consiste nel definirlo come handler globale per tutti i tipi boolean, valorizzando l’attributo type del tag:

La seconda è quella di assegnare un nome all’handler, valorizzando l’attributo name del tag <typeHandler>, e di specificare su quali proprietà applicarlo, valorizzando l’attributo typeHandler del tag <field>:

Codice Sorgente

Il codice sorgente con l’esempio presentato è scaricabile qui bean-io