Nella lista degli attributi di una classe, gli attributi derivati sono contraddistinti dal prefisso /
.
Passando il mouse su un attributo derivato, un tooltip mostra l’espressione che lo definisce. Selezionandolo, tutti gli attributi usati per definirlo sono cerchiati in rosso; viceversa, se viene selezionato un attributo coinvolto in almeno un’espressione, tutti gli attributi derivati calcolati a partire da esso sono cerchiati in blu.
Nell’esempio in figura, il valore dell’attributo /weight
sulla classe Shipping_component è calcolato moltiplicando il valore degli attributi quantity
e /unit_weight
(cerchiati in rosso); a partire da esso viene poi calcolato il valore dell’attributo /total_weight
sulla classe Shipping (cerchiato in blu), che riporta il peso totale aggregato su tutti gli oggetti Shipping_component associati a uno Shipping.
È possibile modificare l’espressione utilizzata in qualunque attributo derivato facendo click destro su di esso e scegliendo Edit expression
dal menu contestuale.
Restrizioni #
Gli attributi derivati dipendono da altri attributi presenti nel database. Per questo motivo, con essi non è possibile compiere alcune delle operazioni normalmente consentite con gli attributi nativi:
- modificare il tipo di dato;
- imporre vincoli di integrità (rendere l’attributo required);
- imporre un vincolo di unicità (
Make Unique
). - imporre restrizioni sul dominio.
Tipologie #
Livebase supporta due tipi di attributo derivato:
- Math, calcolato mediante un’espressione matematica che può contenere riferimenti ad altri attributi presenti nella stessa classe;
- Query, calcolato in base al valore di un attributo presente in una classe correlata (collegata con una relazione o un cammino di relazioni).
Attributi math #
Un attributo math è un attributo il cui valore è calcolato mediante un’espressione matematica definita attraverso il Math expression editor.
Creare un attributo math #
Fai click destro su una classe per aprire il suo Class menu
e seleziona New derived attribute
> Math
. Il Math expression editor si apre ed è possibile scrivere l’espressione matematica per calcolare l’attributo.
Il Math expression editor #
Il Math expression editor consente di definire espressioni, nelle quali è possibile referenziare il valore degli altri attributi presenti nella stessa classe.
Le icone in basso a destra consentono di inserire gli elementi dell’espressione scegliendoli direttamente da un menu a tendina. Vediamole in dettaglio:
- apre la lista degli attributi della classe per cui si sta definendo l’espressione; sono inclusi anche gli attributi derivati definiti in precedenza e gli attributi di piattaforma abilitati;
- apre la lista globale delle classi Enum e per ognuna mostra i suoi letterali; è disabilitata se nel modello sono assenti classi Enum;
- apre la lista globale delle classi Singleton e per ognuna mostra i suoi attributi; è disabilitata se nel modello sono assenti classi Singleton;
- apre la lista delle User properties, ovvero informazioni relative all’utente corrente della Cloudlet al momento in cui l’espressione è valutata. Queste corrispondono agli attributi predefiniti della classe _User (come
username
,timezone
, etc.). Nell’espressione, l’utente corrente è rappresentato dalla variabile__CurrentUser
; - apre la lista delle System properties, informazioni di sistema come data e ora correnti, che dipendono dalla configurazione della Cloudlet. Nell’espressione, il sistema è rappresentato dalla variabile
__System
; - apre una lista di costanti;
- apre una lista contenente operatori matematici e logici;
- apre il function picker.
Function Picker #
Il Function picker raccoglie un insieme di funzioni di utilità per definire espressioni, tra cui funzioni insiemistiche / matematiche o operatori su date e stringhe. Selezionando una funzione dalla lista ne viene mostrata la descrizione, che include i parametri richiesti in input con i corrispondenti tipi di dato. Cliccando su Show Examples
è possibile consultare esempi di utilizzo di ciascuna funzione.
Esempio di attributo math #
Posizionando il cursore sopra un attributo math, compare un tooltip che mostra l’espressione che lo definisce.
Nell’esempio mostrato in figura è stato selezionato l’attributo /age
, che determina l’età di un impiegato (Employee); per fare ciò, esso utilizza l’attributo nativo date_of_birth
per calcolare la differenza in anni tra la data attuale e la data di nascita dell’impiegato. Vediamo ora nel dettaglio come avviene questo calcolo.
L’espressione utilizza la funzione dateDiff(d1,d2,calendarField)
, dove d2
è il termine dell’espressione che viene sottratto a d1
:
- la data corrente (
__System.date
) è stata inserita al posto did1
, selezionandodate: date
dalle proprietà di sistema; date_of_birth
è stato inserito al posto did1
, selezionandolo dalla lista degli attributi;- poiché l’età è normalmente espressa in anni, l’espressione deve restituire come risultato un numero intero (
integer
) che esprima la differenza tra le due date in termini di anni; per fare ciò, il campocalendarField
è stato sostituito confield.year
.
Al termine dell’inserimento, il messaggio Expression has been validated as INTEGER
conferma che l’espressione utilizzata è valida.
Nota che /full_name
è anch’esso un attributo math. Questo attributo è stato creato definendo un Object title su più attributi. Maggiori informazioni su questa operazione sono disponibili nel paragrafo dedicato.
Attributi query #
Un attributo query è calcolato a partire dal valore di un attributo presente su una classe differente da quella su cui è definito e collegata con una relazione o un cammino di relazioni alla classe d’interesse. L’attributo puntato dalla query è detto attributo target, mentre il percorso di relazioni attraversate è detto Path.
Selezionando un attributo query, l’attributo target corrispondente viene evidenziato in rosso. Viceversa, selezionando un attributo coinvolto in una query, vengono cerchiati in blu tutti gli attributi definiti a partire da esso. Questo meccanismo ci consente di conoscere il cammino compiuto dalla query per raggiungere l’attributo.
Ci possono essere più percorsi che collegano la classe su cui è definita la query e la classe dell’attributo target. La raggiungibilità delle classi non dipende dalla navigabilità dei ruoli: è sufficiente che esista una relazione tra due classi affinché essa sia percorribile in entrambi i versi.
Posizionando il cursore sopra un attributo query, compare un tooltip che mostra l’espressione che lo definisce, come mostra la seguente figura:
Nell’esempio, invece di persistere l’informazione relativa alla città di residenza di un impiegato (Employee) utilizzando un attributo nativo, si è scelto di modellare le città in maniera indipendente, come oggetti della classe City. Per associare un impiegato a una città è dunque possibile utilizzare l’attributo derivato /city
, che ha come target l’attributo name
presente nella classe City.
Creare un attributo query #
Fai click destro su una classe per aprire il suo Class menu
e seleziona New derived attribute
> Query
.
In alternativa, seleziona l’attributo target, trascinalo e rilascialo sulla classe dove vuoi creare la query e seleziona Link here
dal menu contestuale.
Il Designer sceglie il nome di default di una query in questo modo:
- se il ruolo ha cardinalità a uno, il nome di default è nomeRuolo_nomeAttributo;
- se il ruolo ha cardinalità a molti, il nome di default include in testa la funzione di aggregazione usata;
- in entrambi i casi, se l’attributo source è l’unico attributo di quella classe, nomeAttributo viene omesso.
Il Query expression editor #
Sotto la sezione Path è presente una lista di tutti gli attributi raggiungibili dalla classe di partenza navigando i suoi ruoli . Da qui è possibile selezionare l’attributo target della query espandendone il percorso. Gli attributi della classe di partenza non sono selezionabili.
Ciascun tipo di attributo è raffigurato con un’icona diversa: attributi nativi: , attributi math: , attributi query: .
Il path selezionato dalla query è riportato anche in forma testuale (es. city_.name
). Questa stringa può essere editata per modificare manualmente il path della query.
Query su valori multipli #
Una query il cui percorso attraversa almeno un ruolo a molti recupererà valori multipli per l’attributo puntato, uno per ogni oggetto della classe interessato dalla relazione; è dunque necessario definire in che modo aggregare questo insieme di valori per rappresentarli in un unico attributo (ad es. concatenando i valori, sommandoli, selezionando il valore massimo, etc.). A seconda del tipo di dato dell’attributo puntato, la tendina Aggregation function
presenta diverse opzioni; nella tabella sono riportati tutte le funzioni disponibili:
Funzione | Significato |
---|---|
Count all | L’attributo contiene il conteggio dei record trovati. |
Count distinct | Come sopra, ma non include record con valori duplicati. |
Concat (comma separated) | L’attributo è una stringa contenente tutti i valori dei record trovati, separati tra loro da virgole. |
Concat distinct (comma separated) | Come sopra, ma non include record con valori duplicati. |
Max / Min | Restituisce il valore massimo/minimo tra i record trovati. |
Se la sorgente è un attributo numerico sono disponibili ulteriori operatori:
Funzione | Significato |
---|---|
Sum | Restituisce la somma dei valori dei record trovati. |
Average | Restituisce il valore medio tra quelli dei record trovati. |
Standard deviation | Restituisce la deviazione standard tra i valori dei record trovati. |
Per attributi booleani abbiamo inoltre:
Funzione | Significato |
---|---|
Logical AND | Restituisce TRUE se tutti i record sono veri, FALSE altrimenti |
Logical OR | Restituisce TRUE se almeno un record è vero, FALSE altrimenti |
Query con condizioni di filtraggio #
È possibile filtrare i record trovati dalla query in modo analogo a quanto avviene in una clausola WHERE
SQL, definendo una condizione di filtraggio (filtering condition) mediante un’espressione; ciò è utile soprattutto quando la query recupera valori multipli.
Cliccando sul pulsante Add filter
del Query expression editor si apre un editor sostanzialmente identico al Math expression editor, con una importante differenza: l’espressione di una filtering condition deve sempre restituire un valore booleano (TRUE
oppure FALSE
). Se l’espressione è corretta, l’editor mostra il messaggio Expression has been validated as BOOLEAN
e consente di confermare l’inserimento.
Quando l’espressione utilizza direttamente un solo attributo booleano, il risultato dipenderà semplicemente dal valore assunto da tale attributo; in casi del genere è possibile evitare di scrivere <AttributeName> = true
e usare direttamente <AttributeName>
.
Esempio di attributo query #
Nel seguente esempio vogliamo determinare quanti progetti (Project) sono stati portati a termine da un impiegato (Employee).
L’attributo completed
su Project rappresenta lo stato del progetto: il valore TRUE
equivale a dire che è stato completato.
La query /completed_projects
nella classe Employee punta verso l’attributo name
di Project. L’associazione ha cardinalità a molti (un impiegato può essere assegnato a più progetti) quindi occorre aggregare i dati con un operatore per poterli rappresentare con un unico attributo. Dal Query expression editor è stata dunque selezionata come Aggregation function l’opzione COUNT_DISTINCT
. In questo modo è stato ottenuto il conteggio di tutti i progetti assegnati a un impiegato.
Per completare la definizione della query è necessario escludere dal conteggio tutti i progetti non ancora completati (per i quali l’attributo completed
ha dunque valore FALSE
). Per fare ciò, abbiamo impostato la condizione Project.completed=true
.