zanoni.doc.doc

109
UNIVERSITA’ DEGLI STUDI DI TRENTO Facoltà di Scienze Matematiche, Fisiche e Naturali Corso di Laurea in Informatica Invocazione di Web Services da devices mobili

description

 

Transcript of zanoni.doc.doc

Page 1: zanoni.doc.doc

UNIVERSITA’ DEGLI STUDI DI TRENTO

Facoltà di Scienze Matematiche, Fisiche e Naturali

Corso di Laurea in Informatica

Invocazione di Web Services da devices mobili

Page 2: zanoni.doc.doc

Relatore:prof. Marco Aiello

Page 3: zanoni.doc.doc

Tesi di laurea di:Manuel Zanoni

Anno Accademico 2002-2003

Indice

Page 4: zanoni.doc.doc

Indice...................................................................................................................................................21 Introduzione al problema...............................................................................................................3

1.1 Descrizione del problema.............................................................................................................31.2 Web services e devices mobili......................................................................................................51.3 Il Web Service di Google.............................................................................................................6

1.3.1 Possibili utilizzi dell’applicazione.........................................................................................61.4 Dialogare con un aggregato di servizi..........................................................................................7

2 Che cos’è un Web Service?.............................................................................................................92.1 XML.....................................................................................................................................122.2 SOAP....................................................................................................................................132.3 WSDL...................................................................................................................................142.4 UDDI....................................................................................................................................152.5 BPEL....................................................................................................................................152.6 XSRL....................................................................................................................................16

3 Soluzione al problema...................................................................................................................183.1 Sviluppare per la J2ME........................................................................................................183.2 Realizzazione di un client per il web service di Google.......................................................193.3 Realizzazione di un client per un aggregato di servizi.........................................................22

Conclusioni........................................................................................................................................26Bibliografia........................................................................................................................................27Appendice A: Codice sorgente........................................................................................................29

A.1 Client per il web service di Google...........................................................................................29A.1.1 GoogleSearchMain.java......................................................................................................29A.1.2 Connection2Server.java......................................................................................................31A.1.3 Operations.java...................................................................................................................33A.1.4 Parser.java...........................................................................................................................36

A.2 Client per un aggregato di servizi..............................................................................................40A.2.1 XSRLQueryMain.java........................................................................................................40A.2.2 Connection2Server.java......................................................................................................43A.2.3 Parser.java...........................................................................................................................44A.2.4 Request.java........................................................................................................................46A.2.5 MenuDate.java....................................................................................................................49A.2.6 MenuFinalDate.java............................................................................................................50A.2.7 MenuInitialDate.java..........................................................................................................52A.2.8 MenuHotel.java..................................................................................................................54A.2.9 MenuHotelAmount.java.....................................................................................................55A.2.10 MenuPlace.java.................................................................................................................57A.2.11 MenuResponse.java..........................................................................................................58A.2.12 MenuTotalAmount.java....................................................................................................59A.2.13 MenuTransport.java..........................................................................................................61A.2.14 MenuTravel.java...............................................................................................................62A.2.15 MenuTravelAmount.java..................................................................................................64A.2.16 MenuWPAmount.java......................................................................................................65A.2.17 MenuWPHotelAmount.java.............................................................................................68A.2.18 MenuWPNotTransport.java..............................................................................................72A.2.19 MenuWPTransport.java....................................................................................................75A.2.20 MenuWPTravelAmount.java............................................................................................78

4

Page 5: zanoni.doc.doc

Capitolo 1

Introduzione al problema

1.1 Descrizione del problema

La necessità di condividere grandissime quantità di informazioni, in principio perlopiù di carattere scientifico ha portato alla nascita e allo sviluppo di Internet.Inizialmente la condivisione delle informazioni era limitata al solo interscambio di file di testo o binari. Il continuo estendersi della rete ha portato alla necessità di definire standard che permettessero l’interazione degli agenti presenti in Internet nonostante le loro enormi differenze in termini di hardware, sistema operativo e applicazioni utilizzate. A tale scopo si è sviluppato TCP/IP [1], un protocollo, o per meglio dire una pila di protocolli, universale grazie alla quale è possibile la comunicazione e lo scambio di informazioni tra sistemi appartenenti a diverse piattaforme software.Il fenomeno dell’espansione di Internet ha inevitabilmente comportato un progressivo cambiamento dell’utenza media che lentamente si è allontanato da quella scientifica per coprire un numero molto più vasto di persone.Ciò ha comportato la necessità di migliorare il modo di esporre i contenuti presenti in Internet in modo da renderli più presentabili; a tal scopo si è diffuso il linguaggio di markup HTML che rende possibile la costruzione di ipertesti aggiungendo ai contenuti di metadati, relativi alla visualizzazione di tali dati, che appositi programmi, detti browser, riescono a interpretare.Con l’insorgere della necessità di offrire servizi che scambiavano le informazioni in modo dinamico e con continui aggiornamenti, col trascorrere del tempo questo standard risultò sempre più limitativo.A tale scopo sono state introdotte varie tecniche per la creazione di componenti dinamici all’interno del contenuto di una pagina web, quali applicazioni CGI, Servlet, Script, ecc.Alcune di queste si basano su Java [2] un linguaggio di programmazione che, grazie alla sua caratteristica di essere indipendente dalla piattaforma che le esegue, si adatta ottimamente a questo scopo. L’evoluzione della rete che si sta ora muovendo verso lo sviluppo di servizi dinamici che svolgono, in modo interattivo, incarichi che prevedrebbero un diverso numero di passi da parte dell’operatore.C’è quindi bisogno di un nuovo processo di standardizzazione che permetta l’intercomunicazione direttamente da macchine a macchine superando la differenza tra le fonti, a questo scopo sono stati introdotti i web services (o servizi web).Estendendo la loro capacità di ottenere l’indipendenza dell’applicazione dal protocollo di trasporto e dalla piattaforma di implementazione, essi permettono l’integrazione di tutte le applicazioni esistenti sul web senza dover procedere ad una modifica di parti di codice. I web services rappresentano un nuovo tipo di applicazioni aventi come caratteristica primaria la capacità di poter essere pubblicati, localizzati ed invocati dal web.Allo stesso modo in cui si è evoluta la rappresentazione delle informazioni di Internet, si è sviluppata anche quella della ricerca di tali informazioni.Infatti, se all’inizio esisteva un semplice sistema informativo di Directory statico nel quale erano riportati i riferimenti alle varie informazioni presenti sulla rete, tale sistema si è rivelato ben presto limitante e ha portato alla creazione di particolari servizi detti motori

5

Page 6: zanoni.doc.doc

