Trasferire i dati da un file all'altro in maniera semplice ed affidabile è diventata un'esigenza sempre più frequente. Ecco come da un problema incontrato di recente è nato lo spunto per questo articolo.

Il problema

Nella soluzione ideata per la fattura alla Pubblica Amministrazione viene creato un file XML con i dati della fattura, spesso sotto forma di codici forniti dalla PA stessa. Occorre poi verificare che il file sia a posto, cioè che i campi obbligatori abbiano un valore, che formato e lunghezza dei campi siano congrui e che siano presenti alcuni valori rispondenti a determinate condizioni.

Fin qui, niente di complicato: basta prevedere alcune liste valori e delle validazioni a livello di campo.

Il problema nasce però dal fatto che codici e condizioni verranno con ogni probabilità modificati nelle versioni successive, il che manda all'aria qualsiasi forma di validazione sia a livello di campo che a livello di script.

Come fare allora? Prevedere una mega routine di aggiornamento per ogni nuova versione? Si tratta però di un'opzione scomodissima che oltretutto non risolve il problema, specialmente nel caso degli utenti che hanno integrato il file nella loro soluzione.

Quali sono le alternative?

La soluzione

L'alternativa consiste nello spostare i criteri con cui eseguire le verifiche in una tabella Controlli, eseguendo poi uno script che capisce quali campi verificare attraverso le funzioni GetField() ed Evaluate().

Gli aggiornamenti della logica avvengono quindi attraverso l'aggiornamento di questa tabella. Ma come eseguire questo aggiornamento? Ci serve una routine semplice che ci dia la possibilità di scegliere quali tabelle aggiornare, e transazionale, per evitare una trasmissione incompleta dei dati.

La tecnica wrap/unwrap

Il risultato è una tecnica che ho chiamato wrap/unwrap, letteralmente incarta/scarta, traducibile anche in prendi, incarta e porta a casa.

Il concetto di fondo è quello di creare un singolo blocco di testo che contenga tutti i dati da aggiornare.

I dati in sostanza vengono incartati in un guscio fatto in XML che avvolge ciascun elemento (tabella, record, campo) con dei tag appropriati. Questi vengono poi spediti al destinatario, il quale esegue una procedura con cui li scarta e ricrea i record originali.

Vediamo la tecnica in dettaglio.

Step 1: Incarto

Nei tip files si simula una situazione in cui si ha un file centrale (incarta.fmp12) che invia aggiornamenti ad una sede periferica (scarta.fmp12). Le tabelle che vengono aggiornate sono due, Prodotti e Preferenze.

prodotti

preferenzeCliccando sul pulsante Aggiornamenti compare il popover, col pulsante Crea aggiornamento col quale si dà il via allo script.

aggiornamenti

Lo  script inizia dal Layout numero 1, e procede avanzando di layout in layout. Quando il layout fa parte di quelli scritti in un campo/variabile globale, i campi e la tabella cui appartiene vengono processati.

Nota: per semplificare nel tip file ho omesso la possibilità di scegliere quali layout/tabelle aggiornare: un altro elemento di grande flessibilità del metodo.

wrap_script

La processazione dei dati della tabella avviene nello script "raccogli i dati e mettili nel guscio XML". Questa si occupa della raccolta dati con un loop esterno che passa in rassegna tutti i record, ed uno interno che processa i campi che trova nel formato. Il contenuto di ciascun campo viene incartato e avvolto in un tag XML costituito dal nome del campo attraverso l'utilizzo di una custom function.

process_data

La custom function che "incarta" i dati si chiama PassXML (Name; Content), originalmente creata da Andy Knasinski:

Case( IsEmpty ( Name ) or IsEmpty ( Content )  ; "" ; "<" & Name & ">" & Content &  "</" & Name & ">" )

Il risultato finale dell’operazione è un blocco di testo del tipo

<table_Products>

<record>

<ProductID>Prod001</ProductID>

<ProductName>wheelbarrow</ProductName>

<ProductPrice>111</ProductPrice>

</record>

</table_Products>

<table_other_tablename>

<record>

etc ...

</record>

</table_other_tablename>

