## FAQ: validazione dei dati immessi dall'utente

In questa sezione sono riportate le domande più frequenti emerse durante l' utilizzo di guigen relative alla validazione dei dati immessi da utente.

Q: Ho letto che esiste la possibilità di modellare i constraint di validazione dei dati immessi mediante gli attributi datatypeModifier e required presenti sia nella classe Widget che nella classe Field: qual'è la differenza?

A: gli attributi datatypeModifier e required presenti sul Widget vanno utilizzati quando:

- il widget non ha binding (binding implicito - utilizzo sconsigliato)
- il widget ha un binding con un application data che non sia di tipo ComplexType

E' invece necessario utilizzare le impostazioni sul Field quando il widget ha un binding con un campo di un ApplicationData di tipo ComplexType

Q: qual'è la sintassi da utilizzare per indicare i constraints di validazione che devono essere inseriti nell'attributo datatypeModifier?

A: Riportiamo qui di seguito un estratto sintetico delle impostazioni possibili.

Tutti i controlli modellabili mediante l'attributo dataTypeModifier del widget devono avere formato

`<validatore>:<regole>`.

L'elemento <validatore> è obbligatorio; in caso di assenza non verrà generata nessuna annotazione. L'elemento <regole> può essere obbligatorio o opzionale a seconda del tipo di validatore. Nel caso di regole opzionali, è indifferente la presenza o meno del segno due punti (:) che verrà comunque ignorato.

E' compito di chi utilizza lo strumento di modellazione assicurarsi che la sintassi del controllo modellato rispetti quella indicata per ciascun validatore. Il generatore effettua una serie limitata di controlli formali per ciascun tipo di validatore. In particolare:

- il generatore controlla che il tipo di validatore modellato sia ammesso per il tipo di dato definito: in caso contrario non genera nessuna annotazione;
- nel caso siano ammessi dei parametri con una sintassi particolare (ad esempio range o size) il generatore cerca di decodificare i parametri secondo le regole specificate; nel caso la regola o il tipo di dato non sia riconosciuto, il parametro verrà ignorato.

Di seguito sono elencati i validatori utilizzabili per i vari tipi di dato.

#### STRINGA

##### size validator

Controlla che la lunghezza di una stringa sia compresa tra un minimo e un massimo numero di caratteri specificati.

sintassi:

`size:<minsize>,<maxsize>`

I due parametri sono mutualmente opzionali (ovvero uno dei due è obbligatorio) e la semantica è da intendersi in senso inclusivo.

Esempi:

- `size:3,10`: lunghezza ammessa da 3 a 10 inclusi
- `size:,10`: lunghezza ammessa da 0 a 10 inclusi
- `size:3,`: lunghezza ammessa superiore o uguale a 3

##### regexp validator

Controlla che l'aderenza della stringa all'espressione regolare specificata.

sintassi:

`regexp:<espressione_regolare>`

#### NUMERICO

##### range

Controlla che il valore numerico sia compreso in un range specificato.

sintassi:

`range:<min>,<max>`

I due parametri sono mutualmente opzionali (ovvero uno dei due è obbligatorio) e la semantica è da intendersi in senso inclusivo.

Esempi:

- `range:30,1000`: il valore deve essere compreso tra 30 e 1000 estremi inclusi
- `size:,1000`: il valore deve essere minore o uguale a 1000
- `size:3,`: il valore deve essere maggiore o uguale a 3

#### tipi DATA/ORA (DATE, DATETIME, HOUR)

Per il tipo DATE esiste un validatore di default attivato senza necessità di specificare nulla (valida le date nel formato dd/MM/yyyy).

##### short

sintassi:

`short`

Il formato verificato è:

- `hh:mm` (HOUR)
- `dd/MM/yyyy-hh:mm` (DATETIME)

##### extended

sintassi:

`extended`

Il formato verificato è:

- `hh:mm:ss` (HOUR)
- `dd/MM/yyyy-hh:mm:ss` (DATETIME)

##### format

sintassi:

`format:<pattern>`