di ricerca che si occupano essi stessi di scandagliare di continuo la maggior parte possibile del web per memorizzare e modificare le informazioni presenti nei propri database.I motori di ricerca sono tutt’ora il metodo più utilizzato per ricercare le informazioni nel web, tra di essi il più famoso e utilizzato è Google dalla cui home page (http://www.google.com) è possibile inserire una stringa ed effettuare su di essa una ricerca in tutto il web.L’evoluzione che ha portato allo sviluppo dei web services potrà portare all’utilizzo di tali motori di ricerca direttamente da apposite applicazioni che si interfacciano in maniera standardizzata al servizio web fornito dal motore di ricerca stesso.Questo sarà uno dei punti trattati nell’elaborazione di questa tesi.

Sulla base di questo contesto si pone il problema preso in esame nello sviluppo di questa tesi, che consiste nel dimostrare l’efficienza e le potenzialità dei web services mostrando come sia possibile interagire con loro in maniera semplice ed efficace anche da un device mobile, quale un moderno telefono cellulare che sia in grado di far eseguire le applicazioni Java scritte usando la J2ME [3] (Java 2 Micro Edition), un’edizione della Java Virtual Machine [4] (la macchina virtuale che permette di mappare le API Java sulla periferica di destinazione e di compilare e eseguire il codice Java) che presenta meno classi e potenzialità, ma che ha il vantaggio di poter essere usata su dispositivi con un limitato potere di calcolo, quali palmari o, come nel caso preso in esame, telefoni cellulari.Tutto ciò è possibile in quanto l’uso dei servizi web implica la realizzazione di un sistema distribuito [5] e tutte le sue caratteristiche, tra cui in questo caso, spiccano:

1. Eterogeneità: che rappresenta la diversità tra le componenti in termini di hardware, rete, sistema operativo, linguaggio di programmazione e implementazione da parte di diversi sviluppatori.

2. Trasparenza: che rappresenta, in diverse forme, l’occultamento dei dettagli implementativi e di gestione distribuita che fanno percepire il sistema come un tutt’uno.

3. Apertura: che impone che siano concordate e pubblicate le interfacce dei componenti; In tale maniera gli sviluppatori possono interfacciare facilmente nuovo software con componenti esistenti.

Per prima cosa verrà mostrato come si possa interagire con un singolo servizio presente nel web, nella fattispecie è stato scelto di rendere possibile a tale applicazione di interrogare il famoso motore di ricerca Google e di ricevere e mostrare i risultati ottenuti.

Il passo successivo è quello di mostrare l’interazione tra il device mobile e un aggregato di servizi, nello specifico verrà preso in esame il caso in cui un utente voglia prenotare un viaggio, interagendo così con vari web services tra i quali: un’agenzia di viaggi, un servizio di hotel, un servizio aereo, un servizio ferroviario, ecc. Dimostrando come sia possibile mascherare tale architettura all’utente finale che percepirà l’intero sistema come un tutt’uno.

6

Page 7: zanoni.doc.doc

Verrà quindi dimostrato come l’utilizzo dei web services consente di superare i maggiori problemi che si presentano nel realizzare questo tipo di applicazioni, che sono:

1. La bassa capacità di calcolo del dispositivo hardware designato a ospitare l’applicativo; infatti, nonostante il continuo sviluppo nel settore e la realizzazione di telefoni cellulari sempre più simili a pc il divario tra i due sistemi resta notevole.

2. La completa eterogeneità dei componenti del sistema che si vuole realizzare; eterogeneità che va dall’hardware e dal sistema operativo utilizzato sugli hosts alle caratteristiche della rete sulla quale il software dovrà operare.

3. L’interazione tra componenti che per loro natura sono autonomi e che quindi non dipendono necessariamente l’uno dall’altro.

4. Far percepire all’utente l’intero sistema come se fosse un unico applicativo proprio del devices che esso sta usando.

Infatti, l’esecuzione di un client per un servizio web comporta un basso carico computazionale e l’utilizzo di protocolli standard rende invisibile l’eterogeneità del sistema.

1.2 Web services e devices mobili

L’evoluzione e la diffusione dei devices mobili hanno suscitato notevoli interessi in tutte le principali aziende che in essi trovano un modo in cui i dipendenti possano accedere ad applicazioni back office dall’esterno dell’azienda stessa.I web services, dal canto loro, per la loro indipendenza alla piattaforma che li utilizza, sono considerati un’ottima soluzione per portare applicazioni sui devices mobili.Appare quindi abbastanza naturale come queste due tecnologie si stiano sempre più avvicinando l’una all’altra, cosicché gli utenti finali possano fruire contemporaneamente dei benefici derivati dalla loro unione.A tale scopo tutti i più importanti software vendors hanno operato per realizzare piattaforme destinate a questo tipo di dispositivi. Oltre alla già citata J2ME [3] della Sun infatti, sono tuttora disponibili anche piattaforme sviluppate da IBM e da Microsoft (che ha realizzato .Net Compact Framework, una versione ridotta della piattaforma .Net).Come detto, quindi, sfruttare i web services comporta, oltre agli enormi benefici in termini di standardizzazione e apertura, lo spostamento del calcolo su un’altra macchina e quindi non soffrire per le basse risorse a disposizione.

1.3 Il Web Service di Google

La possibilità di interrogare il motore di ricerca Google e di riceverne le risposte è resa possibile dal poter usufruire di API fornite gratuitamente da Google stesso reperibili, dopo aver effettuato un’apposita registrazione, all’indirizzo Internet http://www.google.com/apis.Google ha infatti introdotto un servizio web di API che permette agli sviluppatori di programmare un motore di ricerca funzionale nelle loro applicazioni. Con il Google Web

7

Page 8: zanoni.doc.doc

APIs service, un programma ha la possibilità di interrogare più di due miliardi di documenti residenti nel web in maniera facile e veloce, così come lo si fa dalla home page di Google stesso. Il Google Web APIs service fornisce un’interfaccia SOAP (Simple Object Access Protocol) [6] che permette di ricercare all’interno dell’indice di Google, accedendo alle informazioni e alle pagine web dalla sua cache e di effettuare controlli riguardanti lo spelling di parole contrarie alla sintassi standard di ricerca di Google. Il pacchetto scaricabile all’indirizzo sopraccitato contiene tra le altre cose un documento WSDL (Web Services Description Lenguage) [7] che specifica come interagire con il servizio, in che modo effettuare le richieste e come attendersi le risposte.Sfruttando tale file è stato possibile realizzare un’applicazione che riesca a formulare una richiesta valida per la ricerca di una stringa arbitraria incapsulata in un messaggio SOAP inviato all’apposito servizio di Google che si opera di ricercare tale stringa nel web, e poter poi ricevere e riuscire a interpretare i risultati trovati in modo da renderli visibili all’utente finale. Infatti, sempre mediante il file WSDL è stato possibile comprendere la sintassi del messaggio SOAP contenente i risultati per poterli così mostrare a video.Il programma realizzato risulta essere inoltre un brillante esempio di come l’apertura caratteristica dei web services fornisca interfacce grazie alle quali le applicazioni riescono a integrarsi superando così tutti i tipi di eterogeneità dei componenti di sistema, riuscendo a far comunicare un telefono cellulare che con il proprio sistema operativo inoltra le sue richieste usando il protocollo WAP alla sua rete wireless, dalla quale la richiesta verrà inoltrata verso Internet e da lì al un server incaricato di svolgere il servizio web di Google; tutto ciò avviene in totale trasparenza senza che l’utente percepisca le differenze del sistema.

1.3.1 Possibili utilizzi dell’applicazione

L’utilizzo del software realizzato è quello di effettuare una ricerca di una determinata stringa passata in input usando il motore di ricerca Google, gli stessi risultati si possono ottenere semplicemente, tramite HTTP, svolgendo la ricerca nella maniera classica dalla Home page dello stesso Google (http://www.google.com), o creando uno script che esegua tale ricerca inserendo automaticamente la stringa da cercare nell’apposito spazio della pagina web.Da questo punto di vista l’applicativo creato non sembra avere altre funzionalità se non quelle di un esempio didattico, tuttavia esiste una fondamentale differenza tra i due tipi di approcci.Nel caso dello script, viene creato un software che simula il comportamento umano e invia una parola al motore di ricerca aspettando i risultati.Uno dei più classici esempi di programmazione in questa direzione sono i wrapper che sono quegli agenti del sistema che permettono di accedere a risorse esterne interfacciandosi con il software che le gestisce. In questo contesto si pongono come applicazioni che si interfacciano a un sito web con lo scopo di recuperare le informazioni desiderate. Tale procedura è però fortemente vincolata dalla struttura del sito web stesso, ciò comporta che se venisse cambiata tale struttura, aggiungendo un nuovo campo di testo o nuovi pulsanti e funzionalità, l’applicativo creato fallirebbe in quanto esso è stato concepito per interagire solo con la vecchia pagina web.Nel caso dell’utilizzo dei web services, invece, il software interagisce con il servizio di ricerca, ne capisce il meccanismo di funzionamento (per quanto riguarda lo scambio dei dati, senza curarsi del suo funzionamento interno) e comunica direttamente con esso.

8

Page 9: zanoni.doc.doc

Inoltre una simile architettura può essere vista come la base per la realizzazione di un’applicazione ben più complessa che consente il filtraggio dei risultati della ricerca in base a determinate specifiche impostate dall’utente finale.Un tale sistema è estraneo agli scopi di questa tesi di laurea e non verrà quindi trattato.

1.4 Dialogare con un aggregato di servizi

Dialogare con un singolo web service sta diventando al giorno d’oggi pratica molto diffusa nelle applicazioni web, ma l’idea di inoltrare la propria richiesta, non a un singolo servizio, ma a un aggregato di servizi è un problema aperto.Tuttavia lo spostamento del sistema in questa direzione rappresenta un considerevole passo in avanti per l’evoluzione dei web services in quanto la composizione e l’invio di una singola richiesta composta e l’analisi dei risultati in base a tutte le richieste effettuate, significherebbero, in parecchi casi, un notevole risparmio in termini di tempo e risorse rispetto all’inoltrare diverse richieste a singoli web services, attenderne e analizzarne autonomamente i risultati.Nel caso dei devices mobili, inoltre, un eventuale processo di analisi dei risultati effettuato da parte del devices stesso comporterebbe un superfluo sfruttamento delle risorse hardware a disposizione, dato che il basso potere di calcolo dei devices mobili era uno degli ostacoli superati dall’introduzione dei servizi web, sembra ancora più opportuno riuscire a delegare ai servizi web stessi anche questa operazione.Inoltre una tale evoluzione all’interno dei web services permetterebbe di svincolarsi dall’obbligo di utilizzare un’architettura fissa stabilita durante la progettazione del servizio, rendendo possibili continue modifiche della stessa direttamente a run time.Per rendere possibile uno sviluppo di questo tipo c’è bisogno di:

1. Uno standard per la descrizione di aggregati di servizi: così come WSDL è lo standard per la descrizione di un singolo web service serve un sistema che renda possibile la descrizione di aggregati di servizi, a questo scopo è stato realizzato ad esempio, BPEL (Business Process Execution Language) [8].

2. Un linguaggio per esprimere le richieste dell’utente ai servizi: muovendosi in questa direzione l’Università degli studi di Trento ha realizzato XSRL (XML Service Request Lenguage) [9,10], linguaggio grazie al quale è possibile creare richieste, basandosi sulla sintassi XML [11].

Al fine di mostrare un esempio di dialogo con un aggregato di servizi è stata realizzata un’applicazione che rappresenta un esempio di creazione e inoltro di una richiesta XSRL; come caso di studio è stato scelto quello della richiesta di un viaggio.

9

Page 10: zanoni.doc.doc

Capitolo 2

Che cos’è un Web Service?

I web service (o servizi web) stanno diventando uno degli argomenti di maggiore interesse per quanto riguarda l’ambiente di Internet e dei sistemi distribuiti.A dimostrazione di ciò vi è il fatto che aziende quali Microsoft, IBM e Sun stanno investendo molte delle proprie energie in questa direzione.Ma vediamo ora di capire che cosa sia un web service e iniziamo dandone la definizione:

Un servizio web è un’interfaccia che descrive una collezione di operazioni, accessibili attraverso una rete mediante messaggistica XML [12].

La definizione mostra subito le caratteristiche prime di un web service:

1. L’interfaccia nasconde tutti i dettagli di implementazione del servizio, facendo sì che sia possibile utilizzarla indipendentemente dalla piattaforma hardware o software usata o dal linguaggio di programmazione con il quale è stata scritta.

2. L’insieme di operazioni che rappresentano il servizio offerto (rappresentabili tramite le funzioni di una DLL condivisa, le classi di un package Java o in un qualsiasi altro modo).

3. Il fatto di trovarsi di fronte a un sistema distribuito i cui attori si scambiano messaggi codificati attraverso la rete sfruttando XML.

L’introduzione dei web services ha portato al concepimento di un nuovo tipo di programmazione, tale metodo va in contro alle condizioni del SOC (Service Oriented Computing) che è definito in “Service Oriented Computing Manifesto”[13] come segue:

I servizi sono elementi computazionali autonomi e indipendenti dalla piattaforma di esecuzione che possono essere descritti, pubblicati, scoperti, orchestrati e programmati usando XML al fine di sviluppare massivamente applicazioni distribuite interoperabili.

Lo scambio di informazioni tra il richiedente il servizio e il servizio stesso nei web services è analogo allo schema delle classiche architetture request-reply come possono essere le architetture client-server.Tuttavia per i servizi web è più logico attendersi un’architettura di tipo peer to peer nella quale le richieste vengono trasmesse tra vari servizi che si occupano di svolgere l’eventuale parte di richiesta a loro destinata e a inoltrare la stessa al destinatario successivo.

10

Page 11: zanoni.doc.doc

La figura 2.1 è un semplice esempio di un richiedente che effettua la propria richiesta a un servizio web che a sua volta la reinoltra a un altro servizio che si occuperà di effettuare la risposta.

Figura 2.1: Scambio di informazioni tra richiedente di un servizio web e il servizio web stesso

L’innovazione derivata dall’uso dei web services sta nel fatto che se fino ad ora venivano sfruttate, ad esempio, applicazioni client-server dove il client interrogava e otteneva le risposte dal server utilizzando un linguaggio, una piattaforma e un protocollo ben definiti a priori, ora il client cerca un servizio web tra un insieme di possibili servizi, sfruttando il servizio UDDI [14], il servizio di repository e ricerca dei web services al quale i servizi web si registrano specificando le proprie funzionalità e grazie al quale tali servizi vengono rintracciati dai possibili fruitori, e una volta trovato quello desiderato si mette in contatto con esso sfruttando le informazioni che descrivono il servizio, dati che lo stesso web service mette a disposizione usando lo standard WSDL, lo standard di descrizione delle funzionalità messe a disposizione da un servizio web basato su XML.Raccolte queste informazioni il client sarà in grado di creare la sua richiesta usando il protocollo SOAP, il protocollo standard per la creazione e lo scambio di messaggi tra fruitori di servizi web e servizi stessi, e la sintassi XML.Il fatto che i dati vengano scambiati dalle applicazioni in maniera standardizzata fa crollare tutti i vincoli di hardware e di linguaggio, presenti, ad esempio, nelle classiche architettura client-server.Inoltre, essendo basata fondamentalmente su HTTP, la comunicazione con i web services non viene interrotta dalla presenza di eventuali firewalls sul percorso. In base a quanto detto la struttura di un web service può essere rappresentata da una pila, ad esempio quella presente nell’articolo “Advancing the Web services stack”[15]:

11

Page 12: zanoni.doc.doc

Figura 2.2: La pila di protocolli dai quali è composto un web services

I protocolli che formano questa pila sono i seguenti:

1. WSXL (Web Services Experience Language) [16]: modello di web services per applicazioni interattive, cioè utilizzate da utenti.

2. WSFL (Web Services Flow Language) [17]: linguaggio usato per mostrare il flusso

di un processo di business.

3. TPA (Trading Partner Agreement): un framework industriale per allineare le pratiche legali e concettuali nell’e-business.

4. UDDI (Universal Description Discovery and Integration) [14]: servizio di repository e ricerca di web services.

5. WSDL (Web Services Description Lenguage) [7]: standard di descrizione dell’implementazione del servizio e di come esso si interfaccia all’esterno.

6. WS Security [18]: protocollo che fornisce un modo per validare l’integrità, la confidenzialità e l’autenticità dei messaggi SOAP.

7. SOAP (Simple Object Access Protocol) [6]: protocollo che fornisce il meccanismo per lo scambio delle informazioni.

Dei quali WSXL, TPA e WS Security sono estranei agli interessi di questa tesi e quindi non verranno trattati, mentre WSFL è stato più recentemente sostituito da BPEL (Business Process Execution Language, descritto in [8]) che è un linguaggio il cui utilizzo è improntato a descrivere aggregati di servizi web.

12

Page 13: zanoni.doc.doc

Entriamo ora nel dettaglio spiegando una per una le principali tecnologie alla base dei web services.

2.1 XML

XML (eXtensible Markup Language) è attualmente considerato come il linguaggio del futuro per lo scambio dei dati.In realtà XML è un linguaggio a tag che permette di identificare il tipo di dato trasmesso associandone un significato.Banalmente si può paragonare XML all’HTML (derivano entrambi dallo standard SGML che fornisce una notazione formale per la definizione dei linguaggi di markup) con la differenza che mentre in HTML i tag servono per esprimere come un dato deve essere visualizzato (font, dimensione, colore, ecc.) in XML i tag rappresentano il significato del dato, quindi non è affatto necessario che esistano dei parser che rendano il contenuto dei file XML uman-readable, come invece accade con HTML.Per rendere più chiara la descrizione verrà ora mostrato un esempio di file XML che descrive un ipotetico magazzino contenente due libri, il primo, la “Divina Commedia” di Dante Alighieri, che ha codice 111 e costa 40 euro, il secondo, i “Promessi Sposi” di Alessandro Manzoni, che ha codice 222 e costa 30 euro.

<?xml version="1.0" encoding="iso-8859-1" ?> <magazzino><libro>  <IDLibro>111</IDLibro>   <Titolo>Divina Commedia</Titolo>   <Prezzo>40</Prezzo>   <Autori>Dante Alighieri</Autori> </libro><libro>  <IDLibro>222</IDLibro>   <Titolo>Promessi Sposi</Titolo>   <Prezzo>30</Prezzo>   <Autori>Alessandro Manzoni</Autori> </libro></magazzino>

Il documento inizia con una riga di intestazione che informa il parser sulle caratteristiche del documento, dopo la quale inizia il documento vero e proprio nel quale i vari tag, che devono seguire regole ben precise perché il documento sia accettato, “spiegano” il contenuto dei dati.Dal documento si nota inoltre come sia possibile definire nuovi tag a piacere e come le informazioni vengano descritte creando una struttura gerarchica ad albero.Per rendere possibile una validazione da parte del ricevente ogni documento XML può contenere la descrizione della sua struttura (DTD), cosicché il parser ricevente possa controllare se il documento è “well formed” (ben formato), cioè rispetta la sintassi XML e “well formed” e “valid” (valido), cioè rispetta le regole presenti nel DTD.In sintesi XML non è nient’altro che un sistema per dare un significato al contenuto di un documento. Per questo trova grande applicazione, nell'ambito dello scambio di dati tra strutture non omogenee come possono essere diverse aziende.

13

Page 14: zanoni.doc.doc

2.2 SOAP

SOAP (Simple Object Access Protocol) è il protocollo che fornisce un semplice meccanismo per lo scambio di informazioni strutturate (scritte sfruttando le potenzialità di XML) in un sistema distribuito decentralizzato.Definendo solo la struttura del messaggio, che le parti si scambiano, e alcune regole per elaborarlo, SOAP riesce a rimanere ad alto livello e quindi ad astrarsi, risultando completamente indipendente, dal protocollo di trasporto sottostante e risultando così implementabile da qualsiasi linguaggio di programmazione e da qualsiasi sistema operativo.Un’altra caratteristica chiave di SOAP è la sua semplicità (“Simple”) che gli ha permesso di affermarsi tra i protocolli di comunicazione e che lo rende estensibile a seconda delle esigenze e degli sviluppi futuri.Inoltre con SOAP è possibile usare un qualsiasi modello di programmazione e non solo l’RPC al quale è spesso associato.SOAP è diviso in tre parti: 

1. L’envelope (busta), che è una struttura globale per la definizione di cosa sta nel messaggio e di chi se ne deve occupare.

2. Un insieme di regole di encoding, che sono il meccanismo con il quale poter ottenere lo scambio di informazioni.

3. Una rappresentazione RPC, che fornisce la convenzione usata per le eventuali chiamate e risposte a procedure remote.

Mostriamo ora un messaggio SOAP e analizziamone la struttura, come protocollo di trasporto per il messaggio è stato scelto l’HTTP.Tale messaggio rappresenta la richiesta al web service dell’esecuzione del metodo GetLastTradePrice e passa come parametro una stringa, racchiusa tra i tag <symbol></symbol> che rappresenta il prodotto del quale si vuole conoscere il prezzo.

POST /StockQuote HTTP/1.1Host: www.stockquoteserver.comContent-Type: text/xml; charset="utf-8"Content-Length: nnnnSOAPAction: "Some-URI"

<SOAP-ENV:Envelope  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>   <SOAP-ENV:Header>       <t:Transaction           xmlns:t="some-URI"           SOAP-ENV:mustUnderstand="1">               5       </t:Transaction>   </SOAP-ENV:Header>   <SOAP-ENV:Body>       <m:GetLastTradePrice xmlns:m="Some-URI">           <symbol>DEF</symbol>

14

Page 15: zanoni.doc.doc

       </m:GetLastTradePrice>   </SOAP-ENV:Body></SOAP-ENV:Envelope>

Si nota subito come l’envelope del messaggio sia divisa in due parti:

1. L’header: una parte opzionale del messaggio che consente l’aggiunta di caratteristiche al messaggio SOAP stesso ed è sfruttato spesso per l’estensibilità del protocollo, vi possono essere infatti entries riguardati l’autenticazione, la gestione della transazione, ecc.

2. Il Body: parte obbligatoria che contiene le informazioni da spedire al destinatario, quali possono essere il marshalling di una chiamata RPC, comprensivo dell’invio di tutti i parametri necessari alla stessa.

L’applicazione che riceverà il messaggio deve:

1. Identificare le parti del messaggio SOAP destinate ad essa.

2. Verificare che tutte queste parti siano supportate e in tal caso elaborarle.

3. Nel caso in cui l’applicazione non sia il destinatario finale del messaggio, essa deve rimuovere tutte le parti identificate nel punto 1. e inoltrare il messaggio.

Nel caso subentrino degli errori l’applicazione risponderà al mittente con degli speciali messaggi d’errore che specificano il tipo e le cause dell’errore stesso, tali messaggi sono detti SOAP Fault.

2.3 WSDL

Come detto per ricevere i servizi da parte di un web service è sufficiente inviargli una richiesta SOAP opportuna.Ma come si può sapere che tipo di richiesta si aspetta un web service?WSDL (Web Services Description Lenguage) si occupa proprio di questo, consente infatti ai web services di specificare il formato delle richieste che si attendono dai vari client.Infatti i file WSDL associati ai web services sono documenti scritti in XML che descrivono cosa esso possa fare (metodi da invocare con relativi parametri e valori di ritorno, ecc.), dove questi servizi risiedano, in che modo invocarli e come formatteranno le risposte alle richieste che gestiranno.Tutti i metodi riportati sono descritti in maniera astratta e sono associati a un concreto protocollo di rete e formato di messaggi.Le descrizioni dei servizi web fatte con WSDL sono composte dai seguenti elementi:

1. Types: un contenitore per le definizioni dei tipi di dati realizzato usando un sistema come XSD.

2. Message: una definizione astratta e tipata dei dati che verranno scambiati, contiene cioè i parametri di richiesta e di risposta del servizio.

15

Page 16: zanoni.doc.doc

3. Operation: una descrizione astratta di un’azione supportata del servizio web costituita da messaggi di richiesta e risposta.

4. Port Type: un insieme di operazioni astratte supportate da uno o più endpoint.

5. Binding: descrive il protocollo supportato, le operazioni consentite e i relativi input e output per un particolare port type.

6. Port: un singolo endpoint definito come una combinazione di un binding e di un indirizzo di rete.

7. Service: un insieme di endpoints collegati, mostrati dalla locazione del binding associato al servizio.

2.4 UDDI

A questo punto a un cliente non resta che riuscire a individuare il servizio web adatto alle sue esigenze.UDDI (Universal Description Discovery and Integration) ha proprio questa funzionalità, permette infatti di localizzare e conoscere i servizi offerti dalle aziende iscritte, proprio come se fosse una sorta di “pagine gialle” residenti sul web. Più precisamente si tratta di una specifica per registry di informazioni sui servizi web (quale ad esempio i dettagli per collegarsi ad esso) nella quale i fornitori di servizi e i servizi stessi sono descritti in XML. UDDI si basa sul protocollo SOAP in quanto sia le richieste che le risposte sono oggetti UDDI incapsulati all’interno di messaggi SOAPIl tradizionale scenario di utilizzo di UDDI viene rapidamente ricondotto a queste tre fasi fondamentali:

1. Pubblicazione (publishing): il fornitore del servizio per renderlo pubblico contatta il service broker che provvede ad inserirlo nel registry tramite UDDI.

2. Ricerca (finding): alla richiesta di un servizio, il service broker provvede a cercare quelli che meglio rispondono alle esigenze del richiedente.

3. Collegamento (binding): nel momento in cui il service broker fornisce la risposta può stabilirsi il collegamento tra il richiedente del servizio web e il fornitore.

2.5 BPEL

BPEL (Business Process Execution Language) è un linguaggio in grado di specificare il comportamento di un processo di business, e quindi di descrivere le caratteristiche di un aggregato di web services.L’introduzione di tale linguaggio permette un ulteriore grado di astrazione nella pila dei servizi web, infatti grazie al suo utilizzo si è in grado di mascherare all’utente finale non solo il funzionamento interno di ogni singolo servizio (cosa che era già possibile con WSDL) ma anche le modalità di interazione con ogni singolo servizio, mostrando all’utente finale l’aggregato di servizi come un’entità unica.

16

Page 17: zanoni.doc.doc

BPEL esprime le specifiche degli aggregati di servizi tramite un file XML per struttura molto simile ai file WSDL.

2.6 XSRL

XSRL (XML Service Request Lenguage) è un linguaggio per formulare richieste ad aggregati di web services.XSRL, basandosi sull’uso di specifici tag XML, fornisce la possibilità di formulare una precisa richiesta a un aggregato di servizi (o business process) scomponendola nei vari obiettivi e sott’obiettivi necessari per il raggiungimento della stessa.E’ infatti possibile scomporre gli obiettivi per specificarne un ordine temporale, tramite la relazione basata sull’uso del tag <BEFORE> goal1 </BEFORE> <THEN> goal2 </THEN> che è soddisfatta se goal1 è soddisfatto e successivamente anche goal2 viene soddisfatto, o esprimere un obiettivo tramite la comparazione di una variabile ad un valore, ad esempio grazie all’uso della relazione <LESS> variabile </LESS> <THAN> valore </THAN> che è soddisfatta solo se la variabile assume un valore minore di quello specificato.Per rendere più chiari i concetti enunciati creiamo ora, come esempio, una possibile richiesta di un utente a un servizio e la sua realizzazione tramite XSRL.L’utente vuole acquistare un’auto con cilindrata maggiore a 1600cc e, se possibile, spendere meno di 15.000 euro.Nell’esempio l’obiettivo dell’utente è essenzialmente diviso in due obiettivi:

1. La cilindrata DEVE essere maggiore di 1600cc.

2. PREFERISCE un prezzo minore di 15000 euro.

I due obiettivi hanno una differenza fondamentale: il soddisfacimento del primo è condizione necessaria per il soddisfacimento della richiesta (possiamo dire che il primo obiettivo sia vitale), mentre il secondo, che possiamo definirlo opzionale, è considerato sempre soddisfatto, in quanto non pregiudica in alcun caso il buon esito dell’intera richiesta.XSRL esprime questa differenza mediante l’uso di due diverse relazioni espresse rispettivamente dai tag <VITAL-MAINT> e <OPTIONAL-MAINT>.Da ciò deriva che il semplice esempio venga tradotto in XSRL in questo modo:

<XSRL><ACHEIVE-ALL>

<VITAL-MAINT> <GREATER>CilindrataAuto</ GREATER ><THAN>1600</THAN>

</VITAL-MAINT><OPTIONAL-MAINT>

<LESS>PrezzoAuto</LESS><THAN>15000</THAN>

</OPTIONAL-MAINT> </ACHEIVE-ALL>

</XSRL>

17

Page 18: zanoni.doc.doc

Dove i tag <XSRL> </XSRL> rappresentano i delimitatori di inizio e fine del codice XSRL mentre i tag <ACHEIVE-ALL> </ACHEIVE-ALL> racchiudono all’interno una serie di obiettivi che devono necessariamente essere tutti soddisfatti.Come si nota dall’esempio i tag utilizzati sono autoesplicativi, e per questo non è stato ritenuto opportuno inserire in questo documento una specifica della sintassi del linguaggio per la quale si rimanda a [9,10].

18

Page 19: zanoni.doc.doc

Capitolo 3

Soluzione al problema

3.1 Sviluppare per la J2ME

La J2ME (Java 2 Micro Edition) è un runtime environment altamente ottimizzato che permette l’esecuzione di programmi Java su dispositivi di piccole dimensioni, quali ad esempio le smart card, facendo apparire l’esecuzione delle varie applicazioni così come se fosse effettuata da un normale computer.Tuttavia non vi è portabilità assoluta tra le varie versioni di Java usate per i pc, la J2SE (Java 2 Standard Edition) [19] e la J2ME, ciò è dovuto fondamentalmente al fatto che la J2ME presenta un numero di package (e quindi di API fornite allo sviluppatore) molto limitato rispetto alla J2SE.La figura 3.1 (tratta dal datasheet di Sun della J2ME stessa [3]) mostra la distinzione tra le varie edizioni di Java in termini di packages e macchine virtuali in base alle piattaforme che le utilizzano.

Figura 3.1: Distinzione tra le varie edizioni di Java

Quindi all’enorme vantaggio, per chi sviluppa in J2ME, di realizzare un software che possa essere portato e utilizzato in qualsiasi luogo e in qualsiasi momento, dovuto alla

19

Page 20: zanoni.doc.doc

comodità di trasporto dei dispositivi forniti di J2ME rispetto ai normali pc, si contrappone una maggiore difficoltà di sviluppo e l’impossibilità di creare certi tipi di software dovuta alla carenza di risorse (CPU e memoria) del dispositivo ospitante.Esempio del fatto che programmare in J2ME sia più complesso che in J2SE sono anche le applicazioni da me realizzate discusse in questa tesi, per le quali l’assenza del package java.net ha comportato una maggiore difficoltà nella creazione delle comunicazioni tra client e server, inoltre è stato necessario usare un package apposito per la creazione delle GUI più limitante e complesso degli standard per J2SE java.awt o javax.swing.

3.2 Realizzazione di un client per il web service di Google

L’architettura del sistema che si è realizzato è composta dal device mobile provvisto di J2ME che invia le sue richieste SOAP alla propria rete wireless la quale avrà il compito di inoltrarle attraverso Internet finché non sarà raggiunto il web service desiderato (nel nostro caso quello fornito da Google), come mostrato in figura 3.2.

Figura 3.2: Architettura del sistema rappresentante un client per il web service di Google

Questo è un esempio del fatto che il protocollo SOAP per lo scambio di informazioni sia indipendente dal protocollo di rete sottostante.Il modello di programmazione utilizzato è l’RPC (Remote Procedure Call), il più diffuso nelle applicazioni basate su SOAP, tramite il quale un client può invocare un metodo esistente sul server, il quale lo eseguirà e in risposta invierà i risultati di tale invocazione al client stesso.Come protocollo di trasporto dei messaggi SOAP è stato scelto l’HTTP in quanto:

1. E’ semplice e robusto.

2. Passa attraverso eventuali firewalls.

3. La J2ME installata sui devices mobili possiede delle classi apposite per la gestione di questo protocollo che è l’unico protocollo di comunicazione previsto dalle specifiche MIDP 1.0, che insieme alle CLDC 1.0, compongono lo standard della J2ME.

20

Page 21: zanoni.doc.doc

Per interagire con il web service è bastato seguire le regole trovate nel file WSDL di specifica del servizio dove è stato possibile trovare dove inviare la richiesta e come costruirla.Un possibile messaggio SOAP inviato a http://api.google.com/search/beta2 (indirizzo indicato nella sezione service del file WSDL ottenuto da Google) è il seguente:

<?xml version='1.0' encoding='UTF-8'?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:doGoogleSearch xmlns:ns1="urn:GoogleSearch" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <key xsi:type="xsd:string">la mia chiave datami da Google</key> <q xsi:type="xsd:string">stringa da cercare</q> <start xsi:type="xsd:int">0</start> <maxResults xsi:type="xsd:int">10</maxResults> <filter xsi:type="xsd:boolean">true</filter> <restrict xsi:type="xsd:string"></restrict> <safeSearch xsi:type="xsd:boolean">false</safeSearch> <lr xsi:type="xsd:string"></lr> <ie xsi:type="xsd:string"></ie> <oe xsi:type="xsd:string"></oe> </ns1:doGoogleSearch> </SOAP-ENV:Body></SOAP-ENV:Envelope>

Dove tutti i parametri passati (racchiusi nei tag da key a oe) sono quelli espressi nella sezione message della funzione doGoogleSearch del documento WSDL, dei quali solo q (la stringa da cercare), maxResult (il numero massimo di risultati che si desidera ricevere) e start (l’indice dal quale partire per mostrare i maxResult risultati) sono di importanza rilevante, mentre gli altri rappresentano filtri o opzioni per il linguaggio alcune delle quali sono ignorate dal web services attualmente in funzione.Ecco come il file WSDL descrive il metodo usato (doGoogleSearch).

<message name="doGoogleSearch"> <part name="key" type="xsd:string"/> <part name="q" type="xsd:string"/> <part name="start" type="xsd:int"/> <part name="maxResults" type="xsd:int"/> <part name="filter" type="xsd:boolean"/> <part name="restrict" type="xsd:string"/> <part name="safeSearch" type="xsd:boolean"/> <part name="lr" type="xsd:string"/> <part name="ie" type="xsd:string"/> <part name="oe" type="xsd:string"/> </message>

Mentre le informazioni relative alle specifiche di encoding e al namespace utilizzati sono quelle della sezioni binding

<operation name="doGoogleSearch">

21

Page 22: zanoni.doc.doc

<soap:operation soapAction="urn:GoogleSearchAction"/> <input> <soap:body use="encoded" namespace="urn:GoogleSearch" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body use="encoded" namespace="urn:GoogleSearch" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation>

Una volta inviato il messaggio l’applicazione risulta essere pronta a ricevere un messaggio SOAP di risposta, anche la sintassi di tale risposta è riportata nel file WSDL del servizio web di Google, risulta quindi necessario, per poter ottenere le informazioni desiderate, solamente un opportuno parsing di tale risposta.Al fine di testare le applicazioni realizzate è stato utilizzato l’emulatore di telefoni cellulari della Nokia presente nella Nokia Developer’s Suite scaricabile gratuitamente dal sito http://americas.forum.nokia.com/java/default.asp dopo aver effettuato un’opportuna registrazione.All’avvio tale emulatore si presenta nel modo riportato dalla figura 3.3.

Figura 3.3: L’emulatore di telefono cellulare modello Series 60 della Nokia Developer’s Suite

Per fornire un esempio pratico dell’utilizzo dell’applicativo effettuiamo tramite esso la ricerca della stringa “web service” come mostrato in figura 3.4.

22

Page 23: zanoni.doc.doc

Figura 3.4: Effettuazione di una ricerca

Dalla figura si nota come nel primo menù, quello principale, l’utente possa scegliere l’operazione da effettuare (l’unica implementata è la ricerca), nel menù successivo possa digitare la stringa da ricercare e infine, nell’ultimo menù potrà leggere i risultati rappresentati dai primi dieci URL trovati relativi a quella stringa.

3.3 Realizzazione di un client per un aggregato di servizi

L’idea è quella di realizzare un client che inoltri una richiesta a un server relativo a un aggregato di servizi seguendo le istruzioni presenti in un documento riguardante tale aggregato (scritto ad esempio usando BPEL).Tale server, dopo aver ricevuto la richiesta conforme al linguaggio XSRL, la processa all’interno del suo aggregato di servizi e ritorna al client (il device mobile) la risposta, o un insieme di risposte, opportuno.Anche in questo caso, e per gli stessi motivi dell’applicazione precedente, come protocollo di comunicazione tra client e server è stato scelto HTTP.Un server in grado di assolvere a tale compito non è ancora stato realizzato ed è quindi stato necessario simulare il suo funzionamento mediante la creazione di un server simulato operante sulla stessa macchina del client.Questo server si limita a ricevere le richieste del client, stamparle a video e risponde alle richieste alternando in maniera pseudocasuale frasi precostruite.La funzionalità del software residente sul device mobile è invece quella di far creare all’utente una richiesta XSRL senza che egli conosca la sintassi del linguaggio ma semplicemente guidandolo attraverso un interfaccia grafica il più comprensibile possibile, tenendo conto anche delle restrizioni dovute all’uso di un device mobile che limita fortemente nella creazione delle GUI, soprattutto per le ridotte dimensioni del display.Come esempio è stata scelta la creazione da parte dell’utente di un’ipotetica vacanza, e il programma deve fungere da agenzia di viaggi ricevendo in input le richieste dell’utente (su meta, date, spesa, ecc.), inoltrarle, opportunamente formattate, a chi le processerà (nel

23

Page 24: zanoni.doc.doc

nostro caso il server simulato) e presentare all’utente finale i risultati ottenuti, come possibili alternative per la vacanza desiderata.Perché tutto ciò sia possibile è necessario capire le volontà dell’utente e riuscire a trascriverle nel linguaggio XSRL.Nonostante XSRL, seguendo la sintassi XML, risulti abbastanza human-readable è impensabile che l’utente finale scriva le sue richieste direttamente in tale linguaggio, è dunque necessario costruire un interfaccia che tramite una serie di maschere guidi l’utente a formulare la propria richiesta nella maniera a lui più semplice possibile.Tale scelta è ovviamente limitante per l’utente, che non avrà più la possibilità di scrivere la richiesta nella maniera esatta che egli desidera, l’interfaccia deve quindi poter permettere la maggior libertà possibile all’utente affinché egli riesca ad esprimere attraverso di essa tutti i propri desideri.Essendo lo scopo di questa sezione creare un client per l’interazione con un aggregato di servizi sfruttando XSRL e non creare un client per organizzare una vacanza non sono state realizzate funzionalità per far specificare all’utente nel minimo dettaglio le caratteristiche della propria vacanza ma solo gli aspetti fondamentali.In qualità di esempio verrà mostrato come un utente possa impostare la spesa massima della sua vacanza tramite i menù dell’applicazione realizzata tramite la figura 3.5.

Figura 3.5: Inserimento di dati nell’applicazione XSRL

Il primo menu, quello principale, serve ad indicare l’ambito della richiesta, il secondo a specificare se tale obiettivo deve essere raggiunto o se il suo raggiungimento è preferibile (in XSRL, in questo caso, la scelta comporta l’utilizzo del tag <VITAL-MAINT> in alternativa al tag <OPTIONAL-MAINT>), mentre il terzo è utilizzato per specificare i parametri desiderati.Tali passaggi permettono all’utente di esprimere la sua volontà di voler spendere meno di 500 euro nel modo più comodo possibile e permettono all’applicazione di interpretare tale richiesta e trasformarla nella stringa XSRL corrispondente.La richiesta XSRL costruita fino a questo punto è risultata essere la seguente:

<XSRL><ACHEIVE-ALL>

24

Page 25: zanoni.doc.doc

<VITAL-MAINT> <LESS>PrezzoTotale</LESS><THAN>500</THAN>

</VITAL-MAINT></ACHEIVE-ALL>

</XSRL>

Essendo l’idea di fondo quella di avere un business process e un interfaccia che permetta la costruzione di diverse richieste XSRL è ovviamente possibile ampliare e modificare la richiesta in qualsiasi momento aggiungendo informazioni riguardanti la località di soggiorno, l’hotel, il viaggio, ecc.Un esempio più complesso di richiesta può essere la seguente:l’utente vuole organizzare un viaggio a Roma e vuole spendere in totale meno di 400 euro, anche se preferirebbe spenderne meno di 300, e preferirebbe che la spesa relativa all’hotel fosse maggiore di 200 euro. Vuole inoltre categoricamente evitare il viaggio in aereo.Ecco la stringa XSRL derivata dall’inserimento di tali dati nelle apposite maschere dell’applicazione:

<XSRL><ACHEIVE-ALL>

<ATOMIC><EQUAL>destinazione "ROMA"</EQUAL></ATOMIC><PREFER>

<VITAL-MAINT><LESS> PrezzoTotale </LESS><THAN>300</THAN>

</VITAL-MAINT></PREFER><TO>

<VITAL-MAINT><LESS> PrezzoTotale </LESS><THAN>400</THAN>

</VITAL-MAINT></TO><OPTIONAL-MAINT>

<GREATER> PrezzoHotel </ GREATER ><THAN>200</THAN>

</ OPTIONAL -MAINT><VITAL-MAINT>

<NOT><EQUAL> Mezzo "Aereo" </EQUAL></NOT></VITAL-MAINT>

</ACHEIVE-ALL></XSRL>

Questo dimostra come l’applicazione, sfruttando la quasi totalità dei tag XSRL disponibili, riesca ad esprimere in maniera esaustiva le richieste postegli dall’utente.Tramite l’impiego dell’applicativo realizzato non è possibile l’utilizzo di alcuni tag XSRL perché non sono stati ritenuti utili per lo sviluppo dell’esempio proposto, tali tag sono comunque di facile aggiunta in caso di estensione dell’applicazione.Una volta creata la richiesta corrispondente al proprio desiderio di vacanza è sufficiente fornirla di un appropriata intestazione (una possibilità è quella di incapsularla nel corpo di un messaggio SOAP) e inviarla all’apposito server in grado di processarla.

25

Page 26: zanoni.doc.doc

Nel caso trattato, essendo simulato da un server fittizio, il servizio non ha nessun documento di specifica e il messaggio XSRL composto viene inviato con la sola aggiunta di una piccola intestazione simbolica.

26

Page 27: zanoni.doc.doc

Conclusioni

Riassumendo con questo documento si è voluto mostrare l’efficacia e le potenzialità dei web services e il loro utilizzo tramite semplici devices mobili quali i telefoni cellulari, mettendo in risalto come un sistema basato su servizi web superi agevolmente ostacoli quali la bassa capacità di calcolo di alcuni componenti e la più completa eterogeneità tra le varie componenti del sistema stesso.In primo luogo è stato preso in esame il caso della realizzazione di un client per un singolo servizio web presente in internet quale il motore di ricerca Google.Successivamente è stato realizzato un client in grado di effettuare richieste, formulate nell’apposito linguaggio XSRL, ad un aggregato di servizi.La costruzione del client per Google ha evidenziato la facilità con la quale un’applicazione riesce a comprendere come sia possibile utilizzare un servizio esterno e sfruttarne tutte le sue potenzialità mostrandole all’utente finale come proprie, mascherando quindi tutta la parte di calcolo distribuito, cosicché l’utente finale percepisca il sistema come un tutt’uno.Tutto ciò è reso possibile dalla comodità nell’uso web services legata agli standard SOAP e WSDL i quali riescono ad annullare le eterogeneità di piattaforma e di protocolli di rete possibili nella comunicazione tra le parti in causa.Risulta quindi evidente la duttilità e l’efficacia dei web services e appare chiaro come essi si stiano diffondendo nel web.Dalla popolarità sempre maggiore dei servizi web nasce l’esigenza di estenderne maggiormente le potenzialità creando nuovi meccanismi che permettano di comunicare non più con un singolo servizio, ma con aggregati di servizi.Questa è esattamente la tematica trattata nel secondo esempio nel quale si è dimostrata l’efficienza di tale ulteriore processo di astrazione e come esso sia possibile mediante l’introduzione di linguaggi e standard appositi sia per la descrizione del sistema (ad esempio BPEL) che per la possibilità di esprimere richieste (ad esempio XSRL).

27

Page 28: zanoni.doc.doc

Bibliografia

1. Andrew S. Tannenbaum. Reti di computer. 1988 Prentice Hall

2. Java. Concetti base della programmazione Java disponibili all’indirizzo http://developer.java.sun.com/developer/onlineTraining/new2java/

3. J2ME. Java 2 MicroEdition. Datasheet disponibile all’indirizzo http://java.sun.com/j2me/j2me-ds.pdf

4. Tim Lindholm Frank Yellin. Java Virtual Machine Specification, Second Edition. Disponibile all’indirizzo http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html

5. George Coulouris, Jean Dollimore, Tim Kindberg. Distributed Systems: Concepts and Design. 2002 Addison-Wesley

6. W3C, Simple Object Access Protocol (SOAP) 1.1. Disponibile all’indirizzo http://www.w3.org/TR/2000/NOTE-SOAP-20000508

7. W3C, Web Services Description Language (WSDL) 1.1. Disponibile all’indirizzo http://www.w3.org/TR/2001/NOTE-wsdl-20010315

8. BPEL. Business Process Execution Language for Web Services, agosto 2002. Disponibile all’indirizzo http://www-106.ibm.com/developerworks/library/ws-bpel/

9. M. Aiello, M.Papazoglou, J. Yang, M.Carman, M. Pistore, L. Serafini e P.Traverso, A request language for web-services based on planning and constraint satisfaction. In VLDB Workshop on Technologies for E-Services (TES02), 2002

10. M.Papazoglou, M. Aiello, M. Pistore e J. Yang, Planning for requests against web services. IEEE Data Engineering Bulletin, 25(4):41-46, 2002

11. Elliotte Rusty Harold. XML Bible. IDG Books Worldwide Inc.

12. Heather Kreger, Web Services Conceptual Architecture 1.0, 2001, IBM, Disponibile all’indirizzo http://www-4.ibm.com/software/solution/webservices/pdf/WSCA.pdf

13. M. Papazoglou et al. SOC: Service Oriented Computing manifesto, 2003. Disponibile all’indirizzo http://www.eusoc.net

14. Uddi.org, UDDI Technical White Paper. Disponibile all’indirizzo http://www.uddi.org/pubs/Iru_UDDI_Technical_White_Paper.pdf

28

Page 29: zanoni.doc.doc

15. Judith M. Myerson Advancing the Web services stack, 2002. Disponibile all’indirizzo http://www-106.ibm.com/developerworks/webservices/library/ws-wsa/

16. WSXL. Web Services Experience Language, aprile 2002. Disponibile all’indirizzo http://www-106.ibm.com/developerworks/webservices/library/ws-wsxl/

17. WSFL. Web Services Flow Language, maggio 2001. Disponibile all’indirizzo http://www-3.ibm.com/software/solutions/webservices/pdf/WSFL.pdf

18. WS Security. Web Services Security, aprile 2002. Disponibile all’indirizzo http://www-106.ibm.com/developerworks/webservices/library/ws-secure/

19. J2SE. Java 2 StandardEdition. Datasheet disponibile all’indirizzo http://java.sun.com/j2se/1.4/datasheet.1_4.html

29

Page 30: zanoni.doc.doc

Appendice A: Codice sorgente

Di seguito riportiamo il codice sorgente relativo a tutte le classi java realizzate nei due progetti, inoltre, per rendere più chiara la descrizione, ad ogni classe sarà associato il proprio class diagram, dal quale, sempre per semplicità, saranno tolti i campi e metodi relativi all’interfaccia grafica.Inoltre non sono presenti i class diagram delle classi rappresentanti menù dell’applicazione relativa al client per un aggregato di servizi, in quanto i loro campi sono costituiti solo da oggetti grafici e i loro metodi sono solo il costruttore e il metodo print (che serve a visualizzarne a video il contenuto). Descriviamo ora alcuni concetti generali:

1. Ogni progetto ha una classe che estende MIDlet per poter essere la classe di partenza dell’applicazione (una sorta di classe con il main)

2. Tutte le classi provviste di un interfaccia grafica implementano l’interfaccia CommandListener per poter gestire gli eventi

A.1 Client per il web service di Google

A.1.1 GoogleSearchMain.java

La classe che rappresenta il menù principale del programma dal quale si può accedere al menù per la ricerca di una stringa o, in eventuali sviluppi futuri, ad altri menù, come ad esempio quello per ricevere suggerimenti di sintassi per una stringa.

package google;

import javax.microedition.midlet.*;import javax.microedition.lcdui.*;

/** *@author Manuel Zanoni *@version 1.0 */ /** * This class represent the main menu */

public class GoogleSearchMain extends MIDlet implements CommandListener{

30

Page 31: zanoni.doc.doc

/*** variable that represent the display and what the program are showing to the user.<br>* Is possible to change the output to the user changing the current form displayed by this variable*/static Display display;/*** The main form*/static Form form;

//list of possible commandsprivate Command cmExit; private Command cmSearch; private Command cmSuggerimenti;

/** * Class constructor */public GoogleSearchMain()

{}

/** * Destructor of the MIDlet */ public void destroyApp(boolean unconditional) { notifyDestroyed(); }

public void pauseApp() { }

/** * Main method of the MIDlet that create and show the graphcal interface */ public void startApp() { //get display display = Display.getDisplay(this); //create the buttons cmExit = new Command("Exit", Command.EXIT, 1); cmSuggerimenti = new Command("Suggerimenti", Command.SCREEN, 3); cmSearch = new Command("Ricerca", Command.SCREEN, 2);

// create the form form = new Form("Google Main"); StringItem sItem = new StringItem(null,"Scegli l'operazione da effettuare!\n"); //add the components to the form form.append(sItem); form.addCommand(cmExit); form.addCommand(cmSuggerimenti); form.addCommand(cmSearch); //add the command listener form.setCommandListener(this); //set the form as the current one on the display

31

Page 32: zanoni.doc.doc

display.setCurrent(form); } /** * Method who specifies the action to do when a determinate command is listened. * Possible Command are: * cmExit -> Terminate the application * cmSearch -> Go to the Search menu * @param c The command listened * @param s The Displayable variable */

public void commandAction(Command c, Displayable s){ if (c == cmExit){ destroyApp(false); notifyDestroyed(); }else if (c == cmSearch){ Operations operations = new Operations();

try{operations.call(1);}//specify to do a searchcatch(Exception e){}

} }

}

A.1.2 Connection2Server.java

La classe usata per effettuare le connessioni HTTP al server, inviare le richieste e ricevere le risposte

package google;

import java.io.*;import javax.microedition.io.*;/** *@author Manuel Zanoni *@version 1.0 */ /** * The class that is responsible to the connection with the server.<br> * Using this class is possible to estabilish the HTTP connection, send the request * and recive the response */

public class Connection2Server{

32

Page 33: zanoni.doc.doc

/*** The connection object*/private HttpConnection connection;//the set of I/O sreamsprivate OutputStream os;private InputStream is;private DataInputStream dis;/*** A byte array used to send the request in the outputstream and recive the response from the inputsream*/private byte byteArray[];/*** A string that represent the eventual SOAP action to send in the header of the* HTTP request*/private String SOAPAction;

/*** Class constructor.<br>* It create an instance of this class setting the byteArray and SOAPAction fields.* @param request Represent the request to do to the server stored in a byte array* @param action Represent the SOAP action to specified in the header of the connection request*/public Connection2Server(byte request[], String action){byteArray=request;SOAPAction=action;}

/*** This method make the connection, send the request stored in byteArray field, * read the response from the server using byteArray field and convert it into a String* @return server's answer as a string*/ public String sendRecive() throws IOException{ //open the connection connection=(HttpConnection)Connector.open("http://api.google.com/search/beta2",Connector.READ_WRITE,true); //send the header information connection.setRequestProperty("SOAPAction",SOAPAction); connection.setRequestProperty("Content-Type","text/xml"); connection.setRequestProperty("Content-Length","" + byteArray.length); connection.setRequestMethod("POST");

//send the request os=connection.openOutputStream();

os.write(byteArray,0,byteArray.length);

os.close();

//read the answer is=connection.openInputStream(); dis=new DataInputStream(is); String fullReply = new String();

String reply="";while (true) {

try{dis.readFully(byteArray,0,100);}catch(Exception e){break;}

33

Page 34: zanoni.doc.doc

reply=new String(byteArray,0,100);fullReply=fullReply+reply;

} is.close(); dis.close(); //return the answer as a String return fullReply;

}

}

A.1.3 Operations.java

Classe che contiene le operazioni da effettuare e I menu da mostrare a seconda della scelta dell’utente (nel nostro caso solo la ricerca di una stringa).

package google;

import java.io.*;import javax.microedition.lcdui.*;

/** *@author Manuel Zanoni *@version 1.0 */ /** * This class represent the menu of the selected operation */public class Operations implements CommandListener{//list of possible formsForm frmResults;Form frmRequestError;

//the list of the commandprivate Command cmBack;private Command cmOk;//the objects of the formprivate TextBox tbQuery;//variables that represent the values of the form's objectsString input;/*** an integer that represent the current position in the respons or request message*/static int pos;

34

Page 35: zanoni.doc.doc

/** * Class constructor */public Operations(){}

/** * Method who builds the interface for the operation choosed * The only operation implemented is Search * @param IDrichiesta the id of the request that specifies the operaion to do (the only operation implemented is Search with ID=1) */void call(int IDRequest) {cmBack = new Command("Back", Command.BACK, 1);cmOk = new Command("OK", Command.OK, 2);

switch(IDRequest){case 1: tbQuery = new TextBox("Inserisci la stringa", "", 25, 0);

tbQuery.addCommand(cmBack); tbQuery.addCommand(cmOk); tbQuery.setCommandListener(this);

GoogleSearchMain.display.setCurrent(tbQuery); break;

default: Form frmRequestError=new Form("Errore");frmRequestError.append("richiesta non riconosciuta!\n"); frmRequestError.addCommand(cmBack);frmRequestError.setCommandListener(this); GoogleSearchMain.display.setCurrent(frmRequestError);return;

}}

/** * Method who builds the request, sends it to the server and displays the results */private void doSearch() throws IOException{

byte byteArray[];String output;String address;int founded;

//set max result number to 10Parser parser=new Parser(input,10);byteArray=parser.createSearchString();

//connect to the server to send the request Connection2Server c= new Connection2Server(byteArray,"urn:GoogleSearchAction"); output=new String(c.sendRecive()); //Print the result frmResults=new Form("Risultati"); frmResults.append("Ecco i risultati trovati!\n"); pos=parser.control(output); if(pos==0){ Form frmRequestError=new Form("Errore");

frmRequestError.append("Il server non ha accettato la richiesta!\n"); frmRequestError.addCommand(cmBack);

35

Page 36: zanoni.doc.doc

frmRequestError.setCommandListener(this); GoogleSearchMain.display.setCurrent(frmRequestError);return;

} output=output.substring(pos,output.length()); founded=parser.foundedURL(output); if(founded==0){ frmResults.append("La ricerca non ha portato nessun risultato!\n"); return; } pos=pos+2; output=output.substring(pos,output.length()); for(int i=0;i<founded;i++) { address=parser.getURL(output); frmResults.append(""+(i+1)+": "); int j=0; while(j<address.length()-25) { StringItem si=new StringItem(null,address.substring(j,j+25)); frmResults.append(si); frmResults.append(" \n"); j=j+25; } StringItem si=new StringItem(null,address.substring(j,address.length())); frmResults.append(si); frmResults.append("\n"); output=output.substring(pos,output.length()); } frmResults.addCommand(cmBack); frmResults.setCommandListener(this); GoogleSearchMain.display.setCurrent(frmResults); return;

}/** * Method who specifies the action to do when a determinate command is listened. * Possible Command are: * cmBack -> return to the main menu * cmOK -> call the doSearch method * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmBack){ GoogleSearchMain.display.setCurrent(GoogleSearchMain.form); }else if (c == cmOk){ input=new String(tbQuery.getString()); GoogleSearchMain.display.setCurrent(GoogleSearchMain.form); try{doSearch();}catch(Exception e){} } }}

36

Page 37: zanoni.doc.doc

A.1.4 Parser.java

Classe che offre le operazioni per scrivere una richiesta sintatticamente corretta e leggere la risposta.

package google;

import java.io.*;

/** *@author Manuel Zanoni *@version 1.0 *//** * This class represent the parser who has the task to write * the request and read the response */public class Parser{/*** The string that represent the string to search*/private String queryString;/*** The max number of result we want to have in the response*/private int maxRes;/*** The String that represent the request*/private String request; /** * Class constructor *@param input The string to search *@max The max number of result */public Parser(String input, int max){queryString=input; maxRes=max;}

/** * Method who creates the appropriate SOAP string to do the search * It calls some method to write the string on blocks */

37

Page 38: zanoni.doc.doc

public byte[] createSearchString() throws IOException{

byte byteArray[];ByteArrayOutputStream baos = new ByteArrayOutputStream();writeHeader();openSearchOperation("doGoogleSearch");

writeKey(); writeBody();

closeSearchOperation("doGoogleSearch");writeTailer();baos.write(request.getBytes());

byteArray=baos.toByteArray(); return byteArray;} /** * Method who creates the header of the SOAP message */private void writeHeader() throws IOException{

request=new String("<?xml version='1.0' encoding='UTF-8'?>\n\r\n\r<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\">\n\r<SOAP-ENV:Body>\n\r");} /** * Method who creates the tailer of the SOAP message */private void writeTailer() throws IOException{

request=request+"</SOAP-ENV:Body>\n\r</SOAP-ENV:Envelope> \n\r";} /** * Method who starts the search operation */private void openSearchOperation(String op) throws IOException{

request=request+"<ns1:"+op+" xmlns:ns1=\"urn:GoogleSearch\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n\r";} /** * Method who finishes the search operation */private void closeSearchOperation(String op) throws IOException{

request=request+"</ns1:"+op+">\n\r";} /** * Method who writes the google key */private void writeKey() throws IOException{

request=request+"<key xsi:type=\"xsd:string\">G9uce/tQFHJY7vyPliRPt/5/1v3K06LA</key>\n\r";} /** * Method who writes the body of the SOAP message */private void writeBody() throws IOException{

request=request+"<q xsi:type=\"xsd:string\">"+ queryString +"</q>\n\r<start xsi:type=\"xsd:int\">0</start>\n\r<maxResults xsi:type=\"xsd:int\">" + maxRes + "</maxResults>\n\r<filter xsi:type=\"xsd:boolean\">true</filter>\n\r<restrict xsi:type=\"xsd:string\"></restrict>\n\r<safeSearch

38

Page 39: zanoni.doc.doc

xsi:type=\"xsd:boolean\">false</safeSearch>\n\r<lr xsi:type=\"xsd:string\"></lr>\n\r<ie xsi:type=\"xsd:string\"></ie>\n\r<oe xsi:type=\"xsd:string\"></oe>\n\r";} /** * Method who finds in the SOAP response message how many results there are *@param s The string representing the SOAP message *@return the numbers of results */ public int foundedURL(String s){

String match=new String("ns1:ResultElement[");String sub;int ret;char c;ret=0;

for(int i=0;i<s.length()-match.length();i++){

sub=new String(s.substring(i,i+match.length()));if(sub.equals(match)){ i=i+match.length();

while(true){

c=s.charAt(i);i++;Operations.pos=i;if (c==93) break;ret=ret+c-48;ret=ret*10;

}break;

}}ret=ret/10;

return ret;

} /** * Method who controls if the response massage is a vaild one or a SOAP fault *@param s The string representing the SOAP message *@return 0 if the message is a SOAP fault one or the index of the string in which start the body of the SOAP message */public int control(String s){

String match=new String("<SOAP-ENV:Body>");String sub;String response;int index;char c;index=0;response=new String();for(int i=0;i<s.length()-match.length();i++){

sub=new String(s.substring(i,i+match.length()));if(sub.equals(match)){ i=i+match.length();

index=i;

39

Page 40: zanoni.doc.doc

while(true){c=s.charAt(i);i++;if (c=='<') break;

}while(true){

c=s.charAt(i);i++;if (c=='>') break;

response=response+c;

}break;}

}if(response.equals("ns1:doGoogleSearchResponse xmlns:ns1=\"urn:GoogleSearch\"

SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\""))return index+response.length();

else return 0;}

/** * Method who parses the response massage to get an URL *@param s The string representing the SOAP message *@return a string representing an URL */public String getURL(String s){

String match=new String("<URL xsi:type=\"xsd:string\">");String sub;String response;int index;char c;response=new String();index=0;for(int i=0;i<s.length()-match.length();i++){

sub=new String(s.substring(i,i+match.length()));if(sub.equals(match)){ i=i+match.length();

while(true){c=s.charAt(i);i++;if (c=='<') break;response=response+c;

}index=i;break;}

}match=new String("</item>");for(int i=index;i<s.length()-match.length();i++){

sub=new String(s.substring(i,i+match.length()));if(sub.equals(match))

{Operations.pos=i;break;

40

Page 41: zanoni.doc.doc

}}

return response;}

}

A.2 Client per un aggregato di servizi

A.2.1 XSRLQueryMain.java

La classe che rappresenta il menù principale del programma dal quale si può accedere a tutti gli altri menù per la formulazione della stringa XSRL o inviare la stringa stessa al server.

package xsrl;

import javax.microedition.midlet.*;import javax.microedition.lcdui.*;

/** *@author Manuel Zanoni *@version 1.0 */ /** * This class represent the main menu */public class XSRLQueryMain extends MIDlet implements CommandListener{/*** variable that represent the display and what the program are showing to the user.<br>* Is possible to change the output to the user changing the current form displayed by this variable*/static Display display;/*** The main form*/static Form form;

//list of possible commandsprivate Command cmExit; private Command cmPlace; private Command cmDate;private Command cmAmount; private Command cmTravel; private Command cmHotel;

41

Page 42: zanoni.doc.doc

private Command cmSend;

//list of all the menus reachable from the main menuprivate MenuPlace menuPlace; private MenuTotalAmount menuTotalAmount; private MenuTravel menuTravel; private MenuResponse menuResponse; private MenuHotel menuHotel; private MenuDate menuDate;

/** * Class constructor */public XSRLQueryMain()

{}

/** * Destructor of the MIDlet */

public void destroyApp(boolean unconditional) { notifyDestroyed(); }

public void pauseApp() { }/** * Main method of the MIDlet that create and show the graphcal interface */ public void startApp() { //get display display = Display.getDisplay(this); //create the buttons cmExit = new Command("Exit", Command.EXIT, 1); cmPlace = new Command("Localita'", Command.SCREEN, 2); cmDate = new Command("Date", Command.SCREEN, 3);

cmAmount = new Command("Spesa", Command.SCREEN, 4);cmTravel = new Command("Viaggio", Command.SCREEN, 5);cmHotel = new Command("Hotel", Command.SCREEN, 6);cmSend = new Command("Invia la richiesta", Command.SCREEN, 7);

// create the form form = new Form("Menu Principale"); StringItem sItem = new StringItem(null,"Organizza la tua vacanza!\n"); //add the components to the form form.append(sItem); form.addCommand(cmExit); form.addCommand(cmPlace); form.addCommand(cmDate); form.addCommand(cmAmount); form.addCommand(cmTravel); form.addCommand(cmHotel); form.addCommand(cmSend); //add the command listener

42

Page 43: zanoni.doc.doc

form.setCommandListener(this);

//create all the Menu reachable from this menumenuPlace= new MenuPlace();menuTotalAmount= new MenuTotalAmount();menuTravel= new MenuTravel();menuHotel= new MenuHotel();menuDate= new MenuDate();

//initialize the string representing the request

Parser.init(); //set the form as the current one on the display display.setCurrent(form); }

/** * Method who specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmExit -> Terminate the application<br> * cmPlace -> Go to the Place menu<br> * cmDate -> Go to the Date menu<br> * cmHotel -> Go to the Hotel menu<br> * cmTravel -> Go to the Travel menu<br> * cmAmount -> Go to the Amount menu<br> * cmSend -> Send the request to the server<br> * @param c The command listened * @param s The Displayable variable */

public void commandAction(Command c, Displayable s){ if (c == cmExit){ destroyApp(false); notifyDestroyed(); } else if (c == cmPlace){ menuPlace.print();

}else if (c == cmDate){

menuDate.print();}else if (c == cmAmount){

menuTotalAmount.print();}else if (c == cmHotel){

menuHotel.print();}else if (c == cmTravel){

menuTravel.print();} else if (c == cmSend){

String reply="Errore\n";//create the connection objectConnection2Server c2s=new Connection2Server(Parser.print().getBytes(),"");try{//send the request and recive the responsereply=c2s.sendRecive();

43

Page 44: zanoni.doc.doc

}catch (Exception e){System.out.println(e);}//print the response in its menumenuResponse= new MenuResponse(reply);

} }

}

A.2.2 Connection2Server.java

La classe usata per effettuare le connessioni HTTP al server, inviare le richieste e ricevere le risposte

package xsrl;

import java.io.*;import javax.microedition.io.*;

/** *@author Manuel Zanoni *@version 1.0 */ /** * The class that is responsible to the connection with the server.<br> * Using this class is possible to estabilish the HTTP connection, send the request * and recive the response */public class Connection2Server{/*** The connection object*/private HttpConnection connection;

//the set of I/O sreamsprivate OutputStream os;private InputStream is;private DataInputStream dis;/*** A byte array used to send the request in the outputstream and recive the response from the inputsream*/private byte byteArray[];/*** A string that represent the eventual SOAP action to send in the header of the* HTTP request

44

Page 45: zanoni.doc.doc

*/private String SOAPAction;

/*** Class constructor.<br>* It create an instance of this class setting the byteArray and SOAPAction fields.* @param request Represent the request to do to the server stored in a byte array* @param action Represent the SOAP action to specified in the header of the connection request*/public Connection2Server(byte request[], String action){byteArray=request;SOAPAction=action;}/*** This method make the connection, send the request stored in byteArray field, * read the response from the server using byteArray field and convert it into a String* @return server's answer as a string*/ public String sendRecive() throws IOException{ //open the connection connection=(HttpConnection)Connector.open("http://localhost",Connector.READ_WRITE,true); //send the header information connection.setRequestProperty("SOAPAction",SOAPAction); connection.setRequestProperty("Content-Type","text/xml"); connection.setRequestProperty("Content-Length","" + byteArray.length); connection.setRequestMethod("POST");

//send the request os=connection.openOutputStream();

os.write(byteArray,0,byteArray.length);

os.close();

//read the answer is=connection.openInputStream(); dis=new DataInputStream(is); String fullReply = new String();

String reply="";while (true) {

try{dis.readFully(byteArray,0,1);}catch(Exception e){break;}

reply=new String(byteArray,0,1);fullReply=fullReply+reply;

} is.close(); dis.close(); //return the answer as a String return fullReply;

}

}

A.2.3 Parser.java

45

Page 46: zanoni.doc.doc

Classe che offre le operazioni per scrivere una richiesta sintatticamente corretta interpretando i comandi inseriti dall’utente nelle maschere dell’interfaccia grafica.

package xsrl;

import java.util.*;/** *@author Manuel Zanoni *@version 1.0 */ /** * This class represent the parser who has the task to modify * the request */public class Parser{/*** A string Vector whose elements are the single parts of the request*/static private Vector queryString;

static public void init(){queryString=new Vector();queryString.insertElementAt("<XSRL>\n",0);queryString.insertElementAt(" <ACHEIVE-ALL>\n",1);queryString.insertElementAt(" </ACHEIVE-ALL>\n",2);queryString.insertElementAt("</XSRL>\n",3);

}/** * Add a part of the request to the vector * @param string2Write The string to write that represent a prt of the request * @param row The position in which write the part of the request */static public void write(String string2Write, int row){

if(queryString.elementAt(row-1).toString().length()<2)queryString.removeElementAt(row-1);

queryString.insertElementAt(string2Write,row-1);}/** * Delete a part of the request to the vector overwriting that string with an empty one * @param row The position of the request's part to delete */static public void delete (int row){

queryString.removeElementAt(row-1);queryString.insertElementAt("\n",row-1);

}

46

Page 47: zanoni.doc.doc

/** * Return a string representing the entire request * @return the entire request putted in a string */static public String print(){

String entireRequest="";for(int i=0;i<Parser.queryString.size();i++)

entireRequest=entireRequest+queryString.elementAt(i);return entireRequest;}

/** * Scan the Vector to find the position in which a new request's part can be written * @return the position in which a new request's part can be written */static public int rowsCounter (){

return queryString.size()-1;}

/** * Convert a Date object to the corresponding string * @param date2Convert the date to convert into a string * @return the string representing the date passed as parameter */static public String date2String(Date date2Convert){

Calendar c = Calendar.getInstance(); c.setTime(date2Convert); int y = c.get(Calendar.YEAR); int m = c.get(Calendar.MONTH) + 1; int day = c.get(Calendar.DATE); String t = (day<10? "0": "")+day+"/"+(m<10? "0": "")+m+"/"+(y<10? "0": "")+y; return t;

}}

A.2.4 Request.java

La classe rappresenta la superclasse che deve essere estesa da tutte le classi che rappresentano oggetti che vogliono effettuare una richiesta. Contiene infatti metodi e campi necessari alla classe Parser per formulare la richiesta.

package xsrl;/** *@author Manuel Zanoni

47

Page 48: zanoni.doc.doc

*@version 1.0 */ /** * This class represent the superclass for all class who wants to * write a part of the request.<br> * In this way we are sure that all these classes inherit its protected fields and methods */public class Request{/*** represent the row in the request in which the part of the request is written<br>* once setted different from 0 this field never change its value*/protected int row;/*** tells if this part of request has an optional goal*/protected boolean optional;/*** tells if this part of request has a vital goal*/protected boolean vital;/*** represent the optional goal of this part of the request*/protected String stringOpt;/*** represent the vital goal of this part of the request*/protected String stringVit;/*** represent the entire part of the request*/protected String query;/*** represent the kind of tag of this part of request:<br>* 1 -> ATOMIC tag <br>* 2 -> VITAL-MAINT or OPTIONAL-MAINT tag <br>* 3 -> VITAL or OPTIONAL tag <br>*/protected int tag;

/*** represent the opening tag*/private String tag1String;/*** represent the closing tag*/private String tag2String;

/** * Class constructor */public Request(){}

/**

48

Page 49: zanoni.doc.doc

* Method who build the part of the request passed.<br> * The build process is based on the value of the class fields.<br> * The resulted string is putted into the class field query * @param string2Build The string to build */

protected void buildString(String string2Build){switch(tag){

//if tag=1 simply add the atomic start and end tag to the string to biuldcase 1: tag1String="<ATOMIC>";

tag2String="</ATOMIC>\n";query=tag1String+ string2Build + tag2String;break;

//if tag=2case 2: if(row!=0) //if this part of request is alredy writed

Parser.delete(row); //delete it (for overwrite it)if(optional) //if optional field is true add optional-maint start and end tag to the

string to buil{if(stringOpt==null)

stringOpt=string2Build;tag1String="<OPTIONAL-MAINT>";tag2String="</OPTIONAL-MAINT>\n";query=tag1String+ stringOpt + tag2String;

}if(vital) //if vital field is true add vital-maint start and end tag to the string to buil{

if(stringVit==null)stringVit=string2Build;

tag1String="<VITAL-MAINT>";tag2String="</VITAL-MAINT>\n";query=tag1String+ stringVit + tag2String;

}//if each optional and vital tag is true write prefer optional goal to vital goalif(vital && optional)

query="<PREFER><VITAL-MAINT>" +stringOpt +"</VITAL-MAINT></PREFER><TO><VITAL-MAINT>"+ stringVit +"</VITAL-MAINT></TO>\n";

break;//if tag=3 there is the same process we had for tag=2 but the tag to add are now// VITAL and OPTIONAL and not VITAL-MAINT and OPTIONAL-MAINTcase 3:if(row!=0)

Parser.delete(row);if(optional)

{if(stringOpt==null)

stringOpt=string2Build;tag1String="<OPTIONAL>";tag2String="</OPTIONAL>\n";query=tag1String+ stringOpt + tag2String;

}if(vital) {

if(stringVit==null)stringVit=string2Build;

tag1String="<VITAL>";tag2String="</VITAL>\n";query=tag1String+ stringVit + tag2String;

49

Page 50: zanoni.doc.doc

}if(vital && optional)

query="<PREFER><VITAL>" +stringOpt +"</VITAL></PREFER><TO><VITAL>"+ stringVit +"</VITAL></TO>\n";

break;

}}

}

A.2.5 MenuDate.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the hotel amount * in which is possible to choose if go to the initial date menu * or to the final date menu */public class MenuDate implements CommandListener{/*** The form of this menu*/static Form frmDate;//the list of the commandprivate Command cmStart;private Command cmEnd;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuInitialDate menuInitialDate;private MenuFinalDate menuFinalDate;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuDate(){

menuInitialDate=new MenuInitialDate();menuFinalDate=new MenuFinalDate();frmDate=new Form("Data");

cmStart = new Command("Inizio", Command.SCREEN, 2);cmEnd = new Command("Fine", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmDate.addCommand(cmBack); frmDate.addCommand(cmStart); frmDate.addCommand(cmEnd);

50

Page 51: zanoni.doc.doc

String s = new String("Imposta le date di inizio e fine della tua vacanza\n");frmDate.append(s);}

/*** Print out the menu*/void print(){

frmDate.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmDate);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * cmStart -> go to the initial date menu<br> * cmEnd -> go to the final date menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmStart){ menuInitialDate.print(); } else if (c == cmEnd){ menuFinalDate.print(); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); }

}

}

