UNIVERSITÀ POLITECNICA DELLE MARCHE FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica e dell’Automazione PROGETTO E SVILUPPO DI UN SOFTWARE IN “JAVA” PER LA TELEREFERTAZIONE: SEZIONE DOTTORE Laureando: Luca Torelli Relatore: Prof. Aldo Franco Dragoni Correlatore: Prof. Paolo Puliti Anno accademico 2007/2008 Indice Indice ................................................................................................................................... I Elenco delle figure ........................................................................................................... III Elenco dei listati ................................................................................................................ V Elenco delle tabelle ........................................................................................................... V Capitolo 1: I software utilizzati .................................................................................... 1 1.1 JAVA .................................................................................................................. 2 1.1.1 Il linguaggio Java ................................................................................... 4 1.1.2 La piattaforma Java ................................................................................ 9 1.2 GWT (Google Web Toolkit) .............................................................................. 12 1.2.1 Le estensioni GWT ................................................................................. 20 1.3 RPC (Remote Procedure Call) ........................................................................... 21 1.4 ALTRI SOFTWARE ......................................................................................... 23 1.4.1 Eclipse .................................................................................................... 23 1.4.2 Tomcat .................................................................................................... 24 1.4.3 MySQL ................................................................................................... 25 Capitolo 2: I portali per la telemedicina ....................................................................... 27 2.1 IL CONCETTO “TELEMEDICINA” .............................................................. 28 2.1.1 Obiettivi della telemedicina .................................................................... 29 2.2 “MIRO ON RAILS”: RUBY ON RAILS .......................................................... 31 2.3 “MIRO ON RAILS”: IL PORTALE ................................................................. 32 2.3.1 Aspetti corretti del portale ...................................................................... 32 2.4 “MIRO ON RAILS”: ORGANIZZAZIONE DATABASE .............................. 41 Capitolo 3: Il portale “MedTel”: sezione dottore ......................................................... 44 3.1 INTRODUZIONE .............................................................................................. 45 3.2 LOGIN E REGISTRAZIONE ........................................................................... 46 3.2.1 Effettuazione del login ........................................................................... 47 3.3 AREA RISERVATA DEL DOTTORE ............................................................. 50 3.3.1 Pannello “HOME” .................................................................................. 51 3.3.2 Pannello “CLINICAL PROBLEMS” ..................................................... 51 3.3.3 Toolbar menù ......................................................................................... ~I~ 58 3.4 CARTELLA CLINICA DEL PAZIENTE ......................................................... 63 3.4.1 Aspetti generali ....................................................................................... 65 3.4.2 Profilo paziente ....................................................................................... 66 3.4.3 Anamnesi ................................................................................................ 66 3.4.4 Problemi clinici del paziente .................................................................. 67 Capitolo 4: Conclusioni ................................................................................................ 83 4.1 ASPETTI GENERALI ....................................................................................... 84 4.2 CONSIDERAZIONI SUL GWT ....................................................................... 85 4.3 CONSIDERAZIONI SUL PORTALE .............................................................. 87 4.4 CONSIDERAZIONI SUL TIROCINIO ............................................................ 89 BIBLIOGRAFIA ............................................................................................................ 91 ~ II ~ Elenco delle figure Figura 1.1: Logo Java ..................................................................................................... 2 Figura 1.2: Mappa delle eccezioni .................................................................................. 9 Figura 1.3: Logo GWT ................................................................................................... 12 Figura 1.4: Logo GWT-Ext ............................................................................................ 20 Figura 1.5: Logo Eclipse ................................................................................................ 23 Figura 1.6: Logo Tomcat ................................................................................................ 24 Figura 1.7: Logo MySQL ............................................................................................... 25 Figura 2.1: Delocalizzazione del servizio telematico ..................................................... 28 Figura 2.2: Logo Ruby On Rails .................................................................................... 31 Figura 2.3: Portale “Miro On Rails” ............................................................................... 32 Figura 2.4: Portale “Miro On Rails”: area amministrazione .......................................... 33 Figura 2.5: Portale “MedTel”: area amministrazione (1° e 2° livello) ........................... 33 Figura 2.6: Portale “Miro On Rails”: vista cartella clinica (dottore) ............................. 34 Figura 2.7: Portale “MedTel”: vista cartella clinica ....................................................... 35 Figura 2.8: Portale “Miro On Rails”: esito dell’utilizzo della libreria API .................... 35 Figura 2.9: Portale “Miro On Rails”: esito ricerca paziente positivo ............................. 36 Figura 2.10: Portale “Miro On Rails”: esito ricerca paziente negativo .......................... 36 Figura 2.11: Portale “MedTel”: inserimento nuovo utente ............................................ 37 Figura 2.12: Portale “Miro On Rails”: visualizzazione referti e messaggi dei problemi clinici .............................................................................................................................. 37 Figura 2.13: Portale “MedTel”: visualizzazione problemi clinici .................................. 38 Figura 2.14: Portale “Miro On Rails”: inserimento referti e messaggi .......................... 39 Figura 2.15: Portale “Miro On Rails”: cartella clinica ................................................... 39 Figura 2.16: Portale “MedTel”: menù con albero asincrono .......................................... 40 Figura 3.1: Pagina di Login ............................................................................................ 46 Figura 3.2: Segnalazione dati mancanti nella pagina di Login ...................................... 49 Figura 3.3: Segnalazione dati errati durante il login ...................................................... 49 Figura 3.4: Area riservata del dottore ............................................................................. 50 Figura 3.5: Pannello “Home” ......................................................................................... 51 Figura 3.6: Pannello “Clinical Problems” ...................................................................... 51 Figura 3.7: Proprietà della tabella .................................................................................. 52 ~ III ~ Figura 3.8: Toolbar menù ............................................................................................... 58 Figura 3.9: Cartella clinica del paziente (vista dal dottore) ............................................ 63 Figura 3.10: Struttura del menù organizzato ad albero .................................................. 65 Figura 3.11: Pannello “Patient Profile” .......................................................................... 66 Figura 3.12: Pannello “Patient Clinical Problems” ........................................................ 67 Figura 3.13: Finestra aperta cliccando sul bottone “New Message” .............................. 71 Figura 3.14: Finestra aperta cliccando sul bottone “Add Report” .................................. 72 Figura 3.15: Finestra aperta cliccando sul bottone “View Messages” ........................... 74 Figura 3.16: Finestra aperta cliccando sul bottone “View Reports” .............................. 75 Figura 3.17: Finestra aperta cliccando sul bottone “View Details Clinical Problem” ... 77 ~ IV ~ Elenco dei listati Listato 1.1: Pagina Host del progetto “MedTel” ............................................................ 13 Listato 1.2: Modulo del “MedTel” ................................................................................. 16 Listato 3.1: Metodo per il login, lato server (LoginRMImpl.java) ................................ 47 Listato 3.2: Codice per aprire la tabella dei problemi clinici nella cartella clinica, lato client (EventsPatients.java) ............................................................................................ 52 Listato 3.3: Codice per aggiornare il pannello “Clinical Problems”, lato client (ClinicalFolder.java) ....................................................................................................... 54 Listato 3.4: Metodo per caricare la tabella, lato server (EventsPatientRSImpl.java) ..... 55 Listato 3.5: Metodo per caricare i dati, lato server (ModRegistrationRSImpl.java) ...... 58 Listato 3.6: Metodo che salva le modifiche, lato server (ModRegistrationRSImpl.java) ...................................................................................... 60 Listato 3.7: Metodo per effettuare il log-out, lato server (UserAreaRSImpl.java) ........ 61 Listato 3.8: Metodo per caricare dati nel menù a tendina, lato server (UserAreaRSImpl.java) .................................................................................................. 62 Listato 3.9: Codici per costruire la cartella clinica, lato client (ClinicalFolder.java) .... 64 Listato 3.10: Codice per aprire il pannello con la riga pre-selezionata, lato client (ViewVisitsEvent.java) .................................................................................................. 68 Listato 3.11: Metodo per salvare nuovi report o messaggi, lato server (Message_ReportRSImpl.java) ...................................................................................... 73 Listato 3.12: Metodo per salvare vedere report o messaggi, lato server (View_msg_reportRSImpl.java) .................................................................................... Listato 3.13: Metodo per caricare dati nel pannello, lato server (DetailsVisitRSImpl.java) .............................................................................................. Listato 3.14: Metodo per caricare dati di un esame, lato 3.15: Metodo per caricare la lista dei file, lato 78 server (DetailsVisitRSImpl.java) .............................................................................................. Listato 76 80 server (DetailsVisitRSImpl.java) .............................................................................................. 81 Elenco delle tabelle Tabella 2.1: Elenco tabelle del database del “MiroOnRails”................................................... 41 ~V~ Capitolo 1: I software utilizzati CAPITOLO 1: I software utilizzati • quali sono • cosa sono • strutture del software impiegate Pagina 1 Capitolo 1: I software utilizzati 1.1 JAVA Figura 1.1: Logo Java Java è un linguaggio di programmazione, inizialmente chiamato Oak orientato agli oggetti, derivato dal C++ (e quindi indirettamente dal C) e creato da James Gosling e altri ingegneri di Sun Microsystems. Il gruppo iniziò a lavorare nel 1991 ma il nome fu successivamente cambiato in Java a causa di un problema di copyright (il linguaggio di programmazione Oak esisteva già nel 1991). Java fu annunciato ufficialmente il 23 maggio 1995 a SunWorld. La piattaforma di programmazione Java è fondata sul linguaggio stesso, sulla Java Virtual Machine (JVM) e sulle API. Java è un marchio registrato di Sun Microsystems. Il 13 novembre 2006 la Sun Microsystems ha rilasciato la sua implementazione del compilatore Java e della macchina virtuale sotto licenza GPL. L'8 maggio 2007 SUN ha rilasciato anche le librerie (tranne alcune componenti non di sua proprietà) sotto licenza GPL rendendo Java un linguaggio di programmazione la cui implementazione di riferimento è libera. Java fu creato per soddisfare quattro scopi: 1. essere orientato agli oggetti. 2. essere indipendente dalla piattaforma. 3. contenere strumenti e librerie per il networking. 4. essere progettato per eseguire codice da sorgenti remote in modo sicuro. Per facilitare il passaggio a questo linguaggio per i programmatori old-fashioned, legati in particolare a linguaggi come il C, la sintassi di base (strutture di controllo, operatori e così via) è stata mantenuta pressoché identica. Nel complesso, Java è sia un linguaggio di programmazione sia una piattaforma. Quando ci si riferisce a Java come piattaforma, bisogna pensare a due aspetti interconnessi tra loro: l’architettura di ciò che ha cambiato il modo di intendere il software come si è fatto per anni, e come poi tale idea sia stata riutilizzata e abbia aperto la strada al nuovo millennio anche per quanto riguarda la produzione di software. Pagina 2 Capitolo 1: I software utilizzati La piattaforma Java fu uno dei primi sistemi a fornire un largo supporto per l'esecuzione del codice da sorgenti remote. Un applet Java è un particolare tipo di applicazione che può essere avviata all'interno del browser dell'utente, eseguendo codice scaricato da un server web remoto. Questo codice viene eseguito in un'area (sandbox) altamente ristretta, che protegge l'utente dalla possibilità che il codice sia malevolo o abbia un comportamento non desiderato; chi pubblica il codice può applicare un certificato che usa per firmare digitalmente le applet dichiarandole "sicure", dando loro il permesso di uscire dall'area ristretta e accedere al file system e al network, presumibilmente con l'approvazione e sotto il controllo dell'utente. In realtà gli applet non hanno avuto molta fortuna. Infatti, presuppone che il client in cui essi vengono eseguiti abbia installata la JRE (deve eseguire il codice dell'applet). Hanno avuto fortuna le applicazioni che prevedono il cosiddetto thinclient, cioè un client "leggero" che non ha bisogno di particolari strumenti per eseguire il codice remoto (a volte è necessario solo il browser). Rispetto alla tradizione dei linguaggi a oggetti da cui deriva (e in particolare rispetto al suo diretto progenitore, il C++), Java ha introdotto una serie di notevoli novità rispetto all'estensione della sua semantica. Fra le più significative si possono citare probabilmente la possibilità di costruire GUI (interfacce grafiche) con strumenti standard e non proprietari utilizzando i package java.awt e javax.swing (per il C++ e altri linguaggi analoghi solitamente le GUI non fanno parte del linguaggio, ma sono delegate a librerie esterne), la possibilità di creare applicazioni multi-thread, ovvero che svolgono in modo concorrente molteplici attività, e il supporto per la riflessione, ovvero la capacità di un programma di agire sulla propria struttura e di utilizzare classi caricate dinamicamente dall'esterno. Fra gli argomenti che depongono spesso a favore di Java nella scelta del linguaggio di implementazione di un progetto software moderno, inoltre, si deve certamente contare la vastità delle librerie standard di cui il linguaggio è dotato, e che in particolare contribuiscono a renderlo altamente integrabile con le altre tecnologie. Alcuni esempi di funzionalità di libreria di Java sono: • accesso ai database tramite JDBC (Java Database Connectivity) e ai DBMS con driver ODBC (Open Database Connectivity) tramite il bridge JDBC-ODBC. • manipolazione documenti XML. • dialogo con piattaforme CORBA (Common Object Request Broker Architecture). • potenti strumenti per la programmazione lato server nel contesto Web. Pagina 3 Capitolo 1: I software utilizzati • supporto nativo per gran parte dei protocolli della famiglia IP, vedi ad esempio il Socket Java. • supporto per le applicazioni multimediali, streaming audio e video. 1.1.1 IL LINGUAGGIO JAVA Java è un linguaggio di alto livello con innumerevoli qualità: • semplice: può essere programmato senza la necessità di lunghi corsi di addestramento, i concetti fondamentali della tecnologia Java vengono appresi rapidamente così che i programmatori possano essere produttivi sin dall’inizio. • Object Oriented: il linguaggio è progettato per essere orientato agli oggetti da cima a fondo. Non è possibile in Java adottare stili di programmazione che non siano quelli OO (object oriented). Gli oggetti sono caratterizzati da delle proprietà (definite variabili o campi di istanza o di esemplare) e di metodi applicabili sugli oggetti stessi, che possono ad esempio modificarne lo stato o estrarne informazioni. I programmi scritti in Java possono essere unicamente orientati agli oggetti, di conseguenza tutto il codice deve essere necessariamente incluso in una classe. Sebbene Java possa operare sia su oggetti che su tipi di dati primitivi, è considerato un linguaggio ad oggetti puro, ovvero nel quale gli oggetti sono le entità di base del linguaggio, anziché essere costruiti partendo da costrutti ad un inferiore livello di astrazione. • familiare: la sintassi Java è molto simile a quella del C++ e questo lo rende un linguaggio familiare, questo significa che i programmatori C++ possono migrare facilmente al linguaggio Java ed essere produttivi rapidamente. • robusto e sicuro: il linguaggio è progettato per creare software altamente affidabile: fornisce un esaustivo controllo a tempo di compilazione seguito da un secondo livello di controlli a tempo d’esecuzione. Il modello della gestione della memoria è estremamente semplice ed è progettato per operare in ambienti distribuiti in quanto la sicurezza viene messa in risalto come caratteristica di rilievo. • indipendente dalla piattaforma e portabile: il linguaggio è progettato per supportare applicazioni che verranno distribuite sulle più eterogenee piattaforme senza la necessità di dover riscrivere il programma per i vari ambienti (l'esecuzione di programmi scritti in Java deve avere un comportamento simile su hardware diverso). Si dovrebbe essere in grado di scrivere il programma una volta e farlo Pagina 4 Capitolo 1: I software utilizzati eseguire dovunque. Questo è possibile con la compilazione del codice di Java in un linguaggio intermedio bytecode, basato su istruzioni semplificate che ricalcano il linguaggio macchina. Il bytecode verrà quindi eseguito da una macchina virtuale. Inoltre, vengono fornite librerie standardizzate per permettere l'accesso alle caratteristiche della macchina (come grafica e networking) in modo unificato. Il linguaggio Java include anche il supporto per i programmi con multithread, necessario per molte applicazioni che usano la rete. Si illustrano ora le fasi che attraversa un programma Java per essere portabile e indipendente dalla piattaforma: 1. il programma viene prima scritto nel linguaggio di programmazione Java (nome_file.java); 2. la compilazione fornisce come output un file (nome_file.class) che non è ancora il file eseguibile come avviene negli altri linguaggi di programmazione, questo perché il file in uscita dal compilatore è il bytecode del programma. 3. è il bytecode la vera innovazione e ciò che permette l’indipendenza dalla piattaforma in quanto è lo stesso per ogni macchina. L’esecuzione vera e propria avviene interpretando il bytecode. Questa operazione viene fatta dall’interprete: da bytecode a codice macchina e quindi eseguito. Introducendo questo passaggio in più è possibile mandare in esecuzione lo stesso programma su qualsiasi macchina, l’unica cosa da cambiare è l’interprete per quella specifica macchina. Le prime implementazioni del linguaggio usavano una virtual machine che interpretava il bytecode per ottenere la massima portabilità, definita Architecture Neutral. Questa soluzione si è però rivelata poco efficiente, in quanto i programmi interpretati erano molto lenti. Per questo, tutte le implementazioni recenti di macchine virtuali Java hanno incorporato un JIT compiler, cioè un compilatore interno, che al momento del lancio traduce al volo il programma bytecode Java in un normale programma nel linguaggio macchina del computer ospite. Inoltre, questa ricompilazione è dinamica, cioè la virtual machine analizza costantemente il modello di esecuzione del codice (profiling), e ottimizza ulteriormente le parti più frequentemente eseguite, mentre il programma è in esecuzione. Questi accorgimenti, a prezzo di una piccola attesa in fase di lancio del programma, permettono di avere delle applicazioni Java decisamente più veloci e leggere. Tuttavia, Pagina 5 Capitolo 1: I software utilizzati anche così Java resta un linguaggio meno efficiente dei linguaggi compilati come il C++, scontando il fatto di possedere degli strati di astrazione in più, e di implementare una serie di automatismi, come il garbage collector, che se da un lato fanno risparmiare tempo ed errori in fase di sviluppo dei programmi, dall'altro consumano memoria e tempo di CPU in fase di esecuzione del programma finito. COMPONENTI Ci sono varie componenti che caratterizzano il linguaggio Java: • OGGETTO: è un’entità software dotata di uno stato e di un insieme di metodi che permettono all’utente di interagire con esso. Lo stato di un oggetto è l’insieme dei valori degli attributi. E’ una variabile di istanza il cui tipo è definito dall’utente (la classe). • CLASSE: può essere concreta o astratta e ognuna definisce un tipo di dato. E’ anche chiamata “tipo definito dall’utente/programmatore”. In ogni classe sono presenti dei dati (chiamate “variabili di istanza”) e dei metodi, il cui ruolo è quello di manipolare tali dati. La classe viene utilizzata per istanziare gli oggetti che operano insieme per implementare il sistema. • INTERFACCIA: contiene un gruppo di metodi public abstract ma anche dati public final static. L'utilizzo di una interfaccia in Java consente di trattare in modo omogeneo tutti gli oggetti che forniscono un dato insieme di servizi, a prescindere dalla loro implementazione (e quindi dalla loro particolare classe di appartenenza). Dal punto di vista sintattico, una interfaccia Java consiste principalmente di una lista di dichiarazioni di metodi che tutte le classi che implementano l'interfaccia devono fornire. Un’interfaccia è tipicamente utilizzata al posto di una classe abstract quando non c’è alcuna implementazione di default da ereditare (ovvero nessuna variabile d’istanza e nessun metodo di default). Per usare un’interfaccia una classe deve specificare che la implementa, mediante la parola “implements”, e deve definire ogni metodo dell’interfaccia con il numero di argomenti e il tipo di ritorno specificati nella definizione dell’interfaccia. Se la classe lascia un metodo dell’interfaccia non definito, diventa una classe abstract e deve essere dichiarata abstract nella prima riga della sua definizione. Lasciando un metodo dell’interfaccia non definito in una classe che la implementa, in fase di compilazione un errore comunica che la classe deve essere dichiarata abstract. Pagina 6 Capitolo 1: I software utilizzati Legato al concetto di classe e interfaccia c’è quello dell’ereditarietà: questa è definita come la caratteristica per la quale un oggetto di classe B (detta classe derivata) che deriva da A (detta classe madre) possiede tutte le caratteristiche della classe madre. Ciò significa affermare che l’oggetto B è anche un (is a) oggetto di tipo A. Una cosa importante da tenere in considerazione è che in Java una classe può ereditare al massimo da una sola classe, mediante il termine “extends”; in altri linguaggi, come il C++, questa “limitazione” non esiste. Per arginare questo problema, in Java è stato introdotto il concetto di interfaccia. Attraverso l’utilizzo delle interfacce una classe può assumere diversi comportamenti: ciò che accade, in buona sostanza, con l’ereditarietà multipla. Ecco, quindi, che una classe, assumendo i comportamenti di più interfacce, può essere vista come una particolare istanza di quelle interfacce. Tutte le classi Java hanno come classe madre (chiamata anche superclasse) all’origine la classe “Object”. Questo significa che automaticamente quando scriviamo una classe essa deriva (senza doverlo specificare) da “Object”. Con questo espediente è possibile, quindi, parlare genericamente di un qualsiasi “Object” per riferirsi ad un oggetto di classe qualunque. Legata all’ereditarietà ci sono due importanti caratteristiche del Java, l’overloading e l’overriding: il primo significa, in generale, dotare una classe di metodi aventi stesso nome ma con parametri differenti mentre il secondo significa semplicemente riscrivere il metodo coinvolto all’interno della classe derivata, evitando di manomettere la classe base (interviene in questo caso il concetto di “polimorfismo”, ovvero l'attitudine di un oggetto a mostrare più implementazioni per una singola funzionalità). ECCEZIONI E’ possibile definire un’eccezione come un situazione imprevista che il flusso di un’applicazione può incontrare. È possibile gestire un’eccezione in Java, imparando ad utilizzare cinque semplici parole chiave: try, catch, finally, throw e throws. Sarà anche possibile creare eccezioni personalizzate e decidere non solo come, ma anche in quale parte del codice gestirle, grazie ad un meccanismo di propagazione estremamente potente. Questo concetto è implementato nella libreria Java mediante la classe “Exception” e le sue sottoclassi. Un esempio di eccezione che potrebbe verificarsi all’interno di un programma è quella relativo ad un divisione tra due variabili numeriche nella quale la variabile divisore ha valore 0. Come è noto infatti, tale operazione non è fattibile. È invece possibile definire un errore come una situazione imprevista non dipendente da un errore commesso dallo sviluppatore. A differenza delle eccezioni quindi, gli errori non Pagina 7 Capitolo 1: I software utilizzati sono gestibili. Questo concetto è implementato nella libreria Java mediante la classe “Error” e le sue sottoclassi. Un esempio di errore che potrebbe causare un programma è quello relativo alla terminazione delle risorse di memoria. Ovviamente, questa condizione non è gestibile. Nella libreria standard di Java, esiste una gerarchia di classi che mette in relazione, la classe “Exception” e la classe “Error”. Infatti, entrambe queste classi estendono la superclasse “Throwable”. Un’ulteriore categorizzazione delle eccezioni, è data dalla divisione delle eccezioni in checked ed unchecked exception. Ci si riferisce alle RuntimeException (e le sue sottoclassi) come unchecked exception. Tutte le altre eccezioni (ovvero tutte quelle che non derivano da RuntimeException), vengono dette checked exception. Se si utilizza un metodo che lancia una checked exception senza gestirla da qualche parte, la compilazione non andrà a buon fine. Da qui il termine checked exception (in italiano “eccezioni verificate”). Non bisogna fare confusione tra il concetto di errore (problema che un programma non può risolvere) e di eccezione (problema non critico gestibile): il fatto che sia la classe “Exception” sia la classe “Error”, estendano una classe che si chiama “lanciabile” (Throwable), è dovuto al meccanismo con cui la Java Virtual Machine reagisce quando si imbatte in una eccezione-errore. Infatti, se il nostro programma genera un’eccezione durante il runtime, la JVM istanzia un oggetto dalla classe eccezione relativa al problema, e “lancia” l’eccezione appena istanziata (tramite la parola chiave throw). Se il nostro codice non “cattura” (tramite la parola chiave catch) l’eccezione, il gestore automatico della JVM interromperà il programma generando in output informazioni dettagliate su ciò che è accaduto. Pagina 8 Capitolo 1: I software utilizzati Figura 1.2: Mappa delle Eccezioni 1.1.2 LA PIATTAFORMA JAVA La piattaforma Java è una piattaforma solo software che gira in cima ad una piattaforma hardware di base che può essere un computer, una tv, un telefono cellulare, una smart card, ecc.. La piattaforma Java è composta da due blocchi: la Java Virtual Machine (JVM) e la Java Application Program Interface (API). La JVM è la base della piattaforma Java, mentre la Java API è una collezione di componenti software pronti all’uso per lo svolgimento dei più disparati compiti. JAVA VIRTUAL MACHINE La JVM consiste di: • class loader. • un class verifier. • l’interprete Java. Il “class loader” carica il bytecode, sia dal programma Java (nome_file.class) che dalla Java API (a seconda degli import fatti nel programma), per l’esecuzione da parte dell’interprete Java. Subito dopo che la classe è caricata il “class verifier” controlla che il class file è un formato bytecode valido, che non superi i limiti superiori o inferiori dello stack; assicura Pagina 9 Capitolo 1: I software utilizzati che il bytecode non esegue aritmetica dei puntatori il che potrebbe potenzialmente portare ad una violazione di memoria. Se il class passa tutti questi controlli può essere eseguito dall’interprete. L’interprete può essere di varie forme: può essere un modulo software che interpreta il bytecode in una solo volta; potrebbe essere un compilatore JIT (Just In Time) che traduce il bytecode in codice nativo della macchina ospitante. L’uso di un compilatore JIT aumenta le performance quasi al pari di una compilazione direttamente in codice nativo, è una soluzione molto ottimizzata che trova un ottimo compromesso tra velocità d’esecuzione e portabilità del codice. La spettacolarità della JVM è che l’interprete potrebbe essere anche implementato a livello hardware così che da eseguire il bytecode come codice nativo. Certamente a livello di prestazioni questa è la scelta migliore, ma come il lettore può facilmente dedurre la portabilità sarebbe di nuovo confinata a quelle macchine che implementino Java a livello hardware, anche se si continuerebbero ad avere tutti i vantaggi del linguaggio Java che abbiamo precedentemente analizzato. La piattaforma raggiunge performance superiori adottando uno schema nel quale l’interprete può essere eseguito alla massima velocità senza la necessita di effettuare controlli a runtime, questo grazie, come visto antecedentemente, al “class verifier” che esegue tutti i controlli. La piattaforma è anche dotata di un Garbage Collector nel quale la memoria non più utilizzata da alcun oggetto viene rilasciata automaticamente al sistema. Il Garbage Collector viene eseguito in un thread a bassa priorità e grazie a questo la memoria con alta probabilità è sempre disponibile quando richiesta. JAVA API Data la vastità immensa di API circolanti si possono scrivere applicazioni di qualsiasi genere. A tal proposito Java è disponibile in tre “scatole” a seconda dell’uso che se ne vuole fare. • la J2SE (Java 2 Standard Edition), il nucleo di Java, che permette di scrivere un gran numero di applicazioni: applicazioni client e server di rete; applicazioni per accesso a database, applicazioni per il calcolo scientifico; ecc.. • la J2EE (Java 2 Enterprise Edition) che permette di scrivere applicazioni distribuite. Pagina 10 Capitolo 1: I software utilizzati • la J2ME (Java 2 Micro Edition) che permette di scrivere applicazioni per i terminali mobili e Infine per tutti quei dispositivi che stanno invadendo la nostra vita con poche risorse computazionali (come i telefoni cellulari). Pagina 11 Capitolo 1: I software utilizzati 1.2 GWT (Google Web Toolkit) Figura 1.3: Logo GWT Il Google Web Toolkit (GWT) è un framework di sviluppo per applicazioni AJAX rilasciato sotto licenza open source Apache 2.0. Il suo obiettivo è permettere allo sviluppatore di lavorare ad un livello di astrazione più alto rispetto a quello nativo di AJAX evitando di sprecare risorse scrivendo linee di codice HTML e Javascript da testare sui diversi divers browser. Attraverso il GWT è possibile sviluppare e fare il debug di applicazioni AJAX utilizzando semplicemente Java e gli usuali IDE (Eclipse, IntelliJ, NetBeans). Dal momento in cui si vuole passare al sistema di produzione sarà necessario invocare il compilatore GWT che trasformerà l'applicazione stessa in codice HTML e Javascript browser-compabitile. Il ciclo di sviluppo GWT è quindi il seguente: 1. si sviluppa e si fa il debug della propria applicazione Java attraverso i vari tool disponibili sul mercato merca utilizzando le diverse librerie GWT. 2. si utilizza il compilatore GWT da Java a Javascript per creare un insieme di file HTML e Javascript che possono essere piazzati in qualsiasi web server. server 3. si esegue un test della piattaforma sul/sui browsers che la stessa ste dovrebbe supportare. GWT offre allo sviluppatore un insieme di componenti di interfaccia grafica che, assemblati, danno origine all'applicazione; tali componenti sono denominati Widget. Come in ogni framework per la gestione di interfaccia grafica esistono esistono dei Panel che contengono i widget necessari per lavorare. La tecnologia Java offre diversi vantaggi nello sviluppo rispetto a Javascript poiché: • Esiste un insieme molto ricco di tools di sviluppo (Eclipse, IntelliJ, JProfiler, JUnit). • Java verifica staticamente aticamente i tipi di dato riducendo gli errori a runrun-time. • Gli errori Javascript vengono evitati poiché il compilatore Java-to-Javascript Java di GWT conosce come non commetterli. Pagina 12 Capitolo 1: I software utilizzati • Java è più vicino ai tool di progettazione Object Oriented rispetto a Javascript e l'applicazione sarà più comprensibile e mantenibile. LA MODALITA’ “HOSTED” E’ possibile spendere la maggior parte del tempo nello sviluppo dei siti lavorando in hosted mode: ciò significa interagire con l’applicazione GWT senza che questa sia stata tradotta in Javascript. Ogni qualvolta si modifica, si manda in esecuzione e si esegue il debug delle applicazioni da una ambiente di sviluppo integrato Java (IDE), si lavora in hosted mode. Quando si lavora in questo modo la JVM esegue il codice dell’applicazione come bytecode Java compilato permettendo, di gran lunga, uno sviluppo più veloce dell’applicazione stessa. LA MODALITA’ “WEB” Un aspetto particolare che caratterizza il GWT è il suo impiego in modalità Web (ovvero la possibilità di accedere ad un’applicazione da un normale browser): quando un’applicazione viene lanciata in questa modalità, gira completamente in Javascript e non necessita di nessun plug-in per i vari browser o della JVM. LA PAGINA HOST Ogni pagina HTML può includere un codice creato con il GWT (pagina host). La struttura è stata progettata per rendere più facile l’aggiunta di funzionalità del GWT ad applicazioni web già esistenti con solo piccole modifiche. Nel progetto “MedTel” la pagina host è la seguente: <html> <head> <!-- --> <!-- Any title is fine --> <!-- --> <title>Starter Miro</title> <!-- --> <!-- The module reference below is the link --> <!-- between html and your Web Toolkit module --> <!-- --> Pagina 13 Capitolo 1: I software utilizzati <metaname='gwt:module'content='com.uni.mirongwt.Starter'/> <!-- --> <!-- Link CSS file --> <!-- --> <link type="text/css" rel='stylesheet' href='Starter.css'/> <link rel="stylesheet" type="text/css" href="js/ext/resources/css/ext- all.css" /> <link rel="stylesheet" type="text/css" href="js/ext/resources/css/xthemegray.css" /> <script type="text/javascript" src="js/ext/adapter/yui/yui-utilities.js"> </script> <script type="text/javascript" src="js/ext/adapter/yui/ext-yui-adapter.js"> </script> <script type="text/javascript" src="js/ext/ext-all.js"> </script> </head> <!-- --> <!-- The body can have arbitrary html, or --> <!-- we leave the body empty because we want --> <!-- to create a completely dynamic ui --> <!-- --> <body> <!-- --> <!-- This script is required bootstrap stuff. --> <!-- You can put it in the HEAD, but startup --> <!-- is slightly faster if you include it here. --> <!-- --> <script language="javascript" src="com.uni.mirongwt.Starter.nocache.js"> </script> Pagina 14 Capitolo 1: I software utilizzati <!-- OPTIONAL: include this if you want history support --> <iframe id="__gwt_historyFrame" style="width:0;height:0;border:0"> </iframe> </body> </html> Listato 1.1: Pagina Host del progetto “MedTel” IL CODICE Quando un’applicazione viene eseguita in Javascript nel browser, questa vene inviata ad un utente attraverso la rete. Tutto ciò che accade all'interno del proprio browser è chiamato processo client-side (lato client). Quando si scrive un codice lato client, che è destinato a funzionare nel browser web, si deve ricordare che alla fine diventa Javascript: pertanto, è importante utilizzare solo librerie e costrutti di linguaggio Java che possono essere tradotti. Qualsiasi cosa succeda all’interno del server si riferisce, invece, al processo server-side (lato server). Quando l’applicazione necessita di interagire con il server (per salvare o caricare dei dati, ad esempio) viene fatta una richiesta lato client (dal browser) attraverso la rete utilizzando una “Remote Procedure Call” (RPC). Durante l’elaborazione della RPC il server esegue il codice server-side. LA STRUTTURA DEL PROGETTO GWT I progetti GWT sono sovrapposti su pacchetti Java tale che la maggior parte della configurazione può essere dedotta dal classpath e dal personale modulo di definizioni. Se si stanno avviando uno progetto GWT da zero, si dovrebbe usare la struttura standard del package GWT, in cui è facile distinguere codice lato client dal codice lato server. La struttura standard del package, nel caso del progetto “MedTel” è così: • …/MedTel/src/com/uni/mirongwt/: il package principale del progetto che contiene il modulo XML dei files. • …/MedTel/src/com/uni/mirongwt/client: rappresenta il lato, dove sono contenuti i codici client-side, che comprende vari files, tra cui il file di origine (nel caso del “MedTel” è Starter.java), e possibili subpackages. • …/MedTel/src/com/uni/mirongwt/server: rappresenta il lato, dove sono contenuti i codici server-side, che comprende vari files e possibili subpackages. • …/MedTel/src/com/uni/mirongwt/public: contiene risorse statiche che possono essere servite al pubblico (ad esempio immagini o pagine HTML). Pagina 15 Capitolo 1: I software utilizzati I MODULI Le singole unità di configurazione del GWT sono file XML chiamati “moduli”. Un modulo lega insieme tutte le impostazioni di configurazione che necessita il progetto GWT, ovvero: • Moduli ereditati. • Nome della classe che costituisce il punto di ingresso (entry-point); questi sono facoltativi, anche se ogni modulo riferito all’HTML deve avere almeno una specificata classe come punto d'ingresso. • Ingressi del percorso di origine. • Ingressi del percorso pubblico. • Regole vincolanti differite, tra cui i fornitori di proprietà e generatori di classe. I moduli possono apparire in qualsiasi pacchetto nel classpath, anche se è fortemente raccomandato che compaiano nel pacchetto principale della struttura di un progetto standard. Un modulo di entry-point è rappresentato da ogni classe che è assegnabile ad un Entry Point e che può essere costruita senza parametri. Quando un modulo è caricato, ogni punto di ingresso è istanziato e il suo metodo EntryPoint.onModuleLoad() viene chiamato. Source Path: solo i file trovati sul percorso di origine sono candidati ad essere tradotti in Javascript, rendendo possibile la combinazione dei codici lato client e server nella stessa classpath senza conflitto. Quando un modulo eredita altri moduli, i loro percorsi d’origine sono combinati in modo tale che ciascun modulo avrà accesso alla fonte traducibile di cui necessita. Public Path: quando si compila l’applicazione in Javascript, tutti i file che possono essere trovati nel percorso pubblico vengono copiati nella cartella del modulo di uscita. L'effetto netto è che gli URL visibili agli utenti possono non comprendere a pieno il nome del pacchetto. Quando un modulo eredita altri moduli, i loro percorsi pubblico sono combinati in modo tale che ciascun modulo avrà accesso alle risorse statiche che si aspetta. Il modulo che si riferisce al progetto “MedTel” è “Starter.gwt.xml” ed è fatto così: <module> //componenti ereditati <inherits name="com.google.gwt.user.User"/> <inherits name="com.gwtext.GwtExt" /> Pagina 16 Capitolo 1: I software utilizzati <inherits name="com.gwtextux.GwtExtUx" /> //è la classe di ingresso <entry-point class="com.uni.mirongwt.client.Starter"/> //sono utilizzate per le RPC <servlet path="/loginRM" class="com.uni.mirongwt.server.loginRMImpl"/> <servlet path="/CaricaFile" class="com.uni.mirongwt.server.CaricaFile"/> <servlet path="/RegistrationRM" class="com.uni.mirongwt.server.RegistrationRMImpl"/> <servlet path="/ListaUserRM" class="com.uni.mirongwt.server.ListaUserRMImpl"/> <servlet path="/AddConsultantRM" class="com.uni.mirongwt.server.AddConsultantRMImpl"/> <servlet path="/PatientClinicalProblemRM" class="com.uni.mirongwt.server.PatientClinicalProblemRMImpl"/> <servlet path="/ViewClinicalProblemRM" class="com.uni.mirongwt.server.ViewClinicalProblemRMImpl"/> <servlet path="/PatientProfileRS" class="com.uni.mirongwt.server.PatientProfileRSImpl"/> <servlet path="/PhisiologicalRS" class="com.uni.mirongwt.server.PhisiologicalRSImpl"/> <servlet path="/PhisiologicalViewRS" class="com.uni.mirongwt.server.PhisiologicalViewRSImpl"/> <servlet path="/AllergologyRS" class="com.uni.mirongwt.server.AllergologyRSImpl"/> <servlet path="/FamiliarsRS" class="com.uni.mirongwt.server.FamiliarsRSImpl"/> <servlet path="/FamiliarsViewRS" class="com.uni.mirongwt.server.FamiliarsViewRSImpl"/> <servlet path="/PathologicalsRS" Pagina 17 Capitolo 1: I software utilizzati class="com.uni.mirongwt.server.PathologicalsRSImpl"/> <servlet path="/AllergologyViewRS" class="com.uni.mirongwt.server.AllergologyViewRSImpl"/> <servlet path="/PathologiesViewRS" class="com.uni.mirongwt.server.PathologiesViewRSImpl"/> <servlet path="/ClinicalFolderRS" class="com.uni.mirongwt.server.ClinicalFolderRSImpl"/> <servlet path="/PathologicalsViewRS" class="com.uni.mirongwt.server.PathologicalsViewRSImpl"/> <servlet path="/XmlAnamnesis" class="com.uni.mirongwt.server.XmlAnamnesis"/> <servlet path="/FamilyRS" class="com.uni.mirongwt.server.FamilyRSImpl"/> <servlet path="/AnamnesisViewRS" class="com.uni.mirongwt.server.AnamnesisViewRSImpl"/> <servlet path="/PathologiesRS" class="com.uni.mirongwt.server.PathologiesRSImpl"/> <servlet path="/ListaPatientRS" class="com.uni.mirongwt.server.ListaPatientRSImpl"/> <servlet path="/PatientRS" class="com.uni.mirongwt.server.PatientRSImpl"/> <servlet path="/UserAreaRS" class="com.uni.mirongwt.server.UserAreaRSImpl"/> <servlet path="/ModRegistrationRS" class="com.uni.mirongwt.server.ModRegistrationRSImpl"/> <servlet path="/ViewEventsRequestRS" class="com.uni.mirongwt.server.ViewEventsRequestRSImpl"/> <servlet path="/EventsPatientsRS" class="com.uni.mirongwt.server.EventsPatientsRSImpl"/> <servlet path="/ViewVisitsEventRS" class="com.uni.mirongwt.server.ViewVisitsEventRSImpl"/> <servlet path="/DetailsVisitRS" class="com.uni.mirongwt.server.DetailsVisitRSImpl"/> Pagina 18 Capitolo 1: I software utilizzati <servlet path="/Message_ReportRS" class="com.uni.mirongwt.server.Message_ReportRSImpl"/> <servlet path="/View_msg_reportRS" class="com.uni.mirongwt.server.View_msg_reportRSImpl"/> </module> Listato 1.2: Modulo del “MedTel” ELEMENTI DEL MODULO Sono riportati i vari elementi di un modulo generico: • <inherits name=" logical-module-name "/>: eredita tutte le impostazioni dal modulo specificato come se i contenuti di quelli XML ereditati siano stati letteralmente copiati. Qualsiasi modulo può essere ereditato in questo modo. • <entry-point class=" classe "/>: specifica una classe come punto d'ingresso. Qualsiasi classe (vista come punto d’ingresso) può essere aggiunta, anche quelle da moduli ereditati. • <source path=" percorso "/>: aggiunge packages al percorso di origine combinando il package in cui è stato trovato il modulo XML con il percorso specificato ad un subpackage. Ogni file sorgente Java che compare in questo o in altri suoi subpackage si presume che sia traducibile. Se nessun elemento <source> è definito in un modulo di file XML, il client subpackage è implicitamente aggiunto al percorso di origine come se <source path="client"> sia stato trovato nell’XML. Questa impostazione predefinita consente di mantenere compatto il modulo XML per strutture di progetto standard. • <public path=" percorso "/>: aggiunge packages al percorso pubblico combinando il package in cui è stato trovato il modulo XML con il percorso specificato per identificare la radice di un percorso pubblico di ingresso. Qualsiasi file che compare in questo o in altri suoi subpackage verrà considerato come una risorsa pubblicamente accessibile. L’elemento <public> supporta un modello a base di filtraggio (pattern-based filtering) per consentire controllo granulare su quali risorse sono state copiate nella cartella di output nel corso di una compilazione GWT. Se nessun elemento <public> è definito in un modulo di file XML, il public subpackage è implicitamente aggiunto al percorso pubblico come se <public path="public"> sia stato trovato nell’XML. Questa impostazione Pagina 19 Capitolo 1: I software utilizzati predefinita consente di mantenere compatto il modulo XML per strutture di progetto standard. • <servlet path=" url-path " class=" classe "/>: per convenienti analisi RPC questo elemento carica una classe servlet montata nel percorso URL specificato. Quest’ultimo dovrebbe essere assoluto e avere la forma di una cartella (ad esempio, /cartella). Il codice cliente personale specifica, poi, questo URL mappando in una chiamata a ServiceDefTarget.setServiceEntryPoint(String). Qualsiasi servlet può essere caricato in questo modo, anche quelli da moduli ereditati. • <script src=" js-url "/>: immette automaticamente il file Javascript esterno che si trova nella posizione specificata da src. • <stylesheet src=" css-url "/>: immette automaticamente il file CSS esterno che si trova nella posizione specificata da src. • <extend-property name=" client-property-name " values=" comma-separatedvalues "/>: estende l'insieme di valori per una proprietà client esistente. Qualsiasi valore può essere aggiunto in questo modo (quelli di proprietà client si accumulano attraverso moduli ereditati). 1.2.1 LE ESTENSIONI GWT Nella progettazione del portale “MedTel” sono state utilizzate due estensioni del GWT, GWT-EXT e GWT-EXT UX, anche se effettivamente si è deciso di utilizzare quasi esclusivamente la prima. Figura 1.4: Logo GWT-Ext La GWT-EXT è una potente libreria che fornisce ricchi widgets come la Grid (griglia per costruire le tabelle), il Tree, la Combo Box, il Panel, il Menù, la Toolbar e altri elementi. La GWT-EXT UX, invece, è una libreria che estende delle funzionalità di alcuni widgets rispetto a quella descritta in precedenza. Pagina 20 Capitolo 1: I software utilizzati 1.3 RPC (Remote Procedure Call) Il meccanismo di interazione con un server attraverso la rete è chiamato RPC (Remote Procedure Call), anche talvolta indicato come una server call. L’RPC del GWT rende facile per il client ed il server passare oggetti Java avanti e indietro su HTTP. Se usato correttamente, l’RPC dà la possibilità di spostare tutti gli UI logici al client comportando prestazioni nettamente superiori, larghezza di banda ridotta, così come il carico del server Web. Il codice lato server che viene invocato dal client è spesso definito come un “servizio”: così l'atto di effettuare una chiamata di procedura remota (RPC) è talvolta indicato come invocare un servizio. Il concetto di “servizio” in questo contesto non è sinonimo del più generale "servizio web". In particolare, i servizi GWT non sono legati alla Simple Object Access Protocol (SOAP). Le componenti necessarie per una RPC sono quattro: • Classe Java (lato client): attiva la chiamata asincrona. I passi sono: 1. Creo il proxy client. Sebbene si stia creando un corretto servizio di interfaccia, è necessario fare il cast alla versione asincrona dell’interfaccia (sempre sicuro perché il proxy generato implementa l’interfaccia asincrona automaticamente). loginRMAsync login = (loginRMAsync) GWT.create(loginRM.class); 2. Specifico l’URL nel quale l’implementazione del servizio è in esecuzione. La destinazione dell’URL deve risiedere nello stesso dominio e nella stessa porta dai quali la pagina host è servita. ServiceDefTarget endpoint = (ServiceDefTarget) login; String moduleRelativeURL = GWT.getModuleBaseURL() + "loginRM"; endpoint.setServiceEntryPoint(moduleRelativeURL); 3. Creo la chiamata asincrona per gestire il risultato. AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { […] //in caso di successo } public void onFailure(Throwable caught) { Pagina 21 Capitolo 1: I software utilizzati […] //in caso di fallimento } }; 4. Effettua la chiamata. Il flusso di controllo continua immediatamente e successivamente la “callback” sarà invocata quando l’RPC è completata. login.login(username.getValueAsString(),password.getValueAsString(), callback); • Interfaccia sincrona (lato client): crea il servizio estendendo l’interfaccia tag RemoteService. public interface loginRM extends RemoteService { public String[] login(String user, String pass); } • Interfaccia asincrona (lato client): necessaria per effettuare una RPC, è basata sull’interfaccia originale del servizio. La natura del metodo asincrono richiede al chiamante di passare in un oggetto di callback quello che può essere notificato quando una chiamata asincrona si completa, in quanto, per definizione, il chiamante non può essere bloccato fino a quando la chiamata non si completa. Per lo stesso motivo, i metodi asincroni non hanno tipi di ritorno, ma devono sempre ritornare nulle. Dopo che una chiamata asincrona è stata fatta, tutta la comunicazione di ritorno al chiamante è passata attraverso un oggetto di callback. public interface loginRMAsync { public void login(String user, String pass, AsyncCallback callback); callback } • Classe Java (lato server): definisce i metodi dell’interfaccia. public class loginRMImpl extends loginRM { […] } Pagina 22 RemoteServiceServlet implements Capitolo 1: I software utilizzati 1.4 ALTRI SOFTWARE Per sviluppare il progetto si è fatto affidamento ad alcuni programmi open source in quanto fedeli alla filosofia della conoscenza libera a tutti, senza dover necessariamente pagare per usufruire delle funzionalità del programma richiesto. Ad esempio, per scrivere il codice si è deciso di usufruire delle prestazioni di Eclipse mentre per l’esecuzione del portale sul server e per le verifiche in locale si è utilizzato Tomcat. 1.4.1 ECLIPSE Figura 1.5: Logo Eclipse La versione utilizzata nel progetto è la 3.3, poi sostituita da quella più aggiornata 3.4. Lo scopo della comunità di Eclipse è quello di fornire una piattaforma di sviluppo ed un framework applicativo per lo sviluppo di software. Il componente base è l'Eclipse SDK, disponibile per tutte le piattaforme (Windows, Linux, Solaris, ecc.). A tale componente è poi possibile aggiungere parecchi strumenti e plugin che forniscono ulteriori potenzialità ad Eclipse. Nel settore informatico, Eclipse è una piattaforma software che comprende frameworks applicativi estensibili, strumenti e una libreria runtime per lo sviluppo e la gestione di software. È scritto prevalentemente in Java per fornire agli sviluppatori di software ed agli amministratori un ambiente di sviluppo integrato (IDE). La chiave per la perfetta integrazione (ma non di interoperabilità) di strumenti con Eclipse è il plugin. Con l'eccezione di un piccolo run-time del kernel, tutto in Eclipse è un plugin. Questo significa che ogni plugin sviluppato si integra con Eclipse esattamente nella stessa maniera degli altri plugins; a questo proposito, tutte le funzioni sono creati uguali. I widgets di Eclipse sono implementati da un widget toolkit per Java chiamato SWT, a differenza della maggior parte delle applicazioni Java, che utilizza lo standard Java “Abstract Window Toolkit” (AWT) o “Swing”. Pagina 23 Capitolo 1: I software utilizzati IL DEPLOY MODULE DEL GWT Per effettuare il deploy module in Eclipse su un’applicazione server bisogna cliccare sul modulo xml del progetto e selezionare l’omonimo comando dalla lista che appare. Nella finestra che compare verrà chiesto di stabilire nome del file .war che verrà creato, il percorso nel server dove viene messo quest’ultimo, lo stile e la memoria del compilatore. Riassumendo, vengono creati molteplici file con questa operazione: il primo è quello .war (utilizzato dal server), un altro è build.xml (contiene tutti i passi che servono per creare il file WAR) che verrà ricostruito ogni volta che viene fatta un’operazione di deploy. I file con estensione .war sono denominati Web Archives (sono quindi degli archivi utilizzati dalle Servlet) e rappresentano dei componenti utilizzati in fase di messa in opera di un'applicazione (deployment). Un file .war, al suo interno, contiene i componenti Web che fanno parte di una applicazione J2EE (come, ad esempio pagine JSP, file HTML, file .class e file XML). 1.4.2 TOMCAT Figura 1.6: Logo Tomcat La versione utilizzata nel progetto è la 5.5, poi sostituita da quella più aggiornata 6.0. Apache Tomcat è un’implementazione delle tecnologie Java Servlet e JavaServer Pages. Le specifiche Java Servlet e JavaServer Pages sono sviluppate dal “Java Community Process”. Apache Tomcat è sviluppato in un ambiente aperto e partecipativo ed è rilasciato sotto la “Apache Software License”; è destinato, inoltre, ad essere una collaborazione dei più grandi sviluppatori di tutto il mondo. La funzionalità di spicco di Tomcat è quella del “Web Application Server”, ovvero un server capace di gestire e supportare le pagine JSP e le servlet nel rispetto delle specifiche 2.4 (per le servlet) e 2.0 (per le JSP). E’ importante sapere che Tomcat è in grado di svolgere anche le veci di un Web Server, anche se limitato alla gestione di sole pagine statiche. Pagina 24 Capitolo 1: I software utilizzati 1.4.3 MYSQL Figura 1.7: Logo MySQL MySQL è un database management system (DBMS) relazionale, composto da un client con interfaccia a caratteri e un server, entrambi disponibili sia per sistemi Unix (come GNU/Linux) che per Windows, anche se prevale un suo utilizzo in ambito Unix. Dal 1996 supporta la maggior parte della sintassi SQL e si prevede in futuro il pieno rispetto dello standard ANSI. Esistono diversi tipi di MySQL Manager, ovvero di strumenti per l'amministrazione di MySQL. Uno dei programmi più popolari per amministrare i database MySQL è “phpMyAdmin” (quello che è stato utilizzato per modificare i contenuti del database sul quale si appoggia il portale), che richiede un server web come Apache_HTTP_Server ed il supporto del linguaggio PHP. Si può utilizzare facilmente tramite un qualsiasi browser. Durante la progettazione si sono sfruttate le utili funzioni messe a disposizione dal “phpMyAdmin” mentre per la fase di caricamento dei dati nel server si sono utilizzati altri due programmi (“MySQL Administrator” e “MySQL Query Browser”) perché più immediati rispetto alla digitazione dei dati da shell. PhpMyAdmin è probabilmente uno dei software più diffusi in assoluto nel mondo del web. Si tratta infatti di uno strumento open source, scritto in PHP, che consente l'amministrazione di MySQL attraverso un'interfaccia web. PhpMyAdmin è sviluppato da una comunità autonoma rispetto a MySQL AB ed è un'applicazione web-based che necessita quindi di un server web in grado di eseguire PHP. La sua comodità principale consiste nel consentire l'amministrazione del database anche da remoto senza la necessità che il server sia aperto a connessioni remote: infatti è il server web su cui viene eseguito PhpMyAdmin che effettua le connessioni a MySQL. Di conseguenza è sufficiente installare il software sul web server locale rispetto a MySQL per poter poi effettuare l'amministrazione attraverso un qualsiasi browser. L'accesso al server avviene con i diritti dell'utente che accede all'applicazione. Una possibilità interessante è quella di configurare più di un server sullo stesso file: questo consentirà agli utilizzatori di PhpMyAdmin di selezionare, attraverso una casella a discesa nella home page, il server al quale intendono collegarsi. L'interfaccia di PhpMyAdmin è disponibile in moltissime lingue, tra cui Pagina 25 Capitolo 1: I software utilizzati naturalmente anche l'italiano. Essendo possibile configurarlo perché acceda a MySQL coi diritti dell'utente che lo utilizza, risulta utile anche per consentire agli utenti non amministratori di accedere soltanto ai propri database. MySQL Administrator è, invece, un programma di amministrazione a interfaccia grafica fornito da MySQL AB: consente di configurare il server, monitorarne lo stato e le prestazioni, avviarlo e arrestarlo, gestire gli utenti, effettuare backup e altro. Funziona con le versioni di MySQL dalla 4.0 in poi. La sua versione raccomandata è la 1.1, che supporta tutte le nuove funzionalità introdotte in MySQL 5.0. È disponibile per sistemi Windows, Linux e Mac OSX. MySQL Query Browser è un altro programma a interfaccia grafica fornito dalla casa produttrice di MySQL. La sua funzione è quella di facilitare l'esecuzione e l'ottimizzazione delle query e l'analisi dei dati contenuti nel server. Anche questo programma funziona con le versioni da 4.0 in poi di MySQL. È disponibile per Windows e Linux. Pagina 26 Capitolo 2: I portali per la telemedicina CAPITOLO 2: I portali per la telemedicina • cos’è la telemedicina • descrizione “Miro On Rails” • aspetti corretti con “MedTel” Pagina 27 Capitolo 2: I portali per la telemedicina 2.1 IL CONCETTO “TELEMEDICINA” La telemedicina è l'insieme di tecniche mediche ed informatiche che permettono la cura di un paziente a distanza o più in generale di fornire servizi sanitari a distanza. Nata per facilitare l’accesso a strutture sanitarie specialistiche, da parte di pazienti distanti dai Centri di Eccellenza medica e/o per garantire una miglior efficienza del sistema ospedaliero, nell'ambito della diagnostica clinica permette ad un medico effettuare la diagnosi su un paziente che non è fisicamente nello stesso posto del medico, attraverso la trasmissione a distanza di dati prodotti da strumenti diagnostici (si muovono le informazioni al posto dei pazienti). La seconda opinione medica è una delle applicazioni più comuni nell'ambito della telemedicina: essa consiste nel fornire una opinione clinica a distanza supportata da dati acquisiti, inviati ad un medico remoto che li analizza e li referta, producendo di fatto una seconda valutazione clinica su un paziente. Le tecniche telemediche di fatto favoriscono anche applicazioni di formazione distanza, nelle quali il medico remoto può specializzare i medici che chiedono una seconda opinione su un caso clinico attraverso la messaggistica. Figura 2.1: Delocalizzazione del servizio telemedico La classificazione più comune della telemedicina è effettuata a partire dal settore medico al quale viene applicata: • TELEPATOLOGIA: branca della telemedicina che prevede il trasferimento di immagini digitali macroscopiche e microscopiche a scopo diagnostico o educativo mediante la tecnologia informatica. • TELERADIOLOGIA • TELECARDIOLOGIA • TELEDERMATOLOGIA • TELERIABILITAZIONE: erogazione di servizi riabilitativi attraverso le reti di telecomunicazione ed internet. Pagina 28 Capitolo 2: I portali per la telemedicina Lo sviluppo tecnologico e la necessità di contenimento dei costi del servizio sanitario hanno spinto la telemedicina verso un ruolo di avanguardia tra i servizi della sanità e hanno proiettato la sua applicazione in varie direzioni. Non è un segreto, inoltre, la volontà di raggiungere una cooperazione, grazie all’utilizzo di questa struttura medico-informatica, tra i Paesi dotati di maggiori tecnologie e quelli in via di sviluppo. In termini progettuali, il portale per tele-refertazioni mira allo sviluppo di servizi di telemedicina che consentano l’interscambio di dati multimediali e l’integrazione di archivi di interesse medico, distribuiti sul territorio e gestiti da diversi Enti. Il sistema deve consentire la trasmissione, l’archiviazione e consultazione di dati clinici ed immagini diagnostiche e il monitoraggio di pazienti sfruttando sistemi e presidi geograficamente distribuiti sul territorio. Applicare la telematica in ambito medico significa rispondere con tempestività alle esigenze diagnostiche (telediagnosi) e terapeutiche (teleassistenza) di cittadini distanti dalle strutture sanitarie o comunque impossibilitati a muoversi da casa; fornire una risposta valida ed efficace in caso di malati cronici o anziani e un supporto indispensabile nelle urgenze (telesoccorso); favorire l’aggiornamento scientifico (teledidattica) e il collegamento interattivo tra medici (video-teleconsulto) con condivisione dinamica di informazioni, cartelle cliniche digitali, tracciati diagnostici, immagini biomediche, che si "muovono" in tempo reale e con la massima definizione. Le aree di competenza che confluiscono nella telemedicina sono perciò quelle della Medicina, della Ingegneria Medica, dell’Informatica Medica, nonché dei settori generali dell'Informatica e delle Telecomunicazioni. I campi di applicazione della telemedicina sono numerosissimi e in continua evoluzione: dalla cardiologia (trasmissione di tracciati elettrocardiografici) alla radiologia (immagini radiografiche e computerizzate), dalla dermatologia (foto digitali di lesioni cutanee) all’anatomia patologica, dalla ginecologia (monitoraggio in gravidanza) all’odontoiatria e via dicendo; praticamente ogni branca della medicina può avvalersi di questo strumento per migliorare l’esercizio delle attività cliniche, assistenziali e didattiche. 2.1.1 OBIETTIVI DELLA TELEMEDICINA L’avvento dell’informatica medica e la conseguente introduzione di nuove tecnologie nell’ambito sanitario hanno portato e porteranno notevoli vantaggi sia per i pazienti che per il personale medico. L’introduzione della telemedicina permette di: Pagina 29 Capitolo 2: I portali per la telemedicina • Ridurre i costi per personale, specialmente quello di emergenza. • Migliorare la qualità di vita dei pazienti, consentendo loro di essere curati a domicilio o comunque il più possibile vicino alla loro abitazione ed evitando a questi faticosi o onerosi spostamenti. • Incrementare la disponibilità di specialisti indipendentemente dal luogo in cui abiti il paziente, migliorando l’assistenza anche in quelle comunità territorialmente sparse ed evitando al personale medico fastidiosi o improponibili spostamenti. • Accrescere la qualità delle decisioni del medico mettendo a sua disposizione, in modo semplice, veloce e sempre aggiornato, le informazioni esistenti relative al paziente e quelle riguardanti diagnosi e metodi di cura. • Fornire al paziente un servizio migliore e anche maggiori informazioni sullo stato della propria salute. • Garantire una più efficace e tempestiva assistenza diagnostica e terapeutica, soprattutto nei casi di urgenza, tramite comunicazioni più veloci. • Garantire sicurezza e privacy nello scambio di informazioni mediche di ogni singolo paziente. • Sostenere maggiormente lo staff medico allo scopo di formarlo sia a livello teorico sia a livello pratico. Pagina 30 Capitolo 2: I portali per la telemedicina 2.2 “MIRO MIRO ON RAILS”: RAILS RUBY ON RAILS Figura 2.2: Logo Ruby On Rails Ruby on Rails è un framework per applicazioni web open source per il linguaggio di programmazione Ruby. È spesso chiamato 'Rails' o' RoR '. E’ destinato ad essere utilizzato con la metodologia di sviluppo “Agile”, che è spesso utilizzata da sviluppatori web per la sua idoneità per brevi progetti client-driven. La sfida che Rails lancia è ridurre all'osso i tempi di sviluppo: scrivere meno codice possibile, in meno tempo e creare applicazioni migliori per fornire migliori servizi agli utenti. Per questo Rails cattura l'attenzione l'attenzione di un numero crescente di sviluppatori e vede aumentare consensi e adesioni all'interno della comunità web. I principi guida di Ruby on Rails sono due: • "Don't Repeat Yourself": Yourself": significa che le definizioni devono essere poste una volta soltanto. Poiché Ruby On Rails è un framework "full-stack", "full stack", i componenti sono integrati in modo tale che i collegamenti fra di essi non devono essere impostati manualmente. Ad esempio in Active Record (uno dei pacchetti che costituisce Ruby On Rails),, le definizioni delle classi non devono specificare i nomi delle colonne ma possono essere estratte direttamente dal database:: riportarte anche nel programma,dunque, ,dunque, costituirebbe una ridondanza. • "Convention Over Configuration": Configuration": significa che il programmatore ha bisogno di metter mano alla configurazione soltanto per ciò che differisce dalle convenzioni. Ad esempio, se un modello è costituito dalla classe Post,, la corrispondente tabella nel database deve chiamarsi posts,, o altrimenti deve essere specificata manualmente (set_table_name et_table_name "blogposts", "blogposts" nel caso in cui blogposts sia il nome della tabella). Pagina 31 Capitolo 2: I portali per la telemedicina 2.3 “MIRO ON RAILS”: IL PORTALE Figura 2.3: Portale “Miro On Rails” “Miro On Rails”, dal punto di vista funzionale, realizza sufficientemente gli obiettivi che un portale per telerefertazione deve soddisfare: proprio per questo esso costituisce la base del più nuovo “MedTel” che, oltre ad essere graficamente migliore, grazie alle funzioni fornite dal GWT, risolve gran parte dei bug esistenti. 2.3.1 ASPETTI CORRETTI DEL PORTALE L’analisi dettagliata del portale ha portato alla luce diversi aspetti che necessitavano di essere perfezionati oppure ripresi da capo. Tralasciando gli aspetti grafici che, indubbiamente, hanno facilitato l’orientamento dell’utente e la comprensione da parte di quest’ultimo dei concetti presentatigli, come ad esempio tabelle e cartella del paziente. LOGIN Il login non presenta errori logistici né esecutivi quindi non è stato corretto. E’ stato implementato, inoltre, il meccanismo di memorizzazione dell’utente che effettua l’accesso (cosa invece non inserita in “MedTel” poiché considerata superflua). La procedura di login, a livello visivo, è simile per entrambi i portali con la differenza che in quello realizzato con il GWT compare una maschera con scritto “Please wait...” durante il passaggio tra il pannello di login e quello dell’area riservata all’utente. Pagina 32 Capitolo 2: I portali per la telemedicina Anche il logout è simile: nel “MedTel”, diversamente dall’altro portale però, il pulsante per far uscire l’utente si trova nel menù a tendina; dopo aver cliccato su di esso compare una nuova maschera con scritto “Logging out…” prima che il portale venga ricaricato. AMMINISTRAZIONE Figura 2.4: Portale “Miro On Rails”: area amministrazione Figura 2.5: Portale “MedTel”: area amministrazione (1° e 2° livello) Come per il “MedTel”, anche “Miro On Rails” adotta una procedura di sicurezza simile: esiste un amministratore di primo livello che può creare altri amministratori (di secondo livello) ma anche dottori e richiedenti. La differenza tra le due categorie di amministrazione è minima in quanto entrambi possiedono le stesse funzionalità e possono compiere le stesse operazioni precedentemente descritte. In “MedTel”, invece, le uniche azioni che un amministratore di primo livello può fare è la creazione o la cancellazione di manager (quelli di seconda categoria) e la modifica dei dati personali. Quest’ultima operazione è prerogativa anche di tutti gli altri utenti. L’amministratore di secondo livello può creare dottori e richiedenti di sua competenza: sempre per questioni di sicurezza è Pagina 33 Capitolo 2: I portali per la telemedicina stato previsto che se il manager viene cancellato, per un qualsiasi motivo, gli utenti che fanno riferimento a questo passano sotto il controllo di un altro amministratore di secondo livello, se esiste, oppure, come ultima possibilità, sotto quello di prima categoria. La stessa procedura è prevista per la gestione dei pazienti quando il richiedente di competenza viene cancellato. AREA RISERVATA DELL’UTENTE Figura 2.6: Portale “Miro On Rails”: vista cartella clinica (dottore) Come struttura, “MedTel” riprende alcuni aspetti del “Miro On Rails” come, ad esempio, l’utilizzo di un contenitore in cui verranno aperti i dati di ogni pannello dopo aver cliccato nell’apposito link. A destra, inoltre, è sempre presente, per ogni tipo d’utente (eccetto per gli amministratori), uno spazio destinato ad ospitare i vari collegamenti della cartella clinica di un particolare paziente (la quale si apre dopo aver cliccato su quest’ultimo dalla relativa tabella): uno dei problemi che sono stati riscontrati sta nel fatto che il dottore può compiere le stesse identiche operazioni di un richiedente nella cartella clinica. Tali comportamenti non possono essere accettati perché il medico, in teoria, non conosce il paziente e di conseguenza non è in grado (e non deve esserlo) di aggiungere informazioni al profilo e all’anamnesi di quest’ultimo. In aggiunta, la cartella clinica rimane sempre visibile (cambia solo il paziente a cui si fa riferimento) anche se si stanno effettuando diverse operazioni: questo aspetto è stato ritenuto poco funzionale poiché, se non si tratta di interventi sui dati presenti nella cartella, la visualizzazione di tali informazioni è superflua e poco utile in quel momento al dottore. Pagina 34 Capitolo 2: I portali per la telemedicina Figura 2.7: Portale “MedTel”: vista cartella clinica In “MedTel” si è ovviato a questi bug adottando l’idea di aprire la cartella clinica in una nuova finestra dinamica (vede se l’utente che vi accede è un richiedente o un dottore) in modo tale che chiunque vi entri si concentri solo su quelle funzioni per poi, quando si decide di chiuderla, ritornare al lavoro che si stava facendo in precedenza. Figura 2.8: Portale “Miro On Rails”: esito dell’utilizzo della libreria API Nell’area riservata del “Miro On Rails”, così come in altre form presenti nel portale, al momento della registrazione di un utente o della modifica dei suoi dati, è stata utilizzata una particolare libreria API che permette di ricercare in rete la città indicata nel relativo campo, ottenendo in questo modo, oltre al nome e allo stato in cui si trova, informazioni riguardanti la posizione longitudinale e latitudinale del posto. In “MedTel” si è deciso di non implementare questa funzione perché ciò avrebbe comportato l’aggiunta di una nuova tabella (quella che nel “Miro On Rails” si chiama “locations”) nel database, contando anche il fatto che l’utilizzo di questa libreria non era indispensabile. Pagina 35 Capitolo 2: I portali per la telemedicina Figura 2.9: Portale “Miro On Rails”: esito ricerca paziente positivo Figura 2.10: Portale “Miro On Rails”: esito ricerca paziente negativo Un’altra imperfezione progettuale rilevata riguarda la modalità di registrazione di un nuovo paziente: “Miro On Rails” offre la possibilità di aggiungerne uno nuovo soltanto se l’esito della ricerca nel database con i dati passati (nome, cognome, data ed eventualmente luogo di nascita) ha esito negativo, ovvero che non viene ritrovato nessun paziente con quelle credenziali. Come conseguenza di ciò verrà visualizzato, sotto alla form iniziale di ricerca, un link che consente di inserire i rimanenti dati in un’ulteriore form, che compare al posto del collegamento, e poi di salvarli nella tabella “patients” del database. Nel caso, invece, che la query trovi una persona con quelle credenziali verrà segnalato solamente il fatto che il paziente già esiste, senza fare nient’altro. In “MedTel”, al contrario, questa form di ricerca è stata tolta poiché non apportava un beneficio al portale ma soltanto una cosa superflua in più: piuttosto che migliorare tale modalità di registrazione, si è pensato di progettarla diversamente, introducendo un pannello, contenente tutti i campi (obbligatori e non) per l’aggiunta di un nuovo paziente alla corrispondente lista del richiedente, che segnala, una volta cliccato sul pulsante “Save” se è possibile o meno effettuare il salvataggio nel database (controlla prima nel database se esiste già un paziente). Pagina 36 Capitolo 2: I portali per la telemedicina Figura 2.11: Portale “MedTel”: inserimento nuovo utente MESSAGGISTICA Figura 2.12: Portale “Miro On Rails”: visualizzazione referti e messaggi dei problemi clinici Pagina 37 Capitolo 2: I portali per la telemedicina “MedTel” utilizza il modo di rappresentare sia i referti che i messaggi riproponendo, nella presentazione di queste informazioni, l’ora in cui sono state salvate, la persona che le ha scritte e altri dettagli utili per chi consulta i problemi clinici dei pazienti. Uno degli aspetti che sono stati corretti del progetto “Miro On Rails” è la visualizzazione dei referti e dei messaggi in relazione agli esami che un dottore o un richiedente possono consultare: in primo luogo, i messaggi in “MedTel” possono essere visti da entrambi i tipi d’utente mentre nell’altro progetto ciò valeva solo per i medici; in secondo luogo, se esistono problemi clinici (indipendentemente dal numero e dal tipo degli esami) che hanno molteplici messaggi e referti, ogni pannello (ognuno contente un’informazione specifica), che si vorrà aprire, sarà visualizzato nello spazio sottostante creando notevole confusione nel caso ne venissero aperti molti. Nel portale “MedTel” si è ovviato a questo bug facendo in modo che venga caricato nel pannello sottostante solo un esame alla volta e che messaggi e referti siano visualizzabili in pannelli richiudibili in due finestre diverse. Figura 2.13: Portale “MedTel”: visualizzazione problemi clinici A differenza del “Miro On Rails”, per inserire un nuovo messaggio o un nuovo referto viene aperta un’apposita finestra mentre in precedenza compariva un pannello sotto quello contenente il problema clinico. Pagina 38 Capitolo 2: I portali per la telemedicina Figura 2.14: Portale “Miro On Rails”: inserimento referti e messaggi CARTELLA CLINICA Figura 2.15: Portale “Miro On Rails”: cartella clinica Sin dall’inizio la cartella clinica del “Miro On Rails” è sembrata molto statica anche se funzionalmente è stata progettata bene (infatti in “MedTel” si sono adottati gli stessi accorgimenti): nel nuovo portale, di fatto, oltre alla decisione di aprire la cartella in una nuova finestra, si è scelto di costruire un menù dinamico che presenti tutti gli elementi di ogni categoria e che si aggiorni automaticamente quando uno di questi viene inserito, Pagina 39 Capitolo 2: I portali per la telemedicina modificato o cancellato. Tutto ciò è stato possibile utilizzando un albero asincrono, che costituisce una parte del menù, il quale si appoggia su un documento xml per ordinare in base alle categorie i vari elementi. Quest’albero viene ricostruito ogni volta il pannello viene ricaricato: sebbene questa soluzione presenti ancora delle limitazioni (ad esempio, non è possibile creare una struttura che possegga più di tre livelli di organizzazione) e le informazioni in internet relative sono pressoché sufficienti e approssimative, i risultati ottenuti sono stati più che soddisfacenti. L’albero asincrono è stato utilizzato per il ramo dell’anamnesi in modo tale che qualsiasi utente, che consulti o modifichi la cartella clinica di un paziente, possa vedere subito tutti gli elementi che ne fanno parte senza doverli necessariamente ricercare all’interno di ogni sezione così come accade nel “Miro On Rails”. In “MedTel” si è anche risolto il problema della visualizzazione degli elementi di ogni sezione dell’anamnesi: ad esempio, nel vecchio portale, se una delle sezioni ne possiede molti, questi vengono visualizzati, con i loro dati, uno sotto l’altro in degli appositi spazi che allungano la dimensione della pagina in cui si trovano, costringendo l’utente a ricercare l’informazione desiderata (cosa, invece, evitata in “MedTel” proprio grazie all’utilizzo del menù ad albero asincrono che presenta immediatamente tutti gli elementi esistenti per quel determinato paziente). Figura 2.16: Portale “MedTel”: menù con albero asincrono Pagina 40 Capitolo 2: I portali per la telemedicina 2.4 “MIRO ON RAILS”: ORGANIZZAZIONE DATABASE Uno degli obiettivi principali del progetto “MedTel” è quello di semplificare la struttura del sito cercando, quando possibile, di eliminare parti irrilevanti per evitare inutili confusioni nella fase di strutturazione del portale. Nel “MiroOnRails” le tabelle che facevano parte del database erano 21 ma non tutte erano sfruttate alla perfezione. TABELLA allergies FUNZIONALITA’ COLLEGATA A… elenca le allergie possibili anamnesis_allergologie s allergy_categories elenca le categorie di allergie anamnesis_allergologies contiene le allergie di ogni paziente anamnesis_familiars contiene le informazioni di ogni allergies paziente sui familiari anamnesis_family_pathol contiene le patologie ogies paziente sui suoi parenti anamnesis_pathologicals contiene le patologie di ogni di ogni paziente (con eventuale ricovero) anamnesis_physiologicals contiene eventuali informazioni su ogni paziente ecgs contiene i dati di ogni ecg fatta events contiene i problemi clinici dei visits, forums, reports pazienti exam_files contiene l’elenco dei file allegati exams contiene l’elenco degli esami exams_users contiene i pazienti da collegare agli visits, exams_users esami o ai problemi clinici forums contiene i messaggi che si possono scambiare i dottori laboratory_exams contiene i dati provenienti dal laboratorio locations contiene indicazioni sulle località di structures, residenza o di nascita Pagina 41 users, Capitolo 2: I portali per la telemedicina anamnesis_pathologica ls elenca le patologie possibili pathologies anamnesis_family_path ologies, anamnesis_pathologica ls contiene i dati generici di ogni tutte e cinque le tabelle patients paziente dell’anamnesi, visits, events contiene i referti fatti dai dottori reports sugli esami dei problemi clinici contiene structures dati sulle strutture patients, users ospedaliere contiene i dati di ogni tipo d’utente patients, users (amministratore, dottore, exams_users, richiedente) events, reports, forums contiene i dati degli esami dei ecgs, visits visits, pazienti exam_files, laboratory_exams Tabella 2.1: Elenco tabelle del database del “MiroOnRails” Dall’analisi delle tabelle del database sono emerse diverse considerazioni: • Alcuni campi non sono stati sfruttati a dovere, rimanendo così inutilizzati (contengono il valore NULL). • Alcune tabelle (quali “ecgs” e “laboratory_exams”) sono superflue all’interno del database poiché, anche se contengono vari campi, non vengono mai utilizzate. • Alcuni campi possono essere tolti comportando, in questo modo, l’eliminazione di alcune tabelle e la semplificazione di alcune query. DATABASE “MEDTEL” In conclusione, le tabelle, utilizzate in “MedTel”, sono state ridotte in termini numerici e il database funzionalmente è stato semplificato. Gli elementi di quest’ultimo sono: • allergies • allergy_categories (non sfruttata ma lasciata comunque) • anamnesis_allergologies Pagina 42 Capitolo 2: I portali per la telemedicina • anamnesis_familiars • anamnesis_family_pathologies • anamnesis_pathologicals • anamnesis_physiologicals • ecgs (non sfruttata ma lasciata comunque) • events • exams • exam_files • exams_users • forums (non sfruttata ma lasciata comunque) • laboratory_exams • pathologies • patients • reports • users • visits Pagina 43 Capitolo 3: Il portale “MedTel”: sezione dottore CAPITOLO 3: Il portale “MedTel”: sezione dottore • figura del dottore nel portale • struttura della sezione • operazioni possibili dal dottore Pagina 44 Capitolo 3: Il portale “MedTel”: sezione dottore 3.1 INTRODUZIONE La sezione del dottore rappresenta uno dei pilastri su cui il portale è stato dapprima pensato e poi realizzato (di fatto il sito non esisterebbe se non ci fosse la possibilità da parte di un dottore registrato di refertare un problema clinico di un paziente e di fare l’upload di files quali immagini di radiografie). Per quanto riguarda l’aspetto realizzativo, questa sezione riprende alcuni aspetti di quella del richiedente come ad esempio le possibilità di accedere alla cartella clinica di un particolare paziente e di vedere, inseriti in una tabella, i vari problemi clinici (ancora non chiusi) relativi alla specializzazione del dottore. Nel complesso, la sezione del dottore è stata pensata per essere molto semplice nell’utilizzo ma anche nella visualizzazione (non per niente c’è sempre un “Help” che aiuta lo specialista ad orientarsi meglio): lo scopo è quello di permettere a qualsiasi utente, indipendentemente dalle sue abilità nell’utilizzo di un computer e nella navigazione nel web, di effettuare il login e, successivamente, di svolgere i compiti a lui adibiti in questo portale. In questo modo un dottore raggiunge il fine di aiutare un gran numero di persone le quali fanno riferimento a strutture sanitarie sparse nel mondo per avere pareri sui propri problemi clinici. Gli obiettivi che si vogliono raggiungere in questa sezione sono i seguenti: • Accesso all’area riservata al dottore mediante login. • Possibilità da parte del dottore di effettuare modifiche del profilo oppure il log-out. • Fornire un Help comprensibile al dottore per orientarsi nel portale. • Possibilità di accedere alla cartella clinica di un paziente, nella quale sono consentite solo refertazioni e messaggi (le modifiche dei dati di quest’ultimo sono di pertinenza del richiedente), qualora sia presente nella tabella “Clinical Problems” dell’area riservata almeno un problema clinico dello stesso. In conclusione, i settori che sono coinvolti dalla sezione del dottore sono: 1) LOGIN E REGISTRAZIONE 2) AREA RISERVATA DEL DOTTORE 3) CARTELLA CLINICA DEL PAZIENTE Pagina 45 Capitolo 3: Il portale “MedTel”: sezione dottore 3.2 LOGIN E REGISTRAZIONE Figura 3.1: Pagina di Login Il login è il primo pannello che viene visualizzato all’accesso al portale: è necessario per un dottore essere stato registrato da un amministratore di secondo livello (il cosiddetto manager) per effettuare l’accesso alla personale area privata. Il portale, per motivi di sicurezza, è stato progettato in modo tale che un utente (quindi anche un dottore) non possa effettuare la registrazione personalmente: poiché un dottore, così come un richiedente, deve essere di competenza di un manager, un nuovo utente deve essere registrato esclusivamente da quest’ultimo. Se per un non specifico motivo il manager di competenza viene cancellato, il controllo sull’utente-dottore verrà passato ad un altro manager oppure, se non ve ne fossero, all’amministratore di primo livello. E’ sempre compito dell’amministratore di competenza cancellare il dottore. La cancellazione di un dottore sarà necessaria se questo ha una nuova specializzazione e vuole aggiornare il suo profilo nel portale (viene fatta una nuova registrazione di conseguenza). Per ottenere username e password per effettuare il login è necessario inviare una e-mail all’amministratore (oppure contattarlo telefonicamente, se possibile), la quale è contenuta nella finestra che si apre al click sull’Help del login, con la richiesta di essere registrati. Pagina 46 Capitolo 3: Il portale “MedTel”: sezione dottore 3.2.1 EFFETTUAZIONE DEL LOGIN Per effettuare il login il dottore deve necessariamente immettere nei due campi presenti nel pannello username e password corrette e cliccare sul pulsante “Login”. Il controllo viene fatto attraverso una semplice query, eseguita con una chiamata asincrona che passa dal client al server username e password, nella tabella “users” presente nel database. Se la query ha successo (viene trovato effettivamente un utente), la chiamata permette di registrare in una variabile di sessione alcuni dati dell’utente (id, username, nome, cognome, e-mail e tipologia d’utente) e restituisce al client solo l’ultimo di questi dati (in questo caso la tipologia sarà “doctor”) sotto forma di stringa. Nel caso la chiamata asincrona del GWT fallisca, viene visualizzata una MessageBox del GWT che maschera la pagina sottostante e segnala la presenza di un errore durante la chiamata. Se, invece, si verifica un’eccezione all’interno del blocco try, la chiamata restituisce comunque una stringa nella quale sono presenti dei valori che, lato client, fanno visualizzare una diversa MessageBox che informa il dottore della presenza di dati inseriti errati (almeno uno tra username e password). public String[] login(String user, String pass) { Database conn = new Database("db_name","username","password"); String utente = new String(); int id = 0; String mail = new String(); String surname = new String(); String name = new String(); String type = new String(); String stype = new String(); conn.connetti(); conn.query("SELECT * FROM users WHERE username=\""+user+"\" AND hashed_password=md5(\""+pass+"\")"); try { conn.getResult().next(); utente = conn.getResult().getString("username"); id = conn.getResult().getInt("id"); mail = conn.getResult().getString("mail"); surname = conn.getResult().getString("surname"); Pagina 47 Capitolo 3: Il portale “MedTel”: sezione dottore name = conn.getResult().getString("name"); type = conn.getResult().getString("type"); stype = conn.getResult().getString("stype"); } catch (Exception e) { return new String[] {"false","-1"}; } if (user.equals(utente)) { UserSession usersession = new UserSession(id,utente,name,surname,mail,type); HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); session.setAttribute("us", usersession); return new String[] {type,stype}; } else { return new String[] {"false","-1"}; } } Listato 3.1: Metodo per il login, lato server (LoginRMImpl.java) In conclusione, esistono tre possibilità dopo aver cliccato su “Login”: 1) Dati mancanti: se almeno un campo non viene riempito, al click sul pulsante “Login” verrà segnalata visivamente la mancanza nell’apposito campo (grazie ad un effetto grafico del GWT) e di conseguenza il login non sarà effettuato fino a quando questo sarà vuoto. Pagina 48 Capitolo 3: Il portale “MedTel”: sezione dottore Figura 3.2: Segnalazione dati mancanti nella pagina di Login 2) Dati errati in almeno uno dei due campi: compare una MessageBox del GWT che maschera la pagina sottostante e segnala la presenza di dati errati in uno o in entrambi i campi. Figura 3.3: Segnalazione dati errati durante il login 3) Dati corretti: il pannello iniziale di login viene rimosso e sostituito con quello che contiene l’area riservata al dottore. Cambia inoltre il tema GWT (dallo standard allo “slate”). Quale area riservata viene aperta e quale tema viene utilizzato dipendono dalla tipologia d’utente che viene restituita dalla chiamata asincrona in caso di successo (nella sezione del dottore è appunto “doctor”). Pagina 49 Capitolo 3: Il portale “MedTel”: sezione dottore 3.3 AREA RISERVATA DEL DOTTORE Figura 3.4: Area riservata del dottore L’area riservata del dottore rappresenta una Home Page per il diretto interessato. In questa è possibile vedere, tra le varie cose, tutti i problemi clinici non chiusi che devono essere ancora refertati, relativi alle specializzazioni con le quali il dottore è stato registrato nel portale. Per eliminare le possibilità di disorientamento da parte dell’utente si può notare il cambiamento nel tema GWT che passa da quello standard (del pannello di login) all’“aero” nel caso del dottore. L’area è composta da un contenitore nel quale sono inseriti: 1) Pannello “HOME” 2) Pannello “CLINICAL PROBLEMS” 3) Toolbar menù Pagina 50 Capitolo 3: Il portale “MedTel”: sezione dottore 3.3.1 PANNELLO “HOME” Figura 3.5: Pannello “Home” “Home” è un pannello relativamente semplice: di fatto contiene solamente un messaggio di benvenuto all’area riservata al dottore spiegando in modo abbastanza chiaro cosa l’utente può fare all’interno della sua Home Page. Lo sfondo e le funzionalità (ovvero la volontà di aiutare colui che accede in quest’area spiegandogli cosa può o non può fare) di questo pannello ricalcano quelle delle altre aree riservate (amministratore e richiedente). 3.3.2 PANNELLO “CLINICAL PROBLEMS” Figura 3.6: Pannello “Clinical Problems” Pagina 51 Capitolo 3: Il portale “MedTel”: sezione dottore Questo pannello rappresenta la parte più importante dell’area riservata perché su ciò si basa l’obiettivo principale del portale: in esso sono contenuti tutti i problemi clinici con esami relativi alle specializzazioni del dottore aventi stato di “open” o “request another”. La grid fornisce una serie di opzioni selezionabili da un menù che compare al momento del click sulla freccia presente nella parte destra di ogni campo: ordinamento ascendente e discendente delle righe per ogni colonna, possibilità di nascondere o di mostrare colonne (spuntando le checkbox), il cui nome è compreso nella lista di quelle disponibili, e di raggruppare le varie righe in relazione ad un campo. Figura 3.7: Proprietà della tabella Cliccando su ogni riga della tabella sarà possibile accedere alla cartella clinica del paziente in questione: all’interno di questa verrà aperto automaticamente il pannello relativo ai “Patient Clinical Problems”, il quale contiene tutti i problemi clinici del paziente (uno di questi, al momento dell’apertura, è selezionato ed è quello che corrisponde alla riga della tabella su cui si era cliccato in precedenza). grid.addGridRowListener(new GridRowListenerAdapter() { public void onRowClick(final GridPanel grid, final int rowIndex, final EventObject e) { Store app= grid.getStore(); //visualizzo la successiva griglia solo se c'è almeno un evento su //questa di partenza if(!(app.getAt(rowIndex).getAsString("id_event").equals("null"))) { //prendo ID del problema, del paziente e il nome di quest’ultimo Pagina 52 Capitolo 3: Il portale “MedTel”: sezione dottore final String id = app.getAt(rowIndex).getAsString("id_event"); final String patient = app.getAt(rowIndex).getAsString("patient"); final String id_patient = app.getAt(rowIndex).getAsString("id_patient"); final ListaPatientRSAsync set = (ListaPatientRSAsync) GWT.create(ListaPatientRS.class); ServiceDefTarget target = (ServiceDefTarget) set; target.setServiceEntryPoint(GWT.getModuleBaseURL() + "ListaPatientRS"); final AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { Window window = new Window(); ClinicalFolder clinicalFolder = new ClinicalFolder(window,tabArea); //passo alla cartella clinica i tre parametri ClinicalFolder.setDataDoc(id, patient, id_patient); clinicalFolder.setProblem("doctor"); window.add(clinicalFolder); } public void onFailure(Throwable caught) { MessageBox.alert(caught.getMessage()+caught.getCause() +caught.getStackTrace()); } }; //controllo tramite RPC se esiste l’utente set.setId(Integer.parseInt(id_patient), callback); } } }); Listato 3.2: Codice per aprire la tabella dei problemi clinici nella cartella clinica, lato client (EventsPatients.java) Pagina 53 Capitolo 3: Il portale “MedTel”: sezione dottore Il pannello, a differenza di quello dell’“Home”, è aggiornabile mediante il semplice meccanismo di rimozione e re-inserimento dello stesso (è stata adottata questa soluzione in quanto, di per sé, il GWT non forniva una soluzione più pratica e semplice per tale scopo): ciò avviene ogni qualvolta si chiuda la cartella clinica di un paziente, poiché, nella maggior parte dei casi, il dottore vi entra per apportare delle modifiche a qualche problema clinico; di conseguenza risulta utile ritrovare, ritornando al pannello “Clinical Problems”, i problemi modificati aggiornati. this.window.addListener(new WindowListenerAdapter() { public void onClose(Panel panel) { String idActive=tabArea.getActiveTab().getId(); tabArea.remove("lastclinical"); ViewEventsRequest env; EventsPatients env1; Panel pan = new Panel(); Panel lastP; pan.setBorder(false); pan.setPaddings(0); pan.setLayout(new HorizontalLayout(0)); if (type.equalsIgnoreCase("requester")){ env = new ViewEventsRequest(tabArea); pan.add(env); lastP = new Panel(); lastP.setTitle("Last Clinical Problem"); } //per il dottore else { env1=new EventsPatients(tabArea); pan.add(env1); lastP = new Panel(); lastP.setTitle("Clinical Problems"); } lastP.setPaddings(0); Pagina 54 Capitolo 3: Il portale “MedTel”: sezione dottore lastP.setId("lastclinical"); lastP.setSize(709, 600); lastP.setAutoScroll(true); lastP.add(pan); tabArea.add(lastP); tabArea.setActiveTab(idActive); } }); Listato 3.3: Codice per aggiornare il pannello “Clinical Problems”, lato client (ClinicalFolder.java) Il contenuto della tabella è ottenuto mediante una chiamata asincrona dal client al server che attiva una query che ricerca, mediante dei join, in varie tabelle del database (“exams_users”, “visits”, “patients” e “events”) tutti i problemi clinici che hanno stato di “open” o “request another” e che hanno esami che si riferiscono alle specializzazioni del dottore loggato. Se la chiamata ha esito positivo restituirà al client un’ArrayList (che contiene dati quali ID, data di creazione e stato del problema clinico, nome e cognome del paziente, di cui si salva anche l’ID, e del richiedente). La tabella, di conseguenza, verrà riempita con le informazioni presenti nell’ArrayList. Nel caso in cui la chiamata fallisse verrà segnalato uno dei seguenti errori: • Messaggio che indica l’entità dell’eccezione nel caso questa si verifichi all’interno del blocco try, lato server. • MessageBox di GWT che segnala il verificarsi di un errore durante la chiamata asincrona, lato client. Se il risultato della query è vuoto (nessun problema da poter refertare per il dottore) verrà comunque salvato nell’ArrayList un insieme di dati (otto come quando l’esito della ricerca nel database è positivo), che in questo caso saranno tutti nulli: come risultato di questa operazione, nella tabella comparirà una riga vuota che non aprirà nessuna finestra quando verrà cliccata. public ArrayList view_user() { Database conn = new Database("db_name","username","password"); String id_events = new String(); String created_at = new String(); Pagina 55 Capitolo 3: Il portale “MedTel”: sezione dottore String state = new String(); String patient = new String(); String id_patient = new String(); String requester = new String(); ArrayList table_users = new ArrayList(); HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); UserSession usersession = (UserSession)session.getAttribute("us"); int myID = usersession.getId(); conn.connetti(); String query = "SELECT * from exams_users inner join (exams inner join (visits inner join (patients inner join (users inner join events on users.id=events.user_id) on patients.id = events.patient_id) on visits.event_id=events.id) on exams.id=visits.exam_id) on exams.id=exams_users.exam_id where exams_users.user_id="+myID+" and (events.state='open' or events.state='request another') group by(events.id)"; conn.query(query); try { int length=0, i=0; if (!conn.getResult().next()) { table_users.add(new ArrayList()); ((ArrayList)table_users.get(0)).add(""); ((ArrayList)table_users.get(0)).add(""); ((ArrayList)table_users.get(0)).add(""); ((ArrayList)table_users.get(0)).add(""); ((ArrayList)table_users.get(0)).add(""); ((ArrayList)table_users.get(0)).add(""); return table_users; Pagina 56 Capitolo 3: Il portale “MedTel”: sezione dottore } else { do { table_users.add(new ArrayList()); id_events = conn.getResult().getString("events.id"); created_at = conn.getResult().getDate("events.created_at").toString(); state = conn.getResult().getString("events.state"); patient = conn.getResult().getString("patients.name")+" "+ conn.getResult().getString("patients.surname"); requester = conn.getResult().getString("users.name")+" "+ conn.getResult().getString("users.surname"); id_patient = conn.getResult().getString("patients.id"); ((ArrayList)table_users.get(i)).add(id_events.toString()); ((ArrayList)table_users.get(i)).add(created_at.toString()); ((ArrayList)table_users.get(i)).add(state.toString()); ((ArrayList)table_users.get(i)).add(patient.toString()); ((ArrayList)table_users.get(i)).add(requester.toString()); ((ArrayList)table_users.get(i)).add(id_patient.toString()); i++; } while(conn.getResult().next()); } } catch (Exception e) { System.out.println(e.getCause()+e.getMessage()); return null; } finally{ conn.closeConn(); } Pagina 57 Capitolo 3: Il portale “MedTel”: sezione dottore return table_users; } Listato 3.4: Metodo per caricare la tabella, lato server (EventsPatientRSImpl.java) 3.3.3 TOOLBAR MENÙ Figura 3.8: Toolbar Menù La Toolbar è una barra sempre presente nel contenitore (a differenza dei pannelli che si alternano). La struttura è uguale anche per le aree riservate dell’amministratore e del richiedente: infatti, per tutte e tre le sezioni, sono presenti due bottoni, uno per l’Help (che apre una finestra che contiene informazioni molto utili per chi non riesce ad orientarsi al meglio nell’area riservata) mentre l’altro è un menù a tendina con due elementi che sono: • PROFILE (profilo): cliccando su questo elemento viene aperta una finestra in primo piano che permette di modificare o aggiungere vari dati del dottore, alcuni obbligatori (tra cui nome, cognome e username i quali non sono modificabili) altri invece facoltativi. Il caricamento di queste informazioni avviene tramite una chiamata asincrona che ricerca nella tabella “users” il dottore, tramite il relativo ID prelevato dalla variabile di sessione, e salva questi dati in un’ArrayList da cui vengono prelevati, lato client, per riempire i vari campi. Nel caso il metodo, lato server, generasse qualche eccezione nel blocco try, questa verrà poi segnalata mediante una MessageBox del GWT all’utente così come quando la chiamata fallisce. public ArrayList view() { HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); UserSession currentPatient = (UserSession) Pagina 58 Capitolo 3: Il portale “MedTel”: sezione dottore session.getAttribute("us"); String user=currentPatient.getUser(); ArrayList result=new ArrayList(); Database conn = new Database("db_name","username","password"); conn.connetti(); String query = "SELECT * FROM users where username='"+user+"'"; try { conn.query(query); conn.getResult().first(); result.add(user); result.add(conn.getResult().getString("name")); result.add(conn.getResult().getString("surname")); result.add(conn.getResult().getString("mail")); result.add(conn.getResult().getString("location")); result.add(conn.getResult().getString("address")); result.add(conn.getResult().getString("cap")); result.add(conn.getResult().getString("state")); result.add(conn.getResult().getString("telephone_number")); result.add(conn.getResult().getString("fax")); } catch (Exception e) { System.out.println("eeee2222"+e.getMessage()+e.getCause() +e.getStackTrace()); String mess="errore: "; mess+="\n\nLOG DATABASE: "+conn.getLog(); System.out.println(mess); String [] error={mess}; ArrayList ret_err= new ArrayList(); for (int i=0;i<=error.length;i++) ret_err.add(i, error[i]); return ret_err; } Pagina 59 Capitolo 3: Il portale “MedTel”: sezione dottore finally{ conn.closeConn(); } return result; } Listato 3.5: Metodo per caricare i dati, lato server (ModRegistrationRSImpl.java) Per salvare i dati modificati l’utente deve cliccare sul pulsante “Save” e confermare successivamente la scelta premendo su “Sì” nella finestra che comparirà: quindi verrà effettuata una chiamata asincrona che aggiorna, in caso di successo, i dati della riga della tabella “users” corrispondente a quel dottore (ciò avviene confrontando il numero nel campo “id” della tabella con quello della sessione precedentemente salvato in una variabile al momento del login). In caso contrario verranno segnalati tramite MessageBox gli eventuali errori, che siano lato server o client. public boolean boolean modify(String pwd, String String location, String address, String cap, String state, String tel, String mail, String fax){ HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); UserSession currentPatient = (UserSession) session.getAttribute("us"); int id=currentPatient.getId(); Database conn = new Database("db_name","username","password"); conn.connetti(); String query="UPDATE users SET hashed_password= md5('"+pwd+"'), location= '"+location+"', address= '"+address+"', cap= '"+cap+"', state= '"+state+"', telephone_number= '"+tel+"', mail= '"+mail+"', fax= '"+fax+"' WHERE id="+id; try{ conn.insert(query); Pagina 60 Capitolo 3: Il portale “MedTel”: sezione dottore } catch (Exception e) { System.out.println("Eccezione: "+e.getMessage()); return false; } finally{ conn.closeConn(); } return true; } Listato 3.6: Metodo che salva le modifiche, lato server (ModRegistrationRSImpl.java) • LOGOUT: cliccando su questo elemento viene invalidata la sessione e distrutta la variabile relativa (per questioni di sicurezza). Una volta compiute queste operazioni, mentre compare una maschera che segnala il log-out, viene ricaricata la pagina che riproporrà il pannello iniziale del login. Se si dovessero verificare degli errori durante la chiamata asincrona, questi verranno segnalati mediante una MessageBox del GWT, impedendo in questo modo il log-out al dottore. public boolean logout(){ HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); session.removeAttribute("us"); session.invalidate(); return true; } Listato 3.7: Metodo per effettuare il log-out, lato server (UserAreaRSImpl.java) Il menù a tendina presenta una caratteristica particolare: al momento del caricamento dell’area riservata vengono presi dalla variabile di sessione nome e cognome mediante una chiamata asincrona che restituisce una stringa con i due dati, i quali vengono poi stampati nel bottone del menù. Nel caso si verificassero degli errori durante l’operazione, questi Pagina 61 Capitolo 3: Il portale “MedTel”: sezione dottore verranno segnalati mediante una MessageBox del GWT e di conseguenza il bottone non conterrà nessun dato. public String load() { HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); UserSession currentUser=(UserSession) session.getAttribute("us"); String userfullname = currentUser.getName()+" "+currentUser.getSurname(); return userfullname; } Listato 3.8: Metodo per caricare dati nel menù a tendina, lato server (UserAreaRSImpl.java) Pagina 62 Capitolo 3: Il portale “MedTel”: sezione dottore 3.4 CARTELLA CLINICA DEL PAZIENTE Figura 3.9: Cartella clinica del paziente (vista dal dottore) La cartella clinica del paziente, che il dottore può consultare, è il fulcro del portale: in questa, infatti, sono possibili le operazioni di refertazione e di messaggistica: referti e messaggi sono così consultabili sia da altri specialisti ma anche dai richiedenti (ad esempio, a differenza del vecchio portale “Miro On Rails”, i messaggi possono essere visti anche dalle strutture sanitarie perché lo specialista potrebbe richiedere maggiori informazioni riguardo ad un paziente per effettuare un referto corretto). A differenza del richiedente, il dottore può solo visualizzare i dati del paziente senza avere perciò la possibilità di modificane, di cancellarne o di aggiungerne alcuni. La scelta relativa alle operazioni possibili che un dottore può eseguire nella cartella clinica è dovuta a questioni funzionali: infatti, sarebbe inutile fornire all’utente cose di cui può fare benissimo a meno (non essendo in contatto con il paziente, se non tramite il meccanismo di refertazione, non è in grado ad esempio di aggiungere nuovi problemi clinici o di modificare aspetti dell’anamnesi). Il dottore è e deve essere interessato solamente a refertare gli esami del paziente e a scambiare messaggi per aiutare colleghi o per avere chiarimenti o consigli. Pagina 63 Capitolo 3: Il portale “MedTel”: sezione dottore […] //RPC che viene attivata al caricamento della cartella clinica per inserire //nome e cognome del paziente nel titolo del menù a sinistra ClinicalFolderRSAsync view = (ClinicalFolderRSAsync) GWT.create(ClinicalFolderRS.class); ServiceDefTarget endpoint = (ServiceDefTarget) view; endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "ClinicalFolderRS"); AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { ArrayList values=(ArrayList) result; treePanel.setTitle("Patient: "+values.get(0).toString().toUpperCase()); type=values.get(1).toString(); if (!type.equalsIgnoreCase("requester")) tabPatientProfile.getTopToolbar().destroy(); } public void onFailure(Throwable caught) { System.out.println("errore nella view"); } }; view.view(callback); […] // per aggiungere la toolbar ogni volta che si apre un nuovo pannello Toolbar toolbar=createToolbar(); if (type.equalsIgnoreCase("requester")) tab.setTopToolbar(toolbar); […] Listato 3.9: Codici per costruire la cartella clinica, lato client (ClinicalFolder.java) Pagina 64 Capitolo 3: Il portale “MedTel”: sezione dottore 3.4.1 ASPETTI GENERALI La cartella clinica è divisa in due parti: una, a sinistra, che contiene l’albero che funge da menù, l’altra, a destra, destinata ad ospitare il contenuto di ogni pannello che si apre. Anche qui, così come nell’area riservata, è presente un Help che aiuta l’utente a comprendere meglio come orientarsi nella finestra in considerazione. In questa finestra sono presenti, inoltre, dei link a delle pagine HTML in cui viene spiegata dettagliatamente, anche mediante l’impiego di screenshots, la cartella clinica del paziente. Oltre al bottone dell’Help ne sono presenti altri: • REFRESH: per il menù, serve ad aggiornare manualmente il pannello che contiene l’albero nel caso non si ricaricasse automaticamente. • COLLAPSIBLE: per il menù, serve a nascondere il pannello che contiene l’albero a sinistra in modo da espandere quello di destra; sarà possibile riaprirlo in maniera definitiva cliccando sullo stesso pulsante, sempre presente, oppure temporaneamente cliccando sulla barra verticale che rimane visibile a sinistra quando il pannello viene nascosto. L’albero-menù è diviso in tre parti (rami) consultabili da parte del dottore: PATIENT PROFILE ANAMNESIS PATIENT CLINICAL PROBLEMS Figura 3.10: Struttura del menù organizzato ad albero Pagina 65 Capitolo 3: Il portale “MedTel”: sezione dottore 3.4.2 PROFILO PAZIENTE Figura 3.11: Pannello “Patient Profile” Cliccando su questo ramo si aprirà un pannello che contiene i dati relativi al paziente il cui nome e cognome sono scritti nella barra sopra l’albero (queste due informazioni sono ottenute mediante una chiamata asincrona da client a server). Al dottore non è permesso modificare tali dati che rimangono perciò esclusivamente consultabili. Lo sfondo del pannello che viene aperto è verde e contiene la stessa icona che si trova accanto al ramo “Patient Profile” dell’albero. 3.4.3 ANAMNESI Cliccando su questo ramo si aprirà un sotto-albero (asincrono) che contiene cinque elementi: • Allergologies: al click su questo elemento verrà aperto un pannello che informa il dottore se sono presenti eventuali sotto-elementi e quanti questi sono: cliccando su uno di essi sarà possibile visualizzare i dati di quella particolare allergia (tipo, data di inizio e di fine e annotazioni particolari). • Familiars: al click su questo elemento verrà aperto un pannello che informa il dottore se sono presenti i dati relativi ai genitori del paziente: in caso positivo questi potranno essere visualizzati nello stesso pannello (madre e padre vivi o no, gruppo sanguigno dei due e annotazioni particolari). Pagina 66 Capitolo 3: Il portale “MedTel”: sezione dottore • Family Pathologies: al click su questo elemento verrà aperto un pannello che informa il dottore se sono presenti eventuali sotto-elementi e quanti questi sono: cliccando su uno di essi sarà possibile visualizzare i dati di quella particolare malattia (tipo e quali parenti sono ammalati). • Pathologicals: al click su questo elemento verrà aperto un pannello che informa il dottore se sono presenti eventuali sotto-elementi e quanti questi sono: cliccando su uno di essi sarà possibile visualizzare i dati di quella particolare malattia (tipo, in quale età la si è contratta e altre informazioni relative ad un eventuale ricovero in ospedale). • Physiological: al click su questo elemento verrà aperto un pannello che informa il dottore se sono presenti ulteriori dati relativi al paziente in questione: in caso positivo questi potranno essere visualizzati nello stesso pannello (annotazioni varie e gruppo sanguigno del paziente e del o della partner). Al dottore non è permesso modificare tali dati che rimangono perciò esclusivamente consultabili. Lo sfondo del pannello che viene aperto è azzurro e contiene una diversa icona a seconda se viene cliccato un elemento o un sotto-elemento del ramo “Anamnesis” dell’albero. 3.4.4 PROBLEMI CLINICI DEL PAZIENTE Figura 3.12: Pannello “Patient Clinical Problems” Pagina 67 Capitolo 3: Il portale “MedTel”: sezione dottore Questa è la parte verso la quale il dottore è più interessato poiché rappresenta la zona in cui lo stesso dottore può scrivere referti o messaggi. Cliccando su questo ramo verrà aperto il pannello relativo che contiene la tabella con tutti i problemi clinici del paziente e i bottoni con diverse funzionalità. Lo sfondo è rosso. Il pannello si apre automaticamente al momento dell’accesso da parte del dottore nella cartella clinica (realizzato mediante una clausola “if” che controlla il tipo d’utente); inoltre, sarà selezionata la riga corrispondente al problema clinico precedentemente cliccato dall’utente-dottore nella tabella del pannello “Clinical Problems” dell’area riservata. int activeRow = -1; public int stop_collapse = 1; […] viewP.addListener(new PanelListenerAdapter() { public void onCollapse(final Panel panel) { if(stop_collapse==1) { int cont=0; while(!(grid.getStore().getAt(cont).getAsString("id_event"). equals(id_event) )) { cont++; } grid.getSelectionModel().selectRow(cont); activeRow = cont; //“dv” è di tipo “DetailsVisit”: permette di selezionare // gli esami del problema clinico dv.getProblem(Integer.parseInt(id_event)); viewP.setCollapsed(false); //è il pannello stop_collapse=0; } } }); Listato 3.10: Codice per aprire il pannello con la riga pre-selezionata, lato client (ViewVisitsEvent.java) Pagina 68 Capitolo 3: Il portale “MedTel”: sezione dottore La tabella è organizzata in gruppi in base allo stato (aperto, chiuso, refertato, altra richiesta) dei problemi clinici: in questo modo il dottore potrà concentrarsi solamente verso alcuni elementi, evitando di doverli passare in rassegna tutti. I problemi clinici dello stesso gruppo sono in ordine cronologico, dal più vecchio al più recente, in modo tale da invitare il dottore a rispondere a quelli che sono ancora aperti dopo molto tempo. E’ possibile vedere, inoltre, il numero di esami, di messaggi e di referti di ogni problema clinico (ognuno ha una sua colonna). La scelta di mostrare tutti i problemi clinici al dottore, a prescindere dalle sue specializzazioni, nella cartella clinica è voluta per aiutare lo stesso medico in quanto potrebbe trarre vantaggio dalle consultazioni relative ad altri esami, che non riguardano il proprio campo, per dei referti (nell’area riservata ciò non è applicato perché sarebbe inutile e contro le logiche del portale). Messaggio e referto, a livello di database, sono salvati nella stessa tabella (“reports”) ma si differenziano per l’utilizzo del campo “type” che assume il valore “message” nel primo caso e “report” nel secondo. Ogni qualvolta una riga viene evidenziata, dopo essere stata cliccata, i bottoni, che si trovano al di sotto della tabella, eseguiranno le varie funzioni in relazione a quel determinato problema clinico. Nel caso in cui nessuna riga sia selezionata, nel momento in cui un bottone viene cliccato, verrà visualizzata una finestra che invita a selezionare un elemento della tabella. I bottoni che il dottore può cliccare sono cinque: • “New Message”: apre una finestra in cui sono presenti tre campi di cui due non modificabili (destinatario del messaggio e informazioni sul problema clinico) mentre il terzo ospita il contenuto del messaggio. L’operazione è possibile solo se il problema è in stato di “open” o “request another”. • “Add Report”: apre una finestra in cui sono presenti tre campi di cui due non modificabili (destinatario del referto e informazioni sul problema clinico) mentre il terzo ospita il contenuto del referto. L’operazione è possibile solo se il problema è in stato di “open” o “request another”. • “View Messages”: apre una finestra che contiene diversi pannelli ridimensionabili, ognuno dedicato ad un diverso messaggio; ogni singolo pannello è diviso in due parti: la prima contiene il corpo del messaggio con l’indicazione di quando è stato scritto, mentre la seconda viene riservata ad alcuni dati del dottore che l’ha inviato (nome, e-mail, ospedale di riferimento e informazioni aggiuntive). Se non ci sono Pagina 69 Capitolo 3: Il portale “MedTel”: sezione dottore messaggi relativi a quel determinato problema clinico verrà visualizzata una finestra che segnala, appunto, l’assenza di questi. Nel caso il problema clinico sia settato come “close” non sarà possibile vedere alcun messaggio (la finestra sarà vuota). • “View Reports”: apre una finestra che contiene diversi pannelli ridimensionabili, ognuno dedicato ad un diverso referto; ogni singolo pannello è diviso in due parti: la prima contiene il corpo del referto con l’indicazione di quando è stato scritto, mentre la seconda viene riservata ad alcuni dati del dottore che l’ha inviato (nome, e-mail, ospedale di riferimento e informazioni aggiuntive). Se non ci sono referti relativi a quel determinato problema clinico verrà visualizzata una finestra che segnala, appunto, l’assenza di questi. Nel caso il problema clinico sia settato come “close” non sarà possibile vedere alcun referto (la finestra sarà vuota). • “View Details Clinical Problem”: è la parte principale e più interessante del ramo “Patient Clinical Problems” in quanto nel pannello, che si apre al di sotto della tabella, sono contenuti tutti i dati di un particolare esame del problema clinico (selezionabile mediante l’apposita Combo Box) con la possibilità di scaricare dalla lista eventuali file correlati. Oltre alla scelta dell’esame il dottore può vedere lo stato del problema clinico, la data di apertura e quella dell’eventuale chiusura. Pagina 70 Capitolo 3: Il portale “MedTel”: sezione dottore BOTTONE “NEW MESSAGE” Figura 3.13: Finestra aperta cliccando sul bottone “New Message” Questo bottone realizza la funzione descritta in precedenza mediante una chiamata asincrona da client a server che viene attivata al momento del click sul pulsante “Send” e che permette di inserire nella tabella “reports” del database (dopo aver selezionato dalla tabella “events”, che contiene tutti i problemi clinici, l’ID relativo a quella determinata segnalazione) il messaggio assieme all’indicazione della data e dell’ora in cui questo viene salvato. Se la chiamata ha successo verrà comunicato al dottore l’esito positivo dell’inserimento (mediante una MessageBox del GWT) e successivamente verrà ricaricata la tabella del pannello “Patient Clinical Problems” della cartella clinica. In caso contrario, verranno visualizzati diversi messaggi a seconda dei casi: • Il campo relativo al contenuto del messaggio è vuoto, dopo aver cliccato sul pulsante “Sì” della finestra di conferma che compare dopo aver premuto il pulsante “Send”. L’inserimento fallisce e non viene attivata la chiamata asincrona. • Il campo relativo al contenuto del messaggio è pieno ma si clicca sul pulsante “No” della finestra di conferma che compare dopo aver premuto il pulsante “Send”. L’inserimento non viene fatto così come la chiamata asincrona. • Viene generata un’eccezione generica lato server all’interno del blocco try e il metodo chiamato dal client restituisce il valore booleano “false”, comportando, di conseguenza, l’apertura di una MessageBox, che segnala un errore verificatosi nella parte server durante la chiamata asincrona, e la chiusura successiva della finestra di inserimento del referto. Pagina 71 Capitolo 3: Il portale “MedTel”: sezione dottore Se viene premuto il pulsante “Cancel” non viene attivata nessuna procedura di inserimento e la finestra viene chiusa, comportando perciò la cancellazione dell’eventuale contenuto del campo del messaggio. BOTTONE “ADD REPORT” Figura 3.14: Finestra aperta cliccando sul bottone “Add Report” Questo bottone realizza la funzione descritta in precedenza mediante una chiamata asincrona da client a server che viene attivata al momento del click sul pulsante “Send” e che permette di inserire nella tabella “reports” del database (dopo aver selezionato dalla tabella “events”, che contiene tutti i problemi clinici, l’ID relativo a quella determinata segnalazione) il referto assieme all’indicazione della data e dell’ora in cui questo viene salvato. Inoltre, verrà aggiornata la tabella “events” settando lo stato del problema clinico in considerazione (rintracciabile mediante lo stesso ID usato per la SELECT precedente) da “open” o “request another” a “reported”. Se la chiamata ha successo verrà comunicato al dottore l’esito positivo dell’inserimento (mediante una MessageBox del GWT) e successivamente verrà ricaricata la tabella del pannello “Patient Clinical Problems” della cartella clinica. In caso contrario, verranno visualizzati diversi messaggi a seconda dei casi: • Il campo relativo al contenuto del referto è vuoto, dopo aver cliccato sul pulsante “Sì” della finestra di conferma che compare dopo aver premuto il pulsante “Send”. L’inserimento fallisce e non viene attivata la chiamata asincrona. Pagina 72 Capitolo 3: Il portale “MedTel”: sezione dottore • Il campo relativo al contenuto del messaggio è pieno ma si clicca sul pulsante “No” della finestra di conferma che compare dopo aver premuto il pulsante “Send”. L’inserimento non viene fatto così come la chiamata asincrona. • Viene generata un’eccezione generica lato server all’interno del blocco try e il metodo chiamato dal client restituisce il valore booleano “false”, comportando, di conseguenza, l’apertura di una MessageBox, che segnala un errore verificatosi nella parte server durante la chiamata asincrona, e la chiusura successiva della finestra di inserimento del referto. Se viene premuto il pulsante “Cancel” non viene attivata nessuna procedura di inserimento e la finestra viene chiusa, comportando perciò la cancellazione dell’eventuale contenuto del campo del messaggio. public boolean insert_Msg(String id_event, String textArea, String type) { Database conn = new Database("db_name","username","password"); String query ="INSERT into reports(event_id,user_id,body,created_at,type) values(\""+id_event+"\",\""+myID+"\",\""+textArea+"\",NOW(),\""+type+"\");"; conn.connetti(); try { HttpServletRequest request = this.getThreadLocalRequest(); HttpSession session = request.getSession(); UserSession usersession = (UserSession)session.getAttribute("us"); int myID = usersession.getId(); conn.insert(query); if(type.equals("report")) { query = "UPDATE events SET state = 'reported' WHERE events.id ="+id_event; conn.insert(query); } } catch(Exception e) { System.out.println(e.getMessage()); return false; } Pagina 73 Capitolo 3: Il portale “MedTel”: sezione dottore finally { conn.closeConn(); } return true; } Listato 3.11: Metodo per salvare nuovi report o messaggi, lato server (Message_ReportRSImpl.java) BOTTONE “VIEW MESSAGES” Figura 3.15: Finestra aperta cliccando sul bottone “View Messages” Questo bottone realizza la funzione descritta in precedenza mediante una chiamata asincrona da client a server la quale carica all’interno della nuova finestra che viene aperta tanti pannelli quanti sono i messaggi salvati nella tabella “reports” per quel determinato problema clinico: se, ad esempio, non ce ne sono, comparirà una MessageBox del GWT che segnala l’assenza di questi (il controllo del numero di messaggi viene fatto sul relativo campo della tabella presente nel pannello “Patient Clinical Problems” della cartella clinica del paziente). Il metodo della chiamata asincrona, in caso di successo, tramite un join su più tabelle del database (“reports” e “user”), permette di ottenere alcune informazioni sul dottore (nome, cognome, indirizzo e e-mail) e sul messaggio (ID, data di creazione e contenuto): queste vengono salvate in un array multidimensionale sfruttato lato client per comporre il titolo di Pagina 74 Capitolo 3: Il portale “MedTel”: sezione dottore ogni pannello, il testo del messaggio da visualizzare e il profilo del dottore che lo ha scritto. Nel caso venisse generata un’eccezione generica lato server all’interno del blocco try, verrà aperta una MessageBox che segnala un errore verificatosi nella parte server durante la chiamata asincrona. BOTTONE “VIEW REPORTS” Figura 3.16: Finestra aperta cliccando sul bottone “View Reports” Questo bottone realizza la funzione descritta in precedenza mediante una chiamata asincrona da client a server la quale carica all’interno della nuova finestra che viene aperta tanti pannelli quanti sono i referti salvati nella tabella “reports” per quel determinato problema clinico: se, ad esempio, non ce ne sono, comparirà una MessageBox del GWT che segnala l’assenza di questi (il controllo del numero di referti viene fatto sul relativo campo della tabella presente nel pannello “Patient Clinical Problems” della cartella clinica del paziente). Il metodo della chiamata asincrona, in caso di successo, tramite un join su più tabelle del database (“reports” e “user”), permette di ottenere alcune informazioni sul dottore (nome, cognome, indirizzo e e-mail) e sul referto (ID, data di creazione e contenuto): queste vengono salvate in un array multidimensionale sfruttato lato client per comporre il titolo di ogni pannello, il testo del referto da visualizzare e il profilo del dottore che lo ha scritto. Nel caso venisse generata un’eccezione generica lato server all’interno del blocco try, verrà aperta una MessageBox che segnala un errore verificatosi nella parte server durante la chiamata asincrona. Pagina 75 Capitolo 3: Il portale “MedTel”: sezione dottore public String [][] view_msg_report(String id_event, String type_view){ type_view){ String user_id = new String(); String body = new String(); String created_at = new String(); int rows = 0; String[][] dati = new String[20][8]; Database db = new Database("db_name","username","password"); db.connetti(); try { db.query("SELECT * FROM reports inner join users on reports.user_id =users.id where event_id="+id_event+" and reports.type = '"+type_view+"' order by reports.created_at DESC"); while (db.getResult().next()) { rows++; } dati = new String[rows][8]; db.getResult().beforeFirst(); int i = 0; while(db.getResult().next()) { String full_address=new String(); full_address = db.getResult().getString("users.location") + " "+db.getResult().getString("users.cap") + " " + db.getResult().getString("users.state"); dati[i] = new String[]{ db.getResult().getString("reports.id"), db.getResult().getString("reports.created_at"), db.getResult().getString("users.name"), db.getResult().getString("users.surname"), db.getResult().getString("users.structure"), full_address, db.getResult().getString("users.mail"), db.getResult().getString("reports.body")}; i++; Pagina 76 Capitolo 3: Il portale “MedTel”: sezione dottore } } catch(Exception e) { System.out.print(e.getMessage()); } finally { db.closeConn(); } return dati; } Listato 3.12: Metodo per salvare vedere report o messaggi, lato server (View_msg_reportRSImpl.java) BOTTONE “VIEW DETAILS CLINICAL PROBLEM” Figura 3.17: Finestra aperta cliccando sul bottone “View Details Clinical Problem” Questo bottone realizza la funzione descritta in precedenza mediante una chiamata asincrona da client a server la quale carica nel pannello, posto sotto la tabella dei problemi clinici, i dati relativi ad un particolare esame. Inizialmente il pannello presenta solo gli Pagina 77 Capitolo 3: Il portale “MedTel”: sezione dottore aspetti generali della segnalazione selezionata (stato del problema clinico, data di apertura e dell’eventuale chiusura). Il metodo, utilizzato per caricare le informazioni del problema clinico nel pannello, esegue, lato server, due query: la prima serve a ricercare nella tabella “events” del database il problema clinico stesso (utilizzando l’ID relativo che viene passato come parametro del metodo), salvando in un ArrayList alcuni dati (stato, data di apertura e dell’eventuale chiusura), mentre la seconda effettua un join tra le tabelle “visits” e “exams” che permette di identificare gli esami che si riferiscono al problema clinico selezionato (mediante ID, nome e data di creazione) i quali verranno anch’essi salvati nell’ArrayList. Se la chiamata asincrona ha successo, oltre ai dati nel pannello, saranno inseriti nella Combo Box sottostante tutti gli esami trovati con la seconda query (ne sarà presente almeno uno poiché necessario per l’esistenza del problema clinico). In caso contrario verranno visualizzati messaggi d’errore a seconda dei casi: • Messaggio che indica l’entità dell’eccezione nel caso questa si verifichi all’interno del blocco try, lato server. • MessageBox di GWT che segnala il verificarsi di un errore durante la chiamata asincrona, lato client. public ArrayList getData(int id) { ArrayList data = new ArrayList(); String query; Database conn = new Database("db_name","username","password"); conn.connetti(); try { query = "SELECT * FROM events WHERE id="+id; conn.query(query); conn.getResult().next(); String open = conn.getResult().getString("created_at"); String closed = conn.getResult().getString("closed_at"); String status = conn.getResult().getString("state"); data.add(open); data.add(closed); data.add(status); Pagina 78 Capitolo 3: Il portale “MedTel”: sezione dottore query = "SELECT * FROM visits JOIN exams ON visits.exam_id= exams.id WHERE event_id="+id; conn.query(query); while (conn.getResult().next()) { String stringa = new String(); stringa += conn.getResult().getString("visits.id")+ "#"; stringa += conn.getResult().getString("exams.name")+"#"; stringa += conn.getResult().getString("visit_date")+"#"; data.add(stringa); } } catch(Exception e) { System.out.println(e.getMessage()); } return data; } Listato 3.13: Metodo per caricare dati nel pannello, lato server (DetailsVisitRSImpl.java) La Combo Box sotto questi dati presenta la lista degli esami che si riferiscono al problema clinico preso in considerazione: scegliendone uno tra questi verrà attivata una nuova chiamata asincrona che ricerca i dati nella tabella “events” del database e li carica nel pannello che viene aperto sotto la Combo Box e che contiene anche una lista dei file allegati che si possono scaricare. Il metodo, utilizzato per caricare le informazioni dell’esame, dopo essere stato selezionato, esegue, lato server, una semplice query che ricerca nella tabella “visits” del database i dati (utilizzando l’ID relativo che viene passato come parametro del metodo): questi verranno poi salvati in un array di tipo stringa e utilizzati successivamente, in caso di successo, per riempire i campi del pannello che ha come titolo il nome dell’esame. Nel caso si verificassero degli errori durante la chiamata si possono avere delle segnalazioni diverse: • Messaggio che indica l’entità dell’eccezione nel caso questa si verifichi all’interno del blocco try, lato server. • MessageBox di GWT che segnala il verificarsi di un errore durante la chiamata asincrona, lato client. Pagina 79 Capitolo 3: Il portale “MedTel”: sezione dottore public String[] getExam(int id) { String[] result = new String[8]; String query; Database db = new Database("db_name","username","password"); db.connetti(); try { query = "SELECT * FROM visits WHERE id="+id; db.query(query); db.getResult().next(); result[0] = db.getResult().getString("symptoms"); result[1] = db.getResult().getString("weight"); result[2] = db.getResult().getString("height"); result[3] = db.getResult().getString("least_arterial_pressure"); result[4] = db.getResult().getString("maximal_arterial_pressure"); result[5] = db.getResult().getString("cardiac_frequency"); result[6] = db.getResult().getString("conclusions"); result[7] = db.getResult().getString("target_exam"); } catch (Exception e) { System.out.println(e.getMessage()); } return result; } Listato 3.14: Metodo per caricare dati di un esame, lato server (DetailsVisitRSImpl.java) Per poter scaricare i file allegati è necessario selezionarli dall’apposita Combo Box: una volta fatta questa operazione sarà possibile prenderli dal server e salvarli nel proprio computer. La lista dei file viene riempita mediante una chiamata asincrona che viene attivata al momento del caricamento dei dati dell’esame nel pannello: il metodo coinvolto permette di selezionare, tramite query, i nomi degli allegati relativi e di inserirli in un array bidimensionale di tipo stringa. Se la chiamata ha esito positivo gli elementi dell’array Pagina 80 Capitolo 3: Il portale “MedTel”: sezione dottore verranno inseriti nella Combo Box altrimenti si verificheranno diversi messaggi d’errore a seconda dei casi: • Messaggio che indica l’entità dell’eccezione nel caso questa si verifichi all’interno del blocco try, lato server. • MessageBox di GWT che segnala il verificarsi di un errore durante la chiamata asincrona, lato client. public String[][] attachs(int id){ String[][] dati = new String[100][2]; Database db = new Database("db_name","username","password"); db.connetti(); try { int i = 0; int rows = 0; String query = "SELECT * FROM exams_files WHERE visit_id="+id; db.query(query); while (db.getResult().next()) { rows++; } dati = new String[rows][2]; db.getResult().beforeFirst(); while (db.getResult().next()) { dati[i] = new String[]{db.getResult().getString("filename"), db.getResult().getString("name")}; i++; } } catch (Exception e) { System.out.println(e.getMessage()); } Pagina 81 Capitolo 3: Il portale “MedTel”: sezione dottore return dati; } Listato 3.15: Metodo per caricare la lista dei file, lato server (DetailsVisitRSImpl.java) Pagina 82 Capitolo 4: Conclusioni CAPITOLO 4: Conclusioni • impressioni iniziali • valutazioni personali • considerazioni sul futuro Pagina 83 Capitolo 4: Conclusioni 4.1 ASPETTI GENERALI Al momento della scelta del tirocinio, l’aspetto fondamentale che mi ha convinto è stato la possibilità effettiva di aiutare chi, come gran parte degli africani, non può permettersi di avere una consultazione medica adeguata. Con il passare del tempo mi sono sempre più reso conto che questo portale potrebbe rappresentare una vera e propria rivoluzione a livello mondiale: al di là della realizzazione e del modo in cui è stato ideato e strutturato, è il concetto di tele-refertazione globale che dovrebbe permettere una futura diffusione del portale. Il progetto “MedTel” rappresenta solo un semplice “prototipo” di ciò che potrebbe diventare più in là nel tempo: sicuramente verranno sviluppate nuove funzionalità nel GWT, se questo sarà apprezzato dai programmatori, e sarà necessario estendere quelle del portale stesso nel caso, come probabile, il richiedente, per conto dei pazienti, o il dottore avessero bisogno di ulteriori strumenti per nuovi fini. Nel futuro si potrebbe pensare di migliorare la sicurezza del sito, non tanto per i due utenti principali del portale (richiedente e dottore) ma, più che altro, per i diversi livelli di amministrazione (discorso esteso anche per la gestione degli utenti). A mio parere è questo aspetto a dover essere ottimizzato più celermente proprio perché si sta parlando di un portale globale. Per quanto riguarda la grafica, il GWT è un buono strumento per realizzare apprezzabili portali web: durante il tirocinio si è tenuto in particolare considerazione quest’aspetto poiché si riteneva fondamentale utilizzare delle interfacce cosiddette friendly per facilitare l’orientamento nella navigazione dell’utente. Purtroppo nel corso della realizzazione del sito si sono verificati molti problemi dovuti specialmente al fatto che il GWT non è ancora diffuso nel mondo e questo ha rappresentato fin dall’inizio un ostacolo che ha rallentato non poco lo sviluppo del portale, imponendo a volte di adottare soluzioni alternative non sempre pratiche e semplici. Pagina 84 Capitolo 4: Conclusioni 4.2 CONSIDERAZIONI SUL GWT Il GWT è un software molto utile per sviluppare portali o semplici applicazioni grafiche ma allo stesso tempo è ancora poco diffuso, considerando la sua “breve” vita. Sfortunatamente per realizzare un efficiente sito non basta una conoscenza superficiale del GWT stesso: occorre approfondire certi aspetti (come ad esempio è successo per la costruzione dell’albero asincrono nella cartella clinica del paziente) mediante lettura di documentazioni (il più delle volte insufficienti), confronti con altri informatici, tutorial e forum (i quali si sono rivelati i più utili tra tutte le opzioni percorribili). VANTAGGI Il vantaggio principale che offre il GWT è l’apprezzabile grafica: abbiamo scoperto, e ne abbiamo fatto uso, alcuni siti che permettono di vedere vari esempi e che rendono disponibile il codice di quest’ultimi con lo scopo di diffondere le applicazioni rendendole comprensibili a molte più persone (http://www.gwt-ext.com/demo è uno di questi). Per sfruttare al meglio le potenzialità grafiche del GWT abbiamo deciso di scaricare due librerie che ci hanno permesso di utilizzare nuovi e diversi widgets (alcuni con funzioni estese rispetto a quelli della versione standard): GWT-EXT (a cui abbiamo fatto principalmente riferimento salvo problemi) e GWT-EXT-UX. SVANTAGGI Lo svantaggio più grande che questo software ha attualmente è la poca diffusione che ha avuto a livello mondiale tra i programmatori: ancora adesso è difficile trovare un sito (compreso quello di Google) che fornisca indicazioni chiare e semplici su ogni aspetto del GWT. Per questo motivo, quando necessitavamo di informazioni risolutive per un certo tipo di problema, la metà delle volte non riuscivamo a trovare una soluzione diretta ed eravamo costretti a ripiegare su metodi alternativi non sempre soddisfacenti. Fortunatamente nei forum riuscivamo a trovare spesso (ma non subito) qualcuno che forniva un rimedio ai nostri problemi ma questo, comunque, non comporta un grande vantaggio, specialmente se si pensa che una persona mediamente predilige utilizzare programmi di immediata comprensione e con aiuti molteplici e dettagliati (cosa che invece per il GWT ancora non è stata realizzata). Esistono anche svantaggi, se così possiamo chiamarli, dovuti al modo in cui il GWT è stato concepito come, ad esempio, il modo per ricercare, modificare o inserire dati nel database: il fatto di dover utilizzare la “Async Callback” (chiamata asincrona) comporta la presenza Pagina 85 Capitolo 4: Conclusioni di altri due file, oltre a quello lato client e quello lato server, che in pratica non sono molto utili dato che contengono solo metodi, non definiti, che possono essere chiamati dalla classe client, occupando di conseguenza spazio (anche se esiguo) e creando una notevole confusione, specialmente se i file sono tanti. In definitiva, secondo il mio parere, il GWT, sebbene apporti diversi vantaggi e novità alla progettazione di sistemi software, non è ancora adatto per i programmatori poiché tuttora non è riscontrabile un vantaggio così netto rispetto agli altri linguaggi utilizzati per la costruzione di siti (ad esempio il PHP). La scelta da parte di colui che mi ha seguito in azienda (Ing. P. Giampieri) di sviluppare il portale con il GWT, per quanto curiosa e coraggiosa possa essere stata, anche se da un lato confrontarmi con un nuovo software è stato apprezzabile, non si è rivelata, dall’altro, molto proficua, anzi: se avessimo utilizzato un linguaggio di programmazione quale è il PHP avremmo sicuramente concluso prima il nostro tirocinio ed evitato molti bug. Pagina 86 Capitolo 4: Conclusioni 4.3 CONSIDERAZIONI SUL PORTALE Il portale ha fatto un gran passo avanti rispetto al vecchio “Miro On Rails”: rispetto a quest’ultimo è stata migliorata notevolmente la grafica e sono stati risolti alcuni bug anche se l’utilizzo del GWT ne ha creati degli altri. Durante la realizzazione del progetto abbiamo cercato sempre di migliorare gli aspetti che nel vecchio portale non ci sembravano chiari oppure erano sbagliati (come ad esempio la possibilità da parte del dottore di modificare dati personali del paziente, che in realtà non è in grado di conoscere se non tramite la cartella clinica). Tutto ciò è stato possibile grazie ad uno studio attento del “Miro On Rails” (su consiglio dell’Ing. P. Giampieri) che mi ha permesso di evidenziare i vari limiti. Aspetti che non abbiamo sottovalutato sono stati ad esempio la compatibilità con i vari browser e con le diverse versioni di ciascuno (in particolare Internet Explorer che, come ci ha riferito del prof. A.F.Dragoni al ritorno dal suo viaggio in Zambia, è quello usato dalle strutture sanitarie africane), la velocità con la quale un widget veniva caricato o tolto oppure il tempo impiegato per stampare i dati su un pannello (sempre su suggerimento del prof. A.F.Dragoni abbiamo testato il portale su diversi computer con diverse connessioni internet, tra cui quella a 56K, utilizzata nella gran parte del continente africano). POSSIBILI SVILUPPI FUTURI Ricordo, al momento della presentazione del progetto che mi fece il prof. Dragoni, di aver visto tra i possibili sviluppi del portale nel futuro quello del possibile utilizzo di una smart card per poter accedere al sito. Fin dall’inizio questa mi è sempre sembrata un buonissima idea soprattutto se si considera il problema della sicurezza: infatti, preferirei utilizzare uno strumento di identificazione esterno piuttosto che effettuare un login come nel vecchio e nell’attuale portale. Di fatto, oltre alla riduzione delle possibilità di intercettazione di username e password dell’utente da parte di terzi, l’utilizzo della smart card comporterebbe un miglioramento della gestione delle registrazioni, evitando di dover passare per forza attraverso richieste via e-mail. Naturalmente ci sarebbero da prendere le dovute precauzioni che non alterino in modo radicale la struttura del portale: ad esempio credo si possa realizzare una smart card che venga consegnata ad ogni utente con la possibilità di tenere traccia, per quelle del richiedente e del dottore, dell’amministratore di competenza (e viceversa) e di aggiornarle mediante appositi dispositivi. In questo modo si Pagina 87 Capitolo 4: Conclusioni eliminerebbero anche i livelli di amministrazione. Credo, quindi, che un orientamento verso questa direzione possa migliorare non solo la sicurezza ma anche la qualità del sito. Un’ulteriore considerazione che si può fare, rivolta al miglioramento del portale, riguarda il meccanismo di timestamping che, come ci ha suggerito il prof. A.F.Dragoni, potrebbe risultare molto utile nel momento in cui sorgono questioni legali tra dottore e strutture sanitarie riguardo le prestazioni fornite: ad esempio, potrebbe capitare che lo specialista scrivi un referto non disponendo di tutte le informazioni necessarie (per il fatto che il richiedente si scordato oppure ha trascritto erroneamente qualche dato, per poi correggerlo in un secondo momento, dopo la refertazione) per capire quale malattia quel paziente possa avere e come curarla. In questo caso, se il paziente muore o trae danni da quella diagnosi, la struttura sanitaria potrebbe incolpare il dottore e ricorrere alle vie legali. Grazie al timestamping, che riporta quando qualsiasi modifica, inserimento e cancellazione sono state fatte, le due parti si assumono le proprie responsabilità e si possono evitare spiacevoli dissidi. Un altro possibile sviluppo futuro potrebbe essere rappresentato dall’utilizzo di un meccanismo di comunicazione in tempo reale (ad esempio una chat) che potrebbe facilitare l’interazione tra strutture ospedaliere e medici specialmente nelle richieste di maggiori chiarimenti riguardo al paziente di cui si vuole effettuare il referto. Comunque, la comunicazione che attualmente è stata impostata nel portale è abbastanza sufficiente per soddisfare le esigenze delle due parti quindi il discorso riguardante la chat, ad esempio, potrebbe essere preso in considerazione in un tempo futuro quando se ne sentirà la necessità. Per quanto riguarda le funzionalità del portale, credo si debba solo aspettare un ulteriore sviluppo del GWT, peraltro già avvenuto durante il nostro tirocinio: considerando che il primo software è stato lanciato nel 2006 e che nel giro di due anni ci sono state cinque nuove versioni, sono alquanto ottimista che in un futuro molto breve ne verranno sviluppate altre migliori. Pagina 88 Capitolo 4: Conclusioni 4.4 CONSIDERAZIONI SUL TIROCINIO Sebbene il mio tirocinio doveva svolgersi in azienda (presso la ASUR n.7 di Ancona), la maggior parte delle 300 ore le ho spese nel vecchio DEIT dell’università (Dipartimento di Elettronica, Intelligenza Artificiale e Telecomunicazioni), dove gli altri quattro tirocinanti lavoravano: la ragione per cui ho fatto questa scelta è dovuta al fatto che, dato che si trattava di un lavoro di gruppo, era sempre necessario confrontarsi per organizzare al meglio il portale e, successivamente, dividerci il lavoro in modo tale che l’operato di ciascuno di noi non andasse ad ostacolare quello degli altri. Considerando, inoltre, che gli errori e i problemi, dovuti al GWT, erano sempre all’ordine del giorno, col tempo è stato sempre più necessario collaborare per risolvere questi bug. Inizialmente, il tempo trascorso alla ASUR era maggiore proprio perché ancora il portale doveva essere costruito ed era necessario anche confrontarsi con i collaboratori in azienda (si ricorda che l’iniziativa di progettare “MedTel” è stata proprio della ASUR, o meglio, dell’Ing. P. Giampieri) per capire quali aspetti dovevano essere implementati e quali no. Ricordo che nelle mie prime tre visite alla struttura sanitaria ancora si discuteva su come organizzare il portale a livello di maschere e di funzionalità. Una volta che le linee guida sono state tracciate, sono passato alla ASUR un numero di volte inferiore, la maggior parte delle quali per mostrare il lavoro svolto e per eventuali chiarimenti nella strutturazione di alcune pagine del portale, anche perché il GWT e la ricerca su internet non fornivano sempre soluzioni rapide ed efficaci. Le prime ore di tirocinio alla ASUR le ho spese segnando su dei fogli appunti importanti per la progettazione del “MedTel”: questi riguardavano la strutturazione del vecchio portale (il “Miro On Rails”) e l’organizzazione delle informazioni e delle funzionalità richieste dalle specifiche illustratemi dal prof. A.F.Dragoni. Successivamente, sempre alla ASUR, mi sono dedicato all’organizzazione delle form per l’inserimento dei dati per i pazienti, operazione che potevo svolgere autonomamente dato che si trattava il più delle volte di aspetti grafici e funzioni che non richiedevano una collaborazione con gli altri tirocinanti. Nell’azienda, comunque, non ero solo: oltre all’Ing. Giampieri c’era anche l’Ing. Lella che mi aiutava nel caso qualcosa non mi fosse chiaro oppure per risolvere qualche problema. Oltre a questo, mi hanno messo a disposizione la connessione alla rete internet dell’azienda in modo tale che potessi consultare siti e il portale “Miro On Rails” per raccogliere informazioni oppure per contattare i miei colleghi per consulti sul lavoro in questione. Pagina 89 Capitolo 4: Conclusioni Per quanto riguarda l’attività svolta nel dipartimento, questa può essere divisa in due parti: la prima, in ordine cronologico, è rivolta al lavoro in locale, ovvero dove i tirocinanti svolgevano ciascuno un determinato compito per poi mettere insieme i vari files (degli esempi su tutti, la suddivisione delle aree riservate e la distinzione delle varie parti della cartella clinica del paziente); la seconda parte, invece, è stata dedicata, prima, al trasferimento dei files dai nostri computer al server e, poi, all’elaborazione di quest’ultimi nello stesso server: in pratica abbiamo utilizzato anche sul server una versione di Eclipse per effettuare il deploy module (del GWT) del modulo xml. Dopo iniziali “problemi di ambientamento” siamo riusciti a concludere l’esperienza di tirocinio cercando di risolvere eventuali ed improvvisi bug che in locale oppure su un particolare browser non esistevano. Pagina 90 Bibliografia [1] WIKIPEDIA (http://it.wikipedia.org): consultazione informazioni sui vari software trattati nel primo capitolo. [2] http://www.claudiodesio.com/java/excs.htm: consultazione informazioni e utilizzo immagini riguardanti la gestione delle eccezioni in Java. [3] http://www.java-net.it/jmonline/cap6/index.htm: consultazione informazioni riguardanti l’ereditarietà, l’overloading e l’overriding delle classi Java. [4] http://www.bradipomissile.net/2007/11/13/ereditarieta-in-java/: consultazione informazioni riguardanti l’ereditarietà delle classi in Java. [5] http://programmazione.html.it/guide: consultazione informazioni sul Ruby On Rails. [6] “Java Fondamenti di programmazione”, Deitel & Deitel, APOGEO: consultazione informazioni sul Java PORTALI DI RIFERIMENTO “Miro On Rails”: http://193.205.130.163/miro/user/login “MedTel”: http://193.205.130.163:8080/medtel/ Pagina 91