viene verificata l'aderenza al formato specificato. Il formato può essere:

- un pattern compatibile con i formatter di date java
- la stringa `gg/mm/aaaa` (solo per il tipo DATE) che permette di effettuare una validazione più precisa (non solo sintattica) della data

#### tutti i tipi di dato

##### custom

sintassi:

`custom:<classe java del validatore>`

Per tutti i tipi di dato è possibile specificare un custom validator che deve essere implementato secondo le specifiche di struts2.

Q: vi sono delle limitazioni nell'uso dichiarativo dei meccanismi di validazione?

A: Si. Allo stato attuale sono presenti le seguenti limitazioni:

- Non è possibile modellare un vincolo di obbligatorietà su un Widget contenuto in uno dei tab di un TabSetPanel, in uno step di un WizardPanel o in un item di un MultiPanel
- Non è possibile modellare un vincolo di obbligatorietà in un Widget soggetto a diventare invisibile, indipendentemente dal meccanismo che viene utilizzato per renderlo invisibile (VisibilityCommand, ScreenState, SecurityConstraint)

E' necessario pertanto implementare la validazione di obbligatorietà nella business logic.

Nota: la limitazione è legata alla tecnologia struts2: poichè le validazioni modellate si traducono in annotazioni java sugli oggetti dello strato model; in assenza del campo di input nella pagina html renderizzata (evenienza che accade in tutte le casistiche sopracitate) il browser non passa nessuna informazione di valori nella richiesta http e questo ingenererebbe un errore di campo obbligatorio mancante.

Q: come è possibile visualizzare a video gli eventuali errori di validazione?

A: Gli errori di validazione riferiti ai campi sono visualizzabili in due modalità

1. Nell'apposito pannello StdMessagePanel, dove vengono visualizzati tutti gli errori derivanti dall'ultima azione
2. Sulla label del widget che ha causato l'errore (mediante un tooltip se è attivata la modalità ricca)

Q: sto eseguendo logica di validazione all'interno della logica applicativa. Come posso restituire all'utente un feedback sugli eventuali errori, associandoli ai widget che hanno manifestato l'errore?

A: Nella logica applicativa è possibile inserire gli errori rilevati durante il processo di validazione programmatica nell'oggetto `ExecResults`.

In particolare per inserire un messaggio di errore non riferito ad un singolo campo è necessario utilizzare una istruzione simile alla seguente:

`results.getGlobalErrors().add("messaggio di errore");`

Per inserire invece un messaggio di errore relativo ad un determinato campo è necessario utilizzare il seguente codice:

`String chiave = APPDATA_XXXXX+"."+"nomecampo"; String messaggio = "Il campo non e' corretto"; results.getFieldErrors().put(chiave, messaggio);`

Dove:

- messaggio è una stringa che contiene il messaggio da visualizzare
- chiave è una stringa che identifica il campo a cui si riferisce il messaggio. La valorizzazione di questo attributo può essere individuata:
  - empiricamente: occorre cercare nella pagina JSP relativa alla schermata il frammento di codice relativo al widget - il campo labelFor rappresenta il valore di riferimento
  - componendo la stirnga a partire dalle informazioni modellate:
    - se il widget non ha un ApplicationDataBinding allora la stringa vale "widg_<name_del_widget>"
    - se il widget ha un ApplicationDataBinding allora la stringa deve essere costruita componendo il codice dell'application data (vedere costanti che iniziano per "APPDATA" all'interno della classe di business logic) e il path modellato sul binding

Q: e' possibile fare in modo che, per qualche specifico evento, non venga eseguita la validazione?

A: Si, è sufficiente impostare a true il valore dell'attributo skipValidation sull'EventHandler per cui non si vuole far eseguire la validazione

Q: ho modellato un constraint di validazione su un Field di un ComplexType: è possibile fare in modo che tali vincoli agiscano solo quando il campo è collegato ad un certo widget e non agiscano se collegato ad un altro widget?

A: No non è possibile. Per avere il comportamento richiesto è necessario modellare due differenti strutture dato.