A.2.6 MenuFinalDate.java

package xsrl;

import javax.microedition.lcdui.*; import java.util.*;/** *@author Manuel Zanoni *@version 1.0 */ /** * The menu in which is possible to set the final date of the travel */public class MenuFinalDate extends Request implements CommandListener{/*** The form of this menu*/private Form frmFinalDate;//the list of the commandprivate Command cmCancel;private Command cmBack;

51

Page 52: zanoni.doc.doc

private Command cmOK;//the objects of the formprivate DateField dateField;//variables that represent the values of the form's objectsprivate String stringDate;

/*** Class constructor<br>* set row to 0 * that represents that this part of the request is not yet writted.<br>* moreover set tag to 3 that represents that the possible tag for this part of request* are VITAL or OPTIONAL*/public MenuFinalDate(){

tag=3;row=0;stringDate=new String("");query=new String("");}

/*** Print out the menu*/void print(){

String s;frmFinalDate=new Form("Data di fine");

cmOK = new Command("OK", Command.OK, 2);

if(stringDate.length()<1)//if there wasn't specified an final date yet{//display a menu in which is possible to set an final datecmBack = new Command("Back", Command.BACK, 1);frmFinalDate.addCommand(cmBack);s = new String("Scegli il giorno di fine vacanze!\n");dateField=new DateField(null,DateField.DATE);dateField.setDate(new Date(System.currentTimeMillis()));frmFinalDate.append(s); frmFinalDate.append(dateField);}

else //if there was specified an final date yet{//display a menu in which is possible to see and cancel the final date set before

cmCancel = new Command("Cancella", Command.CANCEL, 1);frmFinalDate.addCommand(cmCancel);

s = new String("La data di fine impostata e'\n" + stringDate ); frmFinalDate.append(s); }

frmFinalDate.addCommand(cmOK);

frmFinalDate.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmFinalDate);

}