Questo è il testo che viene quindi inviato alla sede remota, dove verrà usato per aggiornare le varie tabelle.

Nota: per semplificare nei tip files non ho messo la parte di trasmissione dei dati, che quindi va eseguita manualmente con un copiaincolla del blocco di testo XML.

Step 2: Scarto

Arrivati i dati alla sede remota, è tempo di "scartarli" per poter aggiornare le tabelle.

esegui_agg

Lo script che viene eseguito esegue sostanzialmente un reverse engineering della procedura di incartamento: quando un tag  <table> viene trovato il suo contenuto viene passato allo script di processazione, che provvederà a ricreare i record e a scrivere i valori nei campi.

install_update

Lo script "Processa i dati dell'aggiornamento" esegue un loop all’interno del testo (che è a questo punto quello di pertinenza di una singola tabella), un loop esterno che processa ciascun record ed uno interno che processa i singoli campi del record utilizzando il contenuto del tag XML per identificare il campo, ed uno step Set field by name per scrivere i dati che sono all’interno dei tag.

process_update

La funzione custom che esegue lo “scartamento” si chiama ExtractXML (Name; Content), ed è stata originariamente creata da Andy Knasinski:

Let ( [

XML_Length = Length ( Name ) ;

Attribute_Length = Length ( Content ) ;

Get_Instance = 1 ];

Case( IsEmpty ( Name ) or IsEmpty ( Content ) or PatternCount ( Name ; "<" & Content & ">" ) = 0 ; "" ;

Middle ( Name ; Position ( Name ; "<" & Content & ">" ; 1 ; Get_Instance ) + attribute_length + 2 ;

xml_length - ( xml_length - Position ( Name ; "</" & Content & ">" ; 1 ; Get_Instance ) ) - ( Position ( Name ; "<" & Content & ">" ; 1 ; Get_Instance ) + Attribute_Length + 2 ) )

) )

Metodi avanzati di aggiornamento

Ovvero, il copiaincolla server solo ai fini del tip file.

Nel mondo reale in generale si cerca di usare metodi più affidabili, che richiedano meno interazione possibile da parte dell’utente.

Nel tip file ci sono 2 esempi:

agg_adv

Nel primo si ipotizza di aver inviato il file XML alla sede remota, e quindi di eseguire uno script che ne legge il contenuto (è richiesto il plugin Base Elements).

Nel secondo si ipotizza che la sede centrale abbia messo il contenuto del file XML in una pagina web, e che la sede remota utilizzi uno script che esegue un Insert from URL per leggerlo.

I vantaggi della tecnica Wrap-Unwrap

  • Dinamicità e scalabilità. La procedura di “incartamento” è modulare, astratta. Pertanto, può essere applicata ad ogni tabella, dal momento che legge il nome della tabelle e dei campi dal contesto in cui viene eseguita. Ne consegue che basta puntarla ad un qualsiasi layout perchè i dati presenti nel layout vengano registrati, senza bisogno di una singola riga di codice in più; allo stesso modo basta mettere o togliere campi dal layout per includerli o meno nella processazione- Anche la parte di “scartamento” è dinamica: nessun nome di tabella o di campo viene indicato esplicitamente, ma invece tutti gli script utilizzano valori presi dal testo XML
  • Portabilità. Applicare questa tecnica ad altri files è semplicissimo: basta copiare due custom funtion e 4 script.
  • Integrità transazionale. Citato per ultimo è in realtà l’aspetto più importante: la tecnica consente infatti di trasferire tutto l’aggiornamento in un singolo blocco di testo, e quindi in maniera atomica, transazionale, senza esporsi a possibili aggiornamenti parziali (come per esempio potrebbe avvenire con procedure di importazione dei dati).

incartaescarta.zip

Questo articolo è stato pubblicato nei giorni scorsi in versione inglese su FileMaker Hacks.

Qual è il tuo metodo per trasferire i dati con FileMaker? Raccontaci la tua soluzione e condividi le tue idee con gli altri Guru: scopri la comunità Filemaker su Guru Corner!

LASCIA UN COMMENTO

Please enter your comment!
Please enter your name here