/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to date menu <br> * cmCancel -> delete the final date<br>

52

Page 53: zanoni.doc.doc

* cmOK -> add a new final date<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmCancel){ vital=false; stringDate=new String(""); print(); Parser.delete(row); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuDate.frmDate); } else if (c == cmOK){ if(stringDate.length()<1){ vital=true; stringDate=new String(Parser.date2String(dateField.getDate())); buildString("<EQUAL>dataFine "+stringDate+"</EQUAL>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); } XSRLQueryMain.display.setCurrent(MenuDate.frmDate);

}

}

}

A.2.7 MenuInitialDate.java

package xsrl;

import javax.microedition.lcdui.*; import java.util.*;/** *@author Manuel Zanoni *@version 1.0 */ /** * The menu in which is possible to set the initial date of the travel */public class MenuInitialDate extends Request implements CommandListener{/*** The form of this menu*/private Form frmInitialDate;//the list of the commandprivate Command cmCancel;private Command cmBack;private Command cmOK;//the objects of the formprivate DateField dateField;//variables that represent the values of the form's objectsprivate String stringDate;

53

Page 54: zanoni.doc.doc

/*** Class constructor<br>* set row to 0 * that represents that this part of the request is not yet writted.<br>* moreover set tag to 3 that represents that the possible tag for this part of request* are VITAL or OPTIONAL*/public MenuInitialDate(){

tag=3;row=0;stringDate=new String("");query=new String("");}

/*** Print out the menu*/void print(){

String s;frmInitialDate=new Form("Data di inizio");

cmOK = new Command("OK", Command.OK, 2);

if(stringDate.length()<1)//if there wasn't specified an initial date yet{//display a menu in which is possible to set an initial datecmBack = new Command("Back", Command.BACK, 1);frmInitialDate.addCommand(cmBack);s = new String("Scegli il giorno di inizio vacanze!\n");dateField=new DateField(null,DateField.DATE);dateField.setDate(new Date(System.currentTimeMillis()));frmInitialDate.append(s); frmInitialDate.append(dateField);}

else //if there was specified an initial date yet{//display a menu in which is possible to see and cancel the initial date set before

cmCancel = new Command("Cancella", Command.CANCEL, 1);frmInitialDate.addCommand(cmCancel);

s = new String("La data di inizio impostata e'\n" + stringDate ); frmInitialDate.append(s); }

frmInitialDate.addCommand(cmOK);

frmInitialDate.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmInitialDate);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to date menu <br> * cmCancel -> delete the initial date<br> * cmOK -> add a new initial date<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmCancel){ vital=false; stringDate=new String("");

54

Page 55: zanoni.doc.doc

print(); Parser.delete(row); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuDate.frmDate); } else if (c == cmOK){ if(stringDate.length()<1){ vital=true; stringDate=new String(Parser.date2String(dateField.getDate())); buildString("<EQUAL>dataInizio "+stringDate+"</EQUAL>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); } XSRLQueryMain.display.setCurrent(MenuDate.frmDate);

}

}

}

A.2.8 MenuHotel.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the hotel amount * in which is possible to go to the hotel amount menu */public class MenuHotel implements CommandListener{/*** The form of this menu*/static Form frmHotel;//the list of the commandprivate Command frmhotelAmount;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuHotelAmount menuHotelAmount;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuHotel(){

menuHotelAmount=new MenuHotelAmount();frmHotel=new Form("Hotel");

55

Page 56: zanoni.doc.doc

frmhotelAmount = new Command("Spesa Hotel", Command.SCREEN, 2); cmBack = new Command("Back", Command.BACK, 1); frmHotel.addCommand(cmBack); frmHotel.addCommand(frmhotelAmount);

String s = new String("Imposta il tuo soggiorno\n\n");frmHotel.append(s);}

/*** Print out the menu*/void print(){

frmHotel.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmHotel);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * frmhotelAmount -> go to the hotel amount menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == frmhotelAmount){ menuHotelAmount.print(); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); }

}

}

A.2.9 MenuHotelAmount.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the hotel amount * in which is possible to choose if go to the hotel amount wanted menu * or to the hotel amount prefered menu */public class MenuHotelAmount implements CommandListener{/*** The form of this menu*/static Form frmHotelAmount;//the list of the commandprivate Command cmWant;

56

Page 57: zanoni.doc.doc

private Command cmPrefer;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuWPHotelAmount menuWPHotelAmount;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuHotelAmount(){

menuWPHotelAmount=new MenuWPHotelAmount();frmHotelAmount=new Form("Spesa Hotel");

cmWant = new Command("Voglio", Command.SCREEN, 2);cmPrefer = new Command("Preferisco", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmHotelAmount.addCommand(cmBack); frmHotelAmount.addCommand(cmWant); frmHotelAmount.addCommand(cmPrefer);

String s = new String("Imposta la spesa del tuo soggiorno\n\n");frmHotelAmount.append(s);}

/*** Print out the menu*/void print(){

frmHotelAmount.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmHotelAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the hotel menu <br> * cmWant -> go to the hotel amount wanted menu<br> * cmPrefer -> go to the hotel amount prefered menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmWant){ menuWPHotelAmount.print(true); } else if (c == cmPrefer){ menuWPHotelAmount.print(false); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuHotel.frmHotel); }

}

}

57

Page 58: zanoni.doc.doc

A.2.10 MenuPlace.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the place * in which is possible to set the destination of the travel */public class MenuPlace extends Request implements CommandListener{/*** The form of this menu*/private Form frmPlace;//the list of the commandprivate Command cmCancel;private Command cmBack;private Command cmOK;//the objects of the formprivate TextField tfPlace;//variables that represent the values of the form's objectsprivate String destination;

/*** Class constructor<br>* set row to 0 * that represents that this part of the request is not yet writted.<br>* moreover set tag to 1 that represents that the tag for this part of request* is ATOMIC*/public MenuPlace(){

tag=1;row=0;destination=new String("");query=new String("");}

/*** Print out the menu*/void print(){

String s;frmPlace=new Form("Destinazione");

cmOK = new Command("OK", Command.OK, 2);

if(destination.length()<1)//if there wasn't specified a destination yet{//display a menu in which is possible to set a destinationcmBack = new Command("Back", Command.BACK, 1);frmPlace.addCommand(cmBack);s = new String("Digita il luogo dove vuoi andare!\n");StringItem sItem = new StringItem(null,s);frmPlace.append(sItem); tfPlace=new TextField("Luogo", "", 20, TextField.ANY);

58

Page 59: zanoni.doc.doc

frmPlace.append(tfPlace);}

else//if there was specified a destination yet{//display a menu in which is possible to see and cancel the destination set before

cmCancel = new Command("Cancella", Command.CANCEL, 1);frmPlace.addCommand(cmCancel);

s = new String("Il luogo desiderato e'\n" + destination ); StringItem sItem = new StringItem(null,s); frmPlace.append(sItem); }

frmPlace.addCommand(cmOK);

frmPlace.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmPlace);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * cmCancel -> delete the destination<br> * cmOK -> add a new destination<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmCancel){ destination=new String(""); print(); Parser.delete(row); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); } else if (c == cmOK){ if(destination.length()>1) XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); else if(tfPlace.getString().length()>1){ destination=new String(tfPlace.getString()); XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); buildString("<EQUAL>destinazione \""+destination+"\"</EQUAL>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}

}}

A.2.11 MenuResponse.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0

59

Page 60: zanoni.doc.doc

*/ /** * The menu in which is possible to see the server's response */public class MenuResponse implements CommandListener{/*** The form of this menu*/private Form frmResponse;//the list of the commandprivate Command cmBack;/*** Class constructor<br>* create all the component of the form* and add them to the form and pint it*/public MenuResponse(String s){

frmResponse=new Form("Risposta del server");

cmBack = new Command("Back", Command.BACK, 1); frmResponse.addCommand(cmBack);

frmResponse.setCommandListener(this); frmResponse.append(s);

XSRLQueryMain.display.setCurrent(frmResponse);}

/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); }

}

}

A.2.12 MenuTotalAmount.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the travel * in which is possible to choose if go to the total amount wanted or prefered menu */public class MenuTotalAmount implements CommandListener{

60

Page 61: zanoni.doc.doc

/*** The form of this menu*/static Form frmTotalAmount;//the list of the commandprivate Command cmWant;private Command cmPrefer;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuWPAmount menuWPAmount;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuTotalAmount(){

menuWPAmount=new MenuWPAmount();frmTotalAmount=new Form("Spesa");

cmWant = new Command("Voglio", Command.SCREEN, 2);cmPrefer = new Command("Preferisco", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmTotalAmount.addCommand(cmBack); frmTotalAmount.addCommand(cmWant); frmTotalAmount.addCommand(cmPrefer);

String s = new String("Imposta la tua spesa\n\n");frmTotalAmount.append(s);}

/*** Print out the menu*/void print(){

frmTotalAmount.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmTotalAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * cmWant -> go to the total amount wanted menu<br> * cmPrefer -> go to the total amount prefered menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmWant){ menuWPAmount.print(true); } else if (c == cmPrefer){ menuWPAmount.print(false); } else if (c == cmBack){

61

Page 62: zanoni.doc.doc

XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); }

}

}

A.2.13 MenuTransport.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the travel * in which is possible to choose if go to the transport wanted or prefered menu * or to the transport don't wanted or don't prefered menu */public class MenuTransport implements CommandListener{/*** The form of this menu*/static Form frmTravel;//the list of the commandprivate Command cmWant;private Command cmPrefer;private Command cmWantNot;private Command cmPreferNot;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuWPTransport menuWPTransport;private MenuWPNotTransport menuWPNotTransport;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/

public MenuTransport(){

menuWPTransport=new MenuWPTransport();menuWPNotTransport=new MenuWPNotTransport();frmTravel=new Form("Mezzo di trasporto");

cmWantNot = new Command("Voglio evitare", Command.SCREEN, 4);cmPreferNot = new Command("Preferisco evitare", Command.SCREEN, 5);

cmWant = new Command("Voglio", Command.SCREEN, 2);cmPrefer = new Command("Preferisco", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmTravel.addCommand(cmBack); frmTravel.addCommand(cmWant); frmTravel.addCommand(cmPrefer);

62

Page 63: zanoni.doc.doc

frmTravel.addCommand(cmWantNot); frmTravel.addCommand(cmPreferNot);

String s = new String("Imposta il mezzo di trasporto\n\n");frmTravel.append(s);}

/*** Print out the menu*/void print(){

frmTravel.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmTravel);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * cmWant -> go to the transport wanted menu<br> * cmPrefer -> go to the transport prefered menu<br> * cmWantNot -> go to the transport don't wanted menu<br> * cmPreferNot -> go to the transport don't prefered menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmWant){ menuWPTransport.print(true); } else if (c == cmPrefer){ menuWPTransport.print(false); } else if (c == cmWantNot){ menuWPNotTransport.print(true); } else if (c == cmPreferNot){ menuWPNotTransport.print(false); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTransport.frmTravel); }

}

}

A.2.14 MenuTravel.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the travel

63

Page 64: zanoni.doc.doc

* in which is possible to choose if go to the travel amount menu * or to the transport menu */public class MenuTravel implements CommandListener{/*** The form of this menu*/static Form frmTravel;//the list of the commandprivate Command cmTransport;private Command cmTravelAmount;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuTransport menuTransport;private MenuTravelAmount menuTravelAmount;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuTravel(){

menuTransport=new MenuTransport();menuTravelAmount=new MenuTravelAmount();frmTravel=new Form("Viaggio");

cmTransport = new Command("Mezzo", Command.SCREEN, 2);cmTravelAmount = new Command("Spesa Viaggio", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmTravel.addCommand(cmBack); frmTravel.addCommand(cmTravelAmount); frmTravel.addCommand(cmTransport);

String s = new String("Imposta il tuo viaggio\n\n");frmTravel.append(s);

}

/*** Print out the menu*/void print(){

frmTravel.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmTravel);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the main menu <br> * cmTransport -> go to the transport menu<br> * cmTravelAmount -> go to the travel amount menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmTransport){

64

Page 65: zanoni.doc.doc

menuTransport.print(); } else if (c == cmTravelAmount){ menuTravelAmount.print(); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(XSRLQueryMain.form); }

}

}

A.2.15 MenuTravelAmount.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the travel amount * in which is possible to choose if go to the travel amount wanted menu * or to the travel amount prefered menu */public class MenuTravelAmount implements CommandListener{/*** The form of this menu*/static Form frmTravelAmount;//the list of the commandprivate Command cmWant;private Command cmPrefer;private Command cmBack;

//list of all the menus reachable from the main menuprivate MenuWPTravelAmount menuWPTravelAmount;

/*** Class constructor<br>* create all the component of the form* and add them to the form*/public MenuTravelAmount(){

menuWPTravelAmount=new MenuWPTravelAmount();frmTravelAmount=new Form("Spesa Viaggio");

cmWant = new Command("Voglio", Command.SCREEN, 2);cmPrefer = new Command("Preferisco", Command.SCREEN, 3);

cmBack = new Command("Back", Command.BACK, 1); frmTravelAmount.addCommand(cmBack); frmTravelAmount.addCommand(cmWant); frmTravelAmount.addCommand(cmPrefer);

String s = new String("Imposta la spesa del\ntuo viaggio\n\n");

65

Page 66: zanoni.doc.doc

frmTravelAmount.append(s);}

/*** Print out the menu*/void print(){

frmTravelAmount.setCommandListener(this); XSRLQueryMain.display.setCurrent(frmTravelAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> return to the travel menu <br> * cmWant -> go to the travel amount wanted menu<br> * cmPrefer -> go to the travel amount prefered menu<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmWant){ menuWPTravelAmount.print(true); } else if (c == cmPrefer){ menuWPTravelAmount.print(false); } else if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); }

}

}

A.2.16 MenuWPAmount.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the total amount wanted or prefered */public class MenuWPAmount extends Request implements CommandListener{/*** The form of this menu*/private Form frmWPAmount;//the list of possible commandprivate Command cmBack;private Command cmCancelOpt;private Command cmCancelVit;private Command cmOKVit;private Command cmOKOpt;

66

Page 67: zanoni.doc.doc

//the objects of the formprivate TextField tfAmount;private ChoiceGroup lessGreater;//variables that represent the values of the form's objectsprivate boolean lessOpt;private String valueOpt;private boolean lessVit;private String valueVit;/*** Class constructor<br>* set optional and vital to false and row to 0 * that represent that this part of the request is not yet writted.<br>* moreover set tag to 2 that represents that the possible tag for this part of request* are VITAL-MAINT or OPTIONAL-MAINT*/public MenuWPAmount(){

tag=2;row=0;query=new String("");optional=false;vital=false;

}/*** Print out the menu<br>* @param want if it is true the menu printed is the one of the total amount wanted* otherwise the menu printed is the one of the total amount prefered*/void print(boolean want){

frmWPAmount=new Form("Impostazioni spesa");String s;cmBack = new Command("Back", Command.BACK, 1);frmWPAmount.addCommand(cmBack);String choices[] = {"Minore", "Maggiore"};

if(!vital && want)//print the menu of the total amount wanted if there wasn't specified a total amount wanted yet

{//in this menu is possible to set a total amountcmOKVit = new Command("OK", Command.OK, 2);frmWPAmount.addCommand(cmOKVit);lessGreater = new ChoiceGroup("Il prezzo DEVE

essere",Choice.EXCLUSIVE,choices,null);tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPAmount.append(lessGreater);frmWPAmount.append(tfAmount);}

if(!optional && !want)//print the menu of the total amount prefered if there wasn't specified a total amount prefered yet

{//in this menu is possible to set a total amountcmOKOpt = new Command("OK", Command.OK, 2);frmWPAmount.addCommand(cmOKOpt);lessGreater = new ChoiceGroup("PREFERIREI che il prezzo

fosse",Choice.EXCLUSIVE,choices,null);tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPAmount.append(lessGreater);

67

Page 68: zanoni.doc.doc

frmWPAmount.append(tfAmount);}

if(vital && want)//print the menu of the total amount wanted if there was specified a total amount wanted yet

{//in this menu is possible to see and cancel the amount specified beforecmCancelVit = new Command("Cancella", Command.CANCEL, 2);String m;if (lessVit) m="minore";else m="maggiore";s = new String("La spesa DEVE essere\n"+m+" di " + valueVit +"\n");frmWPAmount.append(s);frmWPAmount.addCommand(cmCancelVit);}

if(optional && !want)//print the menu of the total amount prefered if there was specified a total amount prefered yet {//in this menu is possible to see and cancel the amount specified before cmCancelOpt = new Command("Cancella", Command.CANCEL, 2);

String m;if (lessOpt) m="minore";else m="maggiore";s = new String("PREFERIREI che la spesa fosse\n"+m+" di " + valueOpt +"\n");frmWPAmount.append(s);frmWPAmount.addCommand(cmCancelOpt);

}

//add the command listener frmWPAmount.setCommandListener(this); //display the menu XSRLQueryMain.display.setCurrent(frmWPAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> Return to total amount menu<br> * cmCancelOpt -> delete the total amount prefered set before<br> * cmCancelVit -> delete the total amount wanted set before<br> * cmOKVit -> add a new total amount wanted<br> * cmOKOpt -> add a new total amount prefered<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTotalAmount.frmTotalAmount); } else if (c == cmCancelOpt){ optional=false;//set that there is no optional part in this request's part stringOpt=null; if(vital){//if there is a vital part (until the deletion there was a PREFER tag) buildString(""); Parser.write(query,row);//write only the vital part } else Parser.delete(row);//delete the part print(false); //reprint the optional menu to set a new amount }

68

Page 69: zanoni.doc.doc

else if (c == cmCancelVit){ vital=false; stringVit=null; if(optional) {buildString(""); Parser.write(query,row); } else Parser.delete(row); print(true); } else if (c == cmOKVit){ if(tfAmount.getString().length()>1){//if is written an amount in the text field if(lessGreater.isSelected(0)) lessVit=true;//control the radio buttons and get them value else lessVit=false; vital=true;//set that there ia a vital part in this request's part valueVit=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuTotalAmount.frmTotalAmount);//Display the total amount menu if(lessVit)//build the less than or greater than string buildString("<LESS> PrezzoTotale </LESS><THAN>"+ valueVit + "</THAN>"); else buildString("<GREATER> PrezzoTotale </GREATER><THAN>"+ valueVit + "</THAN>"); if (row==0) row=Parser.rowsCounter();//if it is not setted get the row in which write Parser.write(query,row);//write the part of the request in the request } } else if (c == cmOKOpt){ if(tfAmount.getString().length()>1){ if(lessGreater.isSelected(0)) lessOpt=true; else lessOpt=false; optional=true; valueOpt=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuTotalAmount.frmTotalAmount); if(lessOpt) buildString("<LESS> PrezzoTotale </LESS><THAN>"+ valueOpt + "</THAN>"); else buildString("<GREATER> PrezzoTotale </GREATER><THAN>"+ valueOpt + "</THAN>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}}}

A.2.17 MenuWPHotelAmount.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0

69

Page 70: zanoni.doc.doc

*/ /** * The menu of the hotel amount wanted or prefered */public class MenuWPHotelAmount extends Request implements CommandListener{/*** The form of this menu*/private Form frmWPHotelAmount;//the list of possible commandprivate Command cmBack;private Command cmCancelOpt;private Command cmCancelVit;private Command cmOKVit;private Command cmOKOpt;//the objects of the formprivate TextField tfAmount;private ChoiceGroup lessGreater;//variables that represent the values of the form's objectsprivate boolean lessOpt;private String valueOpt;private boolean lessVit;private String valueVit;/*** Class constructor<br>* set optional and vital to false and row to 0 * that represent that this part of the request is not yet writted.<br>* moreover set tag to 2 that represents that the possible tag for this part of request* are VITAL-MAINT or OPTIONAL-MAINT*/public MenuWPHotelAmount(){

tag=2;row=0;query=new String("");optional=false;vital=false;

}/*** Print out the menu<br>* @param want if it is true the menu printed is the one of the hotel amount wanted* otherwise the menu printed is the one of the hotel amount prefered*/void print(boolean want){

frmWPHotelAmount=new Form("Impostazioni spesa hotel");String s;cmBack = new Command("Back", Command.BACK, 1);frmWPHotelAmount.addCommand(cmBack);String choices[] = {"Minore", "Maggiore"};

if(!vital && want)//print the menu of the hotel amount wanted if there wasn't specified a hotel amount wanted yet

{//in this menu is possible to set a hotel amountcmOKVit = new Command("OK", Command.OK, 2);frmWPHotelAmount.addCommand(cmOKVit);lessGreater = new ChoiceGroup("Il prezzo del soggiorno DEVE

essere",Choice.EXCLUSIVE,choices,null);

70

Page 71: zanoni.doc.doc

tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPHotelAmount.append(lessGreater);frmWPHotelAmount.append(tfAmount);}

if(!optional && !want)//print the menu of the hotel amount prefered if there wasn't specified a hotel amount prefered yet

{//in this menu is possible to set a hotel amountcmOKOpt = new Command("OK", Command.OK, 2);frmWPHotelAmount.addCommand(cmOKOpt);lessGreater = new ChoiceGroup("PREFERIREI che il prezzo del soggiorno

fosse",Choice.EXCLUSIVE,choices,null);tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPHotelAmount.append(lessGreater);frmWPHotelAmount.append(tfAmount);}

if(vital && want)//print the menu of the hotel amount wanted if there was specified a hotel amount wanted yet

{//in this menu is possible to see and cancel the amount specified beforecmCancelVit = new Command("Cancella", Command.CANCEL, 2);String m;if (lessVit) m="minore";else m="maggiore";s = new String("La spesa del soggiorno DEVE essere\n"+m+" di " + valueVit +"\n");frmWPHotelAmount.append(s);frmWPHotelAmount.addCommand(cmCancelVit);}

if(optional && !want)//print the menu of the hotel amount prefered if there was specified a hotel amount prefered yet {//in this menu is possible to see and cancel the amount specified before cmCancelOpt = new Command("Cancella", Command.CANCEL, 2);

String m;if (lessOpt) m="minore";else m="maggiore";s = new String("PREFERIREI che la spesa del soggiorno fosse\n"+m+" di " + valueOpt

+"\n");frmWPHotelAmount.append(s);frmWPHotelAmount.addCommand(cmCancelOpt);

}

//add the command listener frmWPHotelAmount.setCommandListener(this); //display the menu XSRLQueryMain.display.setCurrent(frmWPHotelAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> Return to hotel amount menu<br> * cmCancelOpt -> delete the hotel amount prefered set before<br> * cmCancelVit -> delete the hotel amount wanted set before<br> * cmOKVit -> add a new hotel amount wanted<br> * cmOKOpt -> add a new hotel amount prefered<br> * @param c The command listened * @param s The Displayable variable

71

Page 72: zanoni.doc.doc

*/public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuHotelAmount.frmHotelAmount); } else if (c == cmCancelOpt){ optional=false;//set that there is no optional part in this request's part stringOpt=null; if(vital){//if there is a vital part (until the deletion there was a PREFER tag) buildString(""); Parser.write(query,row);//write only the vital part } else Parser.delete(row);//delete the part print(false); //reprint the optional menu to set a new amount } else if (c == cmCancelVit){ vital=false; stringVit=null; if(optional) {buildString(""); Parser.write(query,row); } else Parser.delete(row); print(true); } else if (c == cmOKVit){ if(tfAmount.getString().length()>1){//if is written an amount in the text field if(lessGreater.isSelected(0)) lessVit=true; else lessVit=false;//control the radio buttons and get them value vital=true;//set that there ia a vital part in this request's part valueVit=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuHotelAmount.frmHotelAmount);//Display the hotel amount menu if(lessVit)//build the less than or greater than string buildString("<LESS> PrezzoHotel </LESS><THAN>"+ valueVit + "</THAN>"); else buildString("<GREATER> PrezzoHotel </GREATER><THAN>"+ valueVit + "</THAN>"); if (row==0) row=Parser.rowsCounter();//if it is not setted get the row in which write Parser.write(query,row);//write the part of the request in the request } } else if (c == cmOKOpt){ if(tfAmount.getString().length()>1){ if(lessGreater.isSelected(0)) lessOpt=true; else lessOpt=false; optional=true; valueOpt=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuHotelAmount.frmHotelAmount); if(lessOpt) buildString("<LESS> PrezzoHotel </LESS><THAN>"+ valueOpt + "</THAN>"); else buildString("<GREATER> PrezzoHotel </GREATER><THAN>"+ valueOpt + "</THAN>");

72

Page 73: zanoni.doc.doc

if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}}}

A.2.18 MenuWPNotTransport.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the Transport don't wanted or don't prefered */public class MenuWPNotTransport extends Request implements CommandListener{/*** The form of this menu*/private Form frmWPNotTransport;//the list of possible commandprivate Command cmBack;private Command cmCancelOpt;private Command cmCancelVit;private Command cmOKVit;private Command cmOKOpt;//the objects of the formprivate ChoiceGroup lstTransports;//variables that represent the values of the form's objectsprivate String choosedTransportOpt;private String choosedTransportVit;private String choices[]={"Aereo", "Treno"};/*** Class constructor<br>* set optional and vital to false and row to 0 * that represent that this part of the request is not yet writted.<br>* moreover set tag to 2 that represents that the possible tag for this part of request* are VITAL-MAINT or OPTIONAL-MAINT*/public MenuWPNotTransport(){

tag=2;row=0;query=new String("");optional=false;vital=false;

}/*** Print out the menu<br>* @param want if it is true the menu printed is the one of the transport don't wanted* otherwise the menu printed is the one of the transport don't prefered*/

73

Page 74: zanoni.doc.doc

void print(boolean want){frmWPNotTransport=new Form("Mezzi di trasporto");String s;cmBack = new Command("Back", Command.BACK, 1);frmWPNotTransport.addCommand(cmBack);

if(!vital && want)//print the menu of the transport don't wanted if there wasn't specified a transport don't wanted yet

{//in this menu is possible to set a transportcmOKVit = new Command("OK", Command.OK, 2);frmWPNotTransport.addCommand(cmOKVit);lstTransports = new ChoiceGroup("NON VOGLIO viaggiare

con",Choice.EXCLUSIVE,choices,null);lstTransports.setSelectedIndex(0,true);frmWPNotTransport.append(lstTransports);}

if(!optional && !want)//print the menu of the transport don't prefered if there wasn't specified a transport don't prefered yet

{//in this menu is possible to set a transportcmOKOpt = new Command("OK", Command.OK, 2);frmWPNotTransport.addCommand(cmOKOpt);lstTransports = new ChoiceGroup("PREFERIREI NON viaggiare

con",Choice.EXCLUSIVE,choices,null);lstTransports.setSelectedIndex(0,true);frmWPNotTransport.append(lstTransports);}

if(vital && want)//print the menu of the transport don't wanted if there was specified a transport don't wanted yet

{//in this menu is possible to see and cancel the transport specified beforecmCancelVit = new Command("Cancella", Command.CANCEL, 2);s = new String("Io NON VOGLIO viaggiare con " + choosedTransportVit +"\n");frmWPNotTransport.append(s);frmWPNotTransport.addCommand(cmCancelVit);}

if(optional && !want)//print the menu of the transport don't prefered if there was specified a transport don't prefered yet

{//in this menu is possible to see and cancel the transport specified before cmCancelOpt = new Command("Cancella", Command.CANCEL, 2);

s = new String("Io PREFERIREI NON viaggiare con " + choosedTransportOpt +"\n");frmWPNotTransport.append(s);frmWPNotTransport.addCommand(cmCancelOpt);

}

//add the command listener frmWPNotTransport.setCommandListener(this); //display the menu XSRLQueryMain.display.setCurrent(frmWPNotTransport);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> Return to travel menu<br> * cmCancelOpt -> delete the transport don't prefered set before<br> * cmCancelVit -> delete the transport don't wanted set before<br> * cmOKVit -> add a new transport don't wanted<br> * cmOKOpt -> add a new transport don't prefered<br> * @param c The command listened * @param s The Displayable variable

74

Page 75: zanoni.doc.doc

*/public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); } else if (c == cmCancelOpt){ optional=false;//set that there is no optional part in this request's part stringOpt=null; if(vital){//if there is a vital part (until the deletion there was a PREFER tag) buildString(""); Parser.write(query,row);//write only the vital part } else Parser.delete(row);//delete the part print(false);//reprint the optional menu to set a new amount } else if (c == cmCancelVit){ vital=false; stringVit=null; if(optional) {buildString(""); Parser.write(query,row); } else Parser.delete(row); print(true); } else if (c == cmOKVit){ choosedTransportVit=""; //control the radio buttons and get them value for(int i=0;i<choices.length;i++) if (lstTransports.isSelected(i)) choosedTransportVit=choices[i]; vital=true;//set that there ia a vital part in this request's part XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); //build the not equal string buildString("<NOT><EQUAL> Mezzo \""+choosedTransportVit+"\" </EQUAL></NOT>"); if (row==0) row=Parser.rowsCounter();//if it is not setted get the row in which write Parser.write(query,row);//write the part of the request in the request } else if (c == cmOKOpt){ choosedTransportOpt=""; for(int i=0;i<choices.length;i++) if (lstTransports.isSelected(i)) choosedTransportOpt=choices[i]; optional=true; XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); buildString("<NOT><EQUAL> Mezzo \""+choosedTransportOpt+"\" </EQUAL></NOT>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}}

75

Page 76: zanoni.doc.doc

A.2.19 MenuWPTransport.java

package xsrl;

import javax.microedition.lcdui.*; /** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the Transport wanted or prefered */public class MenuWPTransport extends Request implements CommandListener{/*** The form of this menu*/private Form frmWPTransport;//the list of possible commandprivate Command cmBack;private Command cmCancelOpt;private Command cmCancelVit;private Command cmOKVit;private Command cmOKOpt;//the objects of the formprivate ChoiceGroup lstTransports;//variables that represent the values of the form's objectsprivate String choosedTransportOpt;private String choosedTransportVit;private String choices[]={"Aereo", "Treno"};/*** Class constructor<br>* set optional and vital to false and row to 0 * that represent that this part of the request is not yet writted.<br>* moreover set tag to 2 that represents that the possible tag for this part of request* are VITAL-MAINT or OPTIONAL-MAINT*/public MenuWPTransport(){

tag=2;row=0;query=new String("");optional=false;vital=false;

}/*** Print out the menu<br>* @param want if it is true the menu printed is the one of the transport wanted* otherwise the menu printed is the one of the transport prefered*/void print(boolean want){

frmWPTransport=new Form("Mezzi di trasporto");String s;cmBack = new Command("Back", Command.BACK, 1);frmWPTransport.addCommand(cmBack);

76

Page 77: zanoni.doc.doc

if(!vital && want)//print the menu of the transport wanted if there wasn't specified a transport wanted yet

{//in this menu is possible to set a transportcmOKVit = new Command("OK", Command.OK, 2);frmWPTransport.addCommand(cmOKVit);lstTransports = new ChoiceGroup("VOGLIO viaggiare

con",Choice.EXCLUSIVE,choices,null);lstTransports.setSelectedIndex(0,true);frmWPTransport.append(lstTransports);}

if(!optional && !want)//print the menu of the transport prefered if there wasn't specified a transport prefered yet

{//in this menu is possible to set a transportcmOKOpt = new Command("OK", Command.OK, 2);frmWPTransport.addCommand(cmOKOpt);lstTransports = new ChoiceGroup("PREFERIREI viaggiare

con",Choice.EXCLUSIVE,choices,null);lstTransports.setSelectedIndex(0,true);frmWPTransport.append(lstTransports);}

if(vital && want)//print the menu of the transport wanted if there was specified a transport wanted yet

{//in this menu is possible to see and cancel the transport specified beforecmCancelVit = new Command("Cancella", Command.CANCEL, 2);s = new String("Io VOGLIO viaggiare con " + choosedTransportVit +"\n");frmWPTransport.append(s);frmWPTransport.addCommand(cmCancelVit);}

if(optional && !want)//print the menu of the transport prefered if there was specified a transport prefered yet

{//in this menu is possible to see and cancel the transport specified before cmCancelOpt = new Command("Cancella", Command.CANCEL, 2);

s = new String("Io PREFERIREI viaggiare con " + choosedTransportOpt +"\n");frmWPTransport.append(s);frmWPTransport.addCommand(cmCancelOpt);

}

//add the command listener frmWPTransport.setCommandListener(this); //display the menu XSRLQueryMain.display.setCurrent(frmWPTransport);

}

/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> Return to travel menu<br> * cmCancelOpt -> delete the transport prefered set before<br> * cmCancelVit -> delete the transport wanted set before<br> * cmOKVit -> add a new transport wanted<br> * cmOKOpt -> add a new transport prefered<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel);

77

Page 78: zanoni.doc.doc

} else if (c == cmCancelOpt){ optional=false;//set that there is no optional part in this request's part stringOpt=null; if(vital){//if there is a vital part (until the deletion there was a PREFER tag) buildString(""); Parser.write(query,row);//write only the vital part } else Parser.delete(row); //delete the part print(false);//reprint the optional menu to set a new amount } else if (c == cmCancelVit){ vital=false; stringVit=null; if(optional) {buildString(""); Parser.write(query,row); } else Parser.delete(row); print(true); } else if (c == cmOKVit){ choosedTransportVit=""; //control the radio buttons and get them value for(int i=0;i<choices.length;i++) if (lstTransports.isSelected(i)) choosedTransportVit=choices[i]; vital=true;//set that there ia a vital part in this request's part XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); //build the equal string buildString("<EQUAL> Mezzo \""+choosedTransportVit+"\" </EQUAL>"); if (row==0) row=Parser.rowsCounter();//if it is not setted get the row in which write Parser.write(query,row);//write the part of the request in the request } else if (c == cmOKOpt){ choosedTransportOpt=""; for(int i=0;i<choices.length;i++) if (lstTransports.isSelected(i)) choosedTransportOpt=choices[i]; optional=true; XSRLQueryMain.display.setCurrent(MenuTravel.frmTravel); buildString("<EQUAL> Mezzo \""+choosedTransportOpt+"\" </EQUAL>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}}

A.2.20 MenuWPTravelAmount.java

package xsrl;

import javax.microedition.lcdui.*;

78

Page 79: zanoni.doc.doc

/** *@author Manuel Zanoni *@version 1.0 */ /** * The menu of the travel amount wanted or prefered */public class MenuWPTravelAmount extends Request implements CommandListener{/*** The form of this menu*/private Form frmWPTravelAmount;//the list of possible commandprivate Command cmBack;private Command cmCancelOpt;private Command cmCancelVit;private Command cmOKVit;private Command cmOKOpt;//the objects of the formprivate TextField tfAmount;private ChoiceGroup lessGreater;

//variables that represent the values of the form's objectsprivate boolean lessOpt;private String valueOpt;private boolean lessVit;private String valueVit;

/*** Class constructor<br>* set optional and vital to false and row to 0 * that represent that this part of the request is not yet writted.<br>* moreover set tag to 2 that represents that the possible tag for this part of request* are VITAL-MAINT or OPTIONAL-MAINT*/public MenuWPTravelAmount(){

tag=2;row=0;query=new String("");optional=false;vital=false;

}/*** Print out the menu<br>* @param want if it is true the menu printed is the one of the travel amount wanted* otherwise the menu printed is the one of the travel amount prefered*/void print(boolean want){

frmWPTravelAmount=new Form("Impostazioni spesa Viaggio");String s;cmBack = new Command("Back", Command.BACK, 1);frmWPTravelAmount.addCommand(cmBack);String choices[] = {"Minore", "Maggiore"};

if(!vital && want) //print the menu of the travel amount wanted if there wasn't specified a travel amount wanted yet

79

Page 80: zanoni.doc.doc

{//in this menu is possible to set a travel amountcmOKVit = new Command("OK", Command.OK, 2);frmWPTravelAmount.addCommand(cmOKVit);lessGreater = new ChoiceGroup("Il prezzo del viaggio DEVE

essere",Choice.EXCLUSIVE,choices,null);tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPTravelAmount.append(lessGreater);frmWPTravelAmount.append(tfAmount);}

if(!optional && !want)//print the menu of the travel amount prefered if there wasn't specified a travel amount prefered yet

{//in this menu is possible to set a travel amountcmOKOpt = new Command("OK", Command.OK, 2);frmWPTravelAmount.addCommand(cmOKOpt);lessGreater = new ChoiceGroup("PREFERIREI che il prezzo del viaggio

fosse",Choice.EXCLUSIVE,choices,null);tfAmount=new TextField("di euro", "", 10, TextField.NUMERIC);lessGreater.setSelectedIndex(0,true);frmWPTravelAmount.append(lessGreater);frmWPTravelAmount.append(tfAmount);}

if(vital && want)//print the menu of the travel amount wanted if there was specified a travel amount wanted yet

{//in this menu is possible to see and cancel the amount specified beforecmCancelVit = new Command("Cancella", Command.CANCEL, 2);String m;if (lessVit) m="minore";else m="maggiore";s = new String("La spesa del viaggio DEVE essere\n"+m+" di " + valueVit +"\n");frmWPTravelAmount.append(s);frmWPTravelAmount.addCommand(cmCancelVit);}

if(optional && !want)//print the menu of the travel amount prefered if there was specified a travel amount prefered yet {//in this menu is possible to see and cancel the amount specified before cmCancelOpt = new Command("Cancella", Command.CANCEL, 2);

String m;if (lessOpt) m="minore";else m="maggiore";s = new String("PREFERIREI che la spesa del viaggio fosse\n"+m+" di " + valueOpt +"\

n");frmWPTravelAmount.append(s);frmWPTravelAmount.addCommand(cmCancelOpt);

}

//add the command listener frmWPTravelAmount.setCommandListener(this); //display the menu XSRLQueryMain.display.setCurrent(frmWPTravelAmount);

}/** * Specifies the action to do when a determinate command is listened. * Possible Command are:<br> * cmBack -> Return to travel amount menu<br> * cmCancelOpt -> delete the travel amount prefered set before<br>

80

Page 81: zanoni.doc.doc

* cmCancelVit -> delete the travel amount wanted set before<br> * cmOKVit -> add a new travel amount wanted<br> * cmOKOpt -> add a new travel amount prefered<br> * @param c The command listened * @param s The Displayable variable */public void commandAction(Command c, Displayable s){ if (c == cmBack){ XSRLQueryMain.display.setCurrent(MenuTravelAmount.frmTravelAmount); } else if (c == cmCancelOpt){ optional=false;//set that there is no optional part in this request's part stringOpt=null; if(vital){//if there is a vital part (until the deletion there was a PREFER tag) buildString(""); Parser.write(query,row);//write only the vital part } else Parser.delete(row); //delete the part print(false); //reprint the optional menu to set a new amount } else if (c == cmCancelVit){ vital=false; stringVit=null; if(optional) {buildString(""); Parser.write(query,row); } else Parser.delete(row); print(true); } else if (c == cmOKVit){ if(tfAmount.getString().length()>1){//if is written an amount in the text field if(lessGreater.isSelected(0)) lessVit=true; //control the radio buttons and get them value else lessVit=false; vital=true;//set that there ia a vital part in this request's part valueVit=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuTravelAmount.frmTravelAmount); //Display the travel amount menu if(lessVit) //build the less than or greater than string buildString("<LESS> PrezzoViaggio </LESS><THAN>"+ valueVit + "</THAN>"); else buildString("<GREATER> PrezzoViaggio </GREATER><THAN>"+ valueVit + "</THAN>"); if (row==0) row=Parser.rowsCounter(); //if it is not setted get the row in which write Parser.write(query,row);//write the part of the request in the request } } else if (c == cmOKOpt){ if(tfAmount.getString().length()>1){ if(lessGreater.isSelected(0)) lessOpt=true; else lessOpt=false; optional=true; valueOpt=new String(tfAmount.getString()); XSRLQueryMain.display.setCurrent(MenuTravelAmount.frmTravelAmount);

81

Page 82: zanoni.doc.doc

if(lessOpt) buildString("<LESS> PrezzoViaggio </LESS><THAN>"+ valueOpt + "</THAN>"); else buildString("<GREATER> PrezzoViaggio </GREATER><THAN>"+ valueOpt + "</THAN>"); if (row==0) row=Parser.rowsCounter(); Parser.write(query,row); }

}}}

82