Sei sulla pagina 1di 98

www.edmaster.

it
Poste Italiane S.p.ASpedizione in A.P. D.L. 353/2003 (conv.in L.27/02/2004 n.46) art.1 comma 2 DCB ROMA Periodicit mensile APRILE 2007 ANNO XI N.4 (113)
PER ESPERTI E PRINCIPIANTI
RIVISTA+CD E6,90 RIVISTA+LIBRO+CD E9,90
VERSIONE PLUS VERSIONE STANDARD
ti programmo cos!
Poste Italiane S.p.A Spedizione in A.P. D.L. 353/2003 (conv.in L.27/02/2004 n.46) art.1 comma 2 DCB ROMA Periodicit mensile SETTEMBRE 2008 ANNO XII, N.9 (130)
PER ESPERTI E PRINCIPIANTI
SOLUZIONI GLI ALGORITMI E LE TECNICHE PER RAPPRESENTARE ENTIT
GEOMETRICHE CON UN INSIEME DI PIXEL: LA RASTERIZZAZIONE
HTML
IL TUO SITO WEB
PRONTO PER PAYPAL
Come implementare un carrello
elettronico per gli acquisti
PYTHON
UTILIZZARE GLI OBJECT
RELATIONAL MAPPING
SQLAlchemy per trasformare i dati
di un DB in istanze del linguaggio
JAVA
LA LIBRERIA VISUAL
LIBRARY DI NETBEANS
Strumenti di visualizzazione
evoluti nelle applicazioni
MOBILE
GESTIRE I COMPONENTI
GRAFICI DI J2ME
Adoperare form, etichette, campi
di testo e altri elementi grafici
DATABASE
PRIMI PASSI IN ADO.NET
ENTITY FRAMEWORK
Interrogare un database senza
conoscere struttura e relazioni
CMS
SCRIVERE UN NUOVO
MODULO PER DRUPAL
Progettare un plug-in Ajax
per visualizzare le immagini
SOFTWARE
LE RICETTE
PER USARE ECLIPSE
Creazione, compilazione
ed esecuzione di un progetto Java
POSTA ELETTRONICA
DAL WEB CON PHP
RoundCube, leggi la posta
dal tuo sito in stile Gmail/Hotmail
C#
PC HARDWARE
MONITORING
WMI per riconoscere
lo stato dei dischi removibili
JAVA
SVILUPPARE
APPLICAZIONI RIA
JavaFX Script per creare
facilmente interfacce grafiche
VISUAL BASIC .NET
STAMPE CON
CRYSTAL REPORT
Gli strumenti per gestire
resoconti di ogni tipologia
2
0
S
N
IP
P
E
T
D
I CO
D
ICE
da usare subito nei tuoi lavori
TUTTO SU COME SVILUPPARE
APPLICAZIONI PER IL CELLULARE
PI CHIACCHIERATO DELLA STORIA
NERO 8 FAI DA TE!
Come sfruttare le API di Windows per sviluppare
un software di masterizzazione
AL VIA IL TUTORIAL
SU ZEND FRAMEWORK
Come utilizzare al meglio lambiente PHP per eccellenza
SISTEMA Come funziona
il sistema operativo che equipaggia
il gioiello di casa Apple
TECNICA Cosa bisogna conoscere
prima di addentrarsi nel codice
SOFTWARE Una prima applicazione
da provare immediatamente
sullo Smartphone
SCOPRI IL SIMULATORE
Per sviluppare anche senza
possedere il dispositivo
i
o
P
r
o
g
r
a
m
m
o






A
n
n
o

X
I
I

-

N

9

(
1
3
0
)

















































E
D
I
Z
I
O
N
I

M
A
S
T
E
R
P
R
O
G
R
A
M
M
A
R
E

L
'
I
P
H
O
N
E


S
V
I
L
U
P
P
A
R
E

U
N

S
O
F
T
W
A
R
E

D
I

M
A
S
T
E
R
I
Z
Z
A
Z
I
O
N
E


R
E
A
L
I
Z
Z
A
R
E

A
P
P
L
I
C
A
Z
I
O
N
I

R
I
A
CODICE
SORGENTE
SUL CD
001_ioprog130.indd 1 17-07-2008 12:08:14
Anno XII - N.ro 09 (130) - Settembre 2008 -
Periodicit: Mensile
Reg. Trib. di CS al n.ro 593 del 11 Febbraio 1997
Cod. ISSN 1128-594X
E-mail: ioprogrammo@edmaster.it
http://www.edmaster.it/ioprogrammo
http://www.ioprogrammo.it
Direttore Editoriale: Massimo Sesti
Direttore Responsabile: Massimo Sesti
Responsabile Editoriale: Gianmarco Bruni
Vice Publisher: Paolo Soldan
Collaboratori: C. Pelliccia, F. Paparoni, E. Bottari, F. Grimaldi,
A. Leganza, F. Cozzolino, G. De Marco, M. Buccio, C.
Morano, G. Malanga, G. Ascione, M. Morelli, G.Pennella
Segreteria di Redazione: Emanuela Giordano
Consulenza Redazionale: SET S.r.l.
G. Forlino, P. Mannelli
Realizzazione grafica: Cromatika S.r.l.
Art Director: Paolo Cristiano
Responsabile grafico di progetto: Salvatore Vuono
Responsabile area tecnica: Giancarlo Sicilia
Illustrazioni: M. Veltri
Impaginazione elettronica: Francesco Cospite, Lisa Orrico,
Nuccia Marra, Luigi Ferraro
Realizzazione Multimediale: SET S.r.l.
Realizzazione CD-Rom: Paolo Iacona
Pubblicit: Master Advertising s.r.l.
Via C. Correnti, 1 - 20123 Milano
Tel. 02 831212 - Fax 02 83121207
e-mail advertising@edmaster.it
Sales Director: Max Scortegagna
Editore: Edizioni Master S.p.a.
Sede di Milano: Via Ariberto, 24 - 20123 Milano
Sede di Rende: C.da Lecco, zona ind. - 87036 Rende (CS)
Presidente e Amministratore Delegato: Massimo Sesti
Direttore Generale: Massimo Rizzo
ABBONAMENTO E ARRETRATI
ITALIA: Abbonamento Annuale: IOPROGRAMMO (11 NUMERI)
E59,90 SCONTO 21% SUL PREZZO DI COPERTINA DI E75,90
IOPROGRAMMO CON LIBRO (11 NUMERI) E75,90 SCONTO 30%
SUL PREZZO DI COPERTINA DI E108,90
Abbonamento Biennale: IOPROGRAMMO (22 NUMERI) E75,90
SCONTO 50% SUL PREZZO DI COPERTINA DI E151,80
IOPROGRAMMO CON LIBRO (22 NUMERI) E108,90 SCONTO 50%
SUL PREZZO DI COPERTINA DI E217,80 OFFERTE VALIDE FINO AL
30/09/2008.
Costo arretrati (a copia): il doppio del prezzo di copertina + E
5. 32 spese (spedizione con corriere). Prima di inviare i
pagamenti, verificare la disponibilit delle copie arretrate allo 02
831212.
La richiesta contenente i Vs. dati anagrafici e il nome della riv-
ista, dovr essere inviata via fax allo 02 83121206, oppure via
posta a EDIZIONI MASTER via C. Correnti, 1 - 20123 Milano, dopo
avere effettuato il pagamento, secondo le modalit di seguito
elencate:

cc/p n.16821878 o vaglia postale (inviando copia della ricevuta


del versamento insieme alla richiesta);

assegno bancario non trasferibile (da inviarsi in busta chiusa


insieme alla richiesta);

carta di credito, circuito Visa, Cartas, o Eurocard/Mastercard


(inviando la Vs. autorizzazione, il numero di carta di credito, la
data di scadenza, l'intestatario della carta e il codice CVV2, cio le
ultime 3 cifre del codice numerico riportato sul retro della carta).

bonifico bancario intestato a Edizioni Master S.p.A. c/o BCC


MEDIOCRATI S.C.AR.L. IBAN: IT 85 Q 07062 80881 000000012000
(inviando copia della distinta insieme alla richiesta).
SI PREGA DI UTILIZZARE IL MODULO RICHIESTA ABBONAMENTO PO -
STO NELLE PAGINE INTERNE DELLA RIVISTA. Labbonamento ver r
attivato sul primo numero utile, successivo alla data della ri chiesta.
Sostituzioni: qualora nei prodotti fossero rinvenuti difetti o
imperfezioni che ne limitassero la fruizione da parte dellutente,
prevista la sostituzione gratuita, previo invio del materiale
difettato.
La sostituzione sar effettuata se il problema sar riscontrato e
segnalato entro e non oltre 10 giorni dalla data effettiva di acqui-
sto in edicola e nei punti vendita autorizzati, facendo fede il tim-
bro postale di restituzione del materiale.
Inviare il CD-Rom difettoso in busta chiusa a:
Edizioni Master - Servizio Clienti - Via C. Correnti, 1 - 20123
Milano
Assistenza tecnica: ioprogrammo@edmaster.it
Stampa: Arti Grafiche Boccia S.p.a. Via Tiberio Felice, 7 Salerno
Duplicazione CD-Rom: Neotek S.r.l.
C.da Imperatore - Bisignano (CS)
Distributore esclusivo per lItalia: Parrini & C S.p.A.
Via Vitorchiano, 81 - Roma
Finito di stampare nel mese di Agosto 2008
Nessuna parte della rivista pu essere in alcun modo riprodotta
senza auto riz zazione scritta della Edizioni Master. Manoscritti e
foto originali, anche se non pubblicati, non si restituiscono.
Edizioni Ma ster non sar in alcun caso responsabile per i danni
diretti e/o indiretti derivanti dallu ti lizzo dei pro gram mi contenuti
nel supporto mul ti me dia le allegato alla rivista e/o per even tua li
anomalie degli stessi. Nessuna responsabilit , inol tre, assunta
dalla Edizioni Master per danni o altro derivanti da virus
informatici non riconosciuti dagli antivirus ufficiali allatto della
ma ste riz zazione del supporto. Nomi e mar chi protetti sono citati
senza indicare i relativi brevetti.
Rispettare luomo e lambiente in cui esso vive e lavora una parte
di tutto ci che facciamo e di ogni decisione che prendiamo per
assicurare che le nostre operazioni siano basate sul continuo
miglioramento delle performance ambientali e sulla prevenzione
dellinquinamento
M
LUniverso Tecnologico
www.itportal.it
Servizio Abbonati:
tel. 02 831212
@ e-mail: servizioabbonati@edmaster.it
Allinizio di ogni articolo, troverete un simbolo che indicher la presenza di
codice e/o software allegato, che saranno presenti sia sul CD (nella posizione
di sempre \soft\codice\ e \soft\tools\)
sia sul Web, allindirizzo http://cdrom.ioprogrammo.it
J CD J WEB
nome_file.zip
Questo mese su ioProgrammo
MA QUANT BELLO LIPHONE
SPERIAMO PER CHE IL PROSSIMO SIA ANCHE UTILE!
Certificato n.6168
del 11/12/2007
SISTEMA
Come funziona il sistema operativo
che equipaggia il gioiello di casa Apple
TECNICA
Cosa bisogna conoscere prima
di addentrarsi nel codice
SOFTWARE
Una prima applicazione
da provare immediatamente
sullo SmartPhone

Certificato UNI EN ISO 14001


N.9191.EMAS
TUTTO SU COME SVILUPPARE APPLICAZIONI
PER IL CELLULARE PI CHIACCHIERATO
DELLA STORIA
A un paio di mesi dalluscita nel nostro paese del tan-
to atteso melafonino siamo a tirare un po le somme,
dopo averne fatto la diretta conoscenza. LiPhone
figo, non c dubbio. LiPhone sottile, non c dub-
bio. LiPhone ha una comoda e originale interfaccia tou-
chscreen. Ma largo quasi quanto la padella per le
bistecche usata da mia madre, e anche la sua lavatri-
ce ha linterfaccia con lo schermo che basta sfiorare,
e la centrifuga si avvia in un lampo. Magari la lavatri-
ce di mamma non avr le stesse accattivanti icone,
ma la centrifuga gira che un piacere. Che queste pa-
role non sembrino un attacco a occhi chiusi diretto al
gioiellino della casa di Steve Jobs da parte di uno
che da sempre usa a intermittenza Windows e Linux
snobbando un po la mela di Cupertino per ignoti
motivi, probabilmente ancestrali, ma che siamo ri-
masti un tantino delusi da quello che si pu fare con
il fashion-fonino per eccellenza di questi ultimi me-
si. S, ok ha il WI-FI, il BLUETOOTH, supporta an-
che (ma soltanto dalla seconda release) le reti 3G, ha
laccelerometro, il caff che fa non esattamente al-
la napoletana, sicuramente veloce nella risposta
(mooolto pi dellHTC Diamond, tanto per citarne
uno) quando le dita scorrono sullo schermo lanciando
immagini come fossero tanti piccoli frisbee e, so-
prattutto, chiuso come le porte delle chiese quando
ti vuoi confessare. forse questa la cosa che ci indi-
spone maggiormente. chiuso nel senso che per svi-
luppare unapplicazione da far girare sulliPhone, c
ovviamente bisogno dellSDK distribuito da Apple. E
quando lSDK non sar pi soltanto una versione be-
ta, sar a pagamento. E chi vorr distribuire le pro-
prie applicazioni dovr farlo per forza tramite lApp Sto-
re, con i vincoli imposti dallo stesso. Non ci sembra una
bella mossa, sinceramente, anche se c da ricono-
scere che questo certificher in maniera inequivoca-
bile le applicazioni dellApp Store. Mentre aspettia-
mo la terza versione delliPhone, che speriamo esse-
re in grado di fare anche altro, iniziamo a dare uno
sguardo ad Openmoko (www.openmoko.com), per
esempio, e al suo primo nato: Freerunner. Da questo
sistema Open Source s che ci aspettiamo grandi co-
se. E siamo sicuri che le vedremo.
Piero Mannelli
004-005 editoriale:004-005 editoriale 22-07-2008 15:21 Pagina 4
Questo mese su ioProgrammo
QUALCHE CONSIGLIO UTILE
I nostri articoli si sforzano di essere
com prensibili a tutti coloro che ci
seguono. Nel caso in cui abbiate
difficolt nel comprendere
esattamente il senso di una
spiegazione tecnica, utile aprire il
codice allegato allarticolo e seguire
passo passo quanto viene spiegato
tenendo docchio lintero progetto.
http://forum.ioprogrammo.it
MOBILE
Videogiochi in Java per cellulari
(quarta parte)
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 54
Dopo aver introdotto i principi di
programmazione delle MIDlet, il corso
prosegue illustrando i componenti grafici
di alto livello, indispensabili in qualsiasi
applicazione MIDP: etichette, bottoni e
gestione delle immagini
SISTEMA
Creare report con Visual Basic.NET
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 60
In questo articolo spiegheremo come
utilizzare il tool dedicato alla reportistica
fornito con Visual Studio: Crystal Reports.
Vedremo la struttura di un report e come
integrare lo stesso allinterno di una nostra
applicazione
Masterizzazione facile con C#
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 72
La versatilit del .NET Framework permette,
Come sfruttare le API di Windows per sviluppare
un software di masterizzazione
pag. 72
tra le altre cose, anche di scrivere dati su
supporti ottici. Vediamo praticamente come
realizzare unapplicazione di
masterizzazione sfruttando un componente
COM integrato nel sistema
Monitorare le periferiche del PC
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 84
Utilizziamo WMI per rilevare i cambiamenti
di stato dei dispositivi removibili.
Inserimento, modifica e rimozione di supporti
CD-rom/DVD-rom, USB Mass Storage,
Memory Card e via discorrendo
Database come istanze di Python
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 91
SQLAlchemy un nuovo Object-Relational
Mapper che offre agli sviluppatori, stanchi dei
soliti approcci alle basidati, un nuovo modo di
pensare e concepire il codice e l'SQL,
sfruttando un unico strumento integrato
Utilizzare Ado.Net Entity Framework
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 99
Visual studio 2008 integra un ORM molto
evoluto che permette di astrarre
il modello relazionale in un modello a
oggetti. Tale tecnica consente di interrogare
un DB senza conoscerne struttura e relazioni
SOLUZIONI
Il processo di rasterizzazione
. . . . . . . . . . . . . . . . . . . . . . . . . pag. 110
Un punto cruciale e di estremo interesse
nellambito della grafica computazionale il
processo con il quale si convertono entit,
descritte nel continuo, in corrispondenti entit
discrete, ossia insiemi di pixel
NERO 8 FAI DA TE!
Gli allegati di ioProgrammo
pag. 8
Il software in allegato alla rivista
Il libro di ioProgrammo
pag. 6
Il contenuto del libro in allegato
alla rivista
News pag. 10
Le pi importanti novit del
mondo della programmazione
Biblioteca pag. 67
I migliori testi scelti
dalla redazione
Tips & Tricks pag. 48
Una raccolta di trucchi da tenere
a portata di... mouse
Software pag. 105
I contenuti del CD allegato
a ioProgrammo.
RUBRICHE
SOFTWARE
Progetti java con eclipse
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 22
Iniziamo a conoscere l'ambiente di sviluppo e
le tecnologie per realizzare software per il
nuovo gioiello di casa Apple. Vedremo come
si progetta unapplicazione, riuscendo a
testarla anche se non possediamo il costoso
smartphone
IOPROGRAMMO WEB
Creare un nuovo modulo per drupal
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 26
Una della potenzialit dei nuovi CMS quella
di poterne aumentare le funzionalit
attraverso la creazione di moduli dedicati
a un compito particolare, facilmente gestibili
e integrabili all'interno del CORE
dellapplicazione
Primi passi con Zend Framework
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 30
Esaminiamo in dettaglio la struttura del pi
noto ambiente per Web Application PHP.
Getteremo le basi per progettare
unapplicazione basata sul paradigma Model
View Controller
Roundcube. La posta in PHP
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 34
Installiamo e configuriamo un potente
software gratuito di webmail.
Con Roundcube avremo un sistema capace
di gestire i messaggi cos come fanno i mostri
sacri Gmail,Hotmail e Yahoo!
Il tuo sito pronto per PayPal
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 39
In questo primo articolo ci occuperemo di
descrivere linsieme dei servizi di pagamento
sicuro offerti da Paypal. Analizzeremo, altres,
gli strumenti per lintegrazione dellIPN
allinterno di un proprio sito web
Creare un image viewer con java
. . . . . . . . . . . . . . . . . . . . . . . . . . pag. 44
Scopriamo come sfruttare alcune delle funzioni
principali della Visual Library, una libreria
opensource distribuita come parte di
Netbeans. La adopereremo per realizzare un
visualizzatore di immagini con pochissime
righe di codice
004-005 editoriale:004-005 editoriale 22-07-2008 15:21 Pagina 5
ht t p: / / www. i opr ogr ammo. i t
G
6
/Settembre 2008
Le versioni di ioProgrammo
RIVISTA
+
LIBRO
+
CD-ROM
in edicola
9
,90
h
V
e
r
s
io
n
e
P
L
U
S
I contenuti del libro
P
rogrammare le macro contemporaneamente una sfida e
un gioco, ed molto pi semplice di quanto si possa pensare.
Vederle produrre i risultati desiderati, poi, una notevole
soddisfazione. Infatti si potr orgogliosamente dire: questo lho
fatto io! Per chi utilizza con dimestichezza Microsoft Excel, il
mondo delle macro un passaggio obbligato per arricchire il foglio
elettronico di nuove caratteristiche e funzionalit, di automatismi
creati appositamente per le proprie esigenze. Questo libro ha un
taglio pratico e ha lobiettivo di indicare con semplicit le tecniche
da adottare nellutilizzo delle macro, per ottenere rapidamente i
risultati desiderati. Laspetto pi importante comprendere che le
immense potenzialit delle macro possono essere sfruttate
iniziando con la creazione di quelle pi semplici, per aumentarne
progressivamente le complessit, fino a realizzare macro (anche
dette funzioni o routine) molto articolate, in grado di aprire un
documento, cercare uninformazione, chiedere allutente cosa fare
e agire di conseguenza.
AMPLIARE LE POTENZIALIT DI EXCEL
CON FUNZIONI E PROGRAMMAZIONE
Imparare a sfruttare le potenzialit
di Excel attraverso le macro.
Il linguaggio VBA: Visual Basic for Application
Visual Basic Editor
Funzioni, routine e subroutine
Operatori, variabili, matrici e costanti
Esecuzione condizionale e ciclica delle istruzioni
Gestione degli errori
Creare finestre di dialogo
Interagire con celle, fogli e cartelle
POCKET EXCEL 2007 MACRO
006 Presentaz Libro:008 22-07-2008 15:22 Pagina 6
ht t p: / / www. i opr ogr ammo. i t
G
8
/Settembre 2008
Posta elettronica con Visual basic
Le versioni di ioProgrammo
Come usare linterfaccia del CDRom
V
e
r
s
io
n
e
B
A
S
E
6
,90
h
RIVISTA
+
CD-ROM
in edicola
Molte volte, sviluppando una qualunque applicazio-
ne, ci si trova in situazioni particolari e impreviste che
provocano a volte la sgradevole sensazione di non
sapere cosa fare. Lintegrazione di un particolare
componente che intervenga sui file di Office piutto-
sto che su quelli in formato PDF, la necessit di testa-
re unespressione regolare prima di inserirla nel pro-
gramma o, ancora, la volont di dotare lapplicazione
che si sta creando di unaccattivante interfaccia che
distingua il nostro programma dalla marea di applica-
zioni in circolo. Spesso si perde prezioso tempo cer-
cando la soluzione adatta al problema di turno.
Proprio per questo, nel CD-Rom allegato a questo
numero proponiamo una raccolta di componenti,
tool e programmi che di sicuro agevoleranno il lavo-
ro quotidiano di chi ci segue. Gli attrezzi giusti per
inserire un motore antivirus nelle proprie applicazio-
ni o per proteggere il proprio codice da impertinenti
decompilatori, e ancora i programmi per conservare
le porzioni riutilizzabili del proprio prezioso codice.
Sfogliando il CD-Rom troverete tutti questi tool, e
molti altri ancora, pronti da installare ed utilizzare per
perfezionare il vostro lavoroe divertimento!
SPECIALE TOOL
Il top software del mese
individuato dalla redazione
IN EVIDENZA
Il software diviso
in categorie per
una comoda consultazione
IL SOFTWARE
Torna alla pagina iniziale
del CD-ROM
HOME
Vuoi inviare una email alla
redazione con le tue richieste
CONTATTACI
Il database di tutti i software
pubblicati da ioProgrammo
anche gli arretrati
RICERCA SOFTWARE
Abbonamenti informazioni
e servizi utili
INFO
Lelenco del software
contenuto nelle categorie
IL SOFTWARE
La dimensione
del software sul CD
DIMENSIONE
Clicca qui per installare o
salvare il software sul tuo PC
SALVA
Una accurata recensione
dei contenuti
IL SOFTWARE
008 Presentaz CDRom 1:010 22-07-2008 15:23 Pagina 8
ht t p: / / www. i opr ogr ammo. i t
NEWS M
G
10
/Settembre 2008
News
PICCOLI PIRATI
CRESCONO
M
icrosoft ha reso pubblici i risul-
tati di un'indagine mirata a in-
dividuare le abitudini sull'uso dei com-
puter da parte di bambini e adole-
scenti. La realt dei fatti, gi palese da
tempo, abbastanza inquietante. I
baby-informatici, infatti, crescono in
un ambiente dove la pirateria al-
l'ordine del giorno, e viene vista an-
zi come una strada, facile e veloce,
per acquisire informazioni, conoscenza
e, soprattutto, software e materiale
multimediale come film e brani MP3.
A nulla servirebbero, quindi, i vari
software utilizzati dai genitori per li-
mitare e controllare l'uso di Internet,
e del computer in genere. La fascia
d'et interessata dallo studio con-
dotto dalla casa di Redmond, infatti,
un particolare tipo di utenza. Bam-
bini e adolescenti hanno molto pi
tempo a disposizione rispetto a un
adulto, e sono certamente dotati di
maggiore elasticit mentale; pro-
prio quest'ultima che li avvantaggia
nell'apprendimento di nuovi tool,
software e tecniche da utilizzare. Il
40% dei bambini intervistati, appar-
tenente, inoltre, a una fascia d'et
compresa tra gli 11 e 16 anni, ha can-
didamente ammesso di cercare sul
Web materiale pirata, pur sapendo
che si tratta di un'azione illegale. Mi-
crosoft "se la cava" con il commento
del suo responsabile del settore an-
tipirateria di Microsoft UK: "I genito-
ri dovrebbero prestare maggiore at-
tenzione alle attivit svolte propri fi-
gli davanti al PC. Solita strategia del
terrore, quindi, che probabilmente
proprio la causa di questo fenomeno
baby pirata.
GMAIL? SEMPRE PI SICURO!
L
implementazione del nuo-
vo servizio non ancora
ufficiale, e non disponibile
per tutti gli utenti. Si tratta di
una nuova e originale carat-
teristica di Google che offre
maggior sicurezza ai suoi uten-
ti. Ogni persona che dispone
di un account Gmail potr con-
trollare in tempo reale se qual-
cun altro sta utilizzando la sua
casella di posta. Il sistema for-
nir dei completi log , attra-
verso i quali lutente potr mo-
nitorare gli ultimi accessi ef-
fettuati sul suo account, gli IP di pro-
venienza e gli orari nei quali sono sta-
ti effettuati i login.
Qualora si dovesse trovare una sessione
aperta e loggata, lutente avr anche la pos-
sibilit di terminarla , effettuando il lo-
gout alla persona che si era indebita-
mente loggata al suo posto. Questa nuo-
va feature di Google stata pensata per
proteggere ad esempio - coloro che,
controllando la propria casella e-mail
da una postazione allinterno di un In-
ternet Caf, distrattamente lasciano aper-
to il loro account e danno la possibilit
a chiunque passi da quella postazione
di controllare la sua posta. stata pen-
sata anche per coloro che magari han-
no rivelato la propria password a qualche
amico o collega, e questi approfitta per
controllare la posta dellingenuo pro-
prietario della casella.
Controllare gli accessi effettuati al pro-
prio account dar la possibilit di capi-
re se qualcun altro usa la propria casel-
la senza la preventiva autorizzazione,
con tanto di indirizzo IP, che si riveler mol-
to utile per eventuali denuncie presso le
autorit competenti.
NOKIA SI COMPRA SYMBIAN E
LO TRASFORMA IN OPEN SOURCE
F
orse la spinta stata data dallim-
minente uscita di Android, la piat-
taforma per cellulari e smartphone
creata da Google per contrastare il
dominio Microsoft nel mondo della
telefonia mobile. Nokia non rimasta
a guardare, e si impegnata ad acqui-
sire le azioni di Symbian non ancora in
suo possesso. La casa finlandese, che
deteneva gi il 53% dei titoli di borsa di
Symbian, tenta in questo modo di con-
trastare limminente ingresso di BigG
nel mondo degli SO mobili. Nulla di
nuovo sotto il sole, osserveranno alcu-
ni, visto che da sempre Nokia e
Symbian vanno a braccetto, e il pro-
duttore di telefoni contribuisce attiva-
mente allo sviluppo e allaggiorna-
mento del S.O. in questione. La novit,
invece, sta nel cambio di licenza ope-
rato da Nokia. Symbian diventer,
infatti, Open Source a tutti gli effetti.
Guarda caso, la stessa licenza dovreb-
be essere quella adottata da Android di
Google.
Una volta terminate le procedure di
acquisizione, Nokia si impegner,
assieme alla Symbian Foundation, della
conversione del codice sorgente di
Symbian da chiuso a open source.
La metamorfosi dovrebbe avvenire
entro un paio danni, di fatto avvantag-
giando la diffusione della gi utilizzatis-
sima piattaforma di sviluppo mobile.
010-011:014-015 17-07-2008 12:52 Pagina 10
ht t p: / / www. i opr ogr ammo. i t
NEWS M
Settembre 2008/
11
G
M
entre scriviamo, iPhone approdato in Italia
da qualche giorno (a proposito, vi invitiamo a
leggere larticolo di copertina che parla proprio del
nuovo smartphone) ed stato subito boom!.
Apple ha infatti dichiarato di aver venduto in tutto il
mondo addirittura un milione di esemplari dello schic-
cosissimo Melafonino (quello di seconda generazione)
in soli tre giorni dalla data del lancio ufficiale.
Grazie a questo risultato il titolo Apple in borsa (come
se ce ne fosse bisogno) in un attimo salito dell1,24%.
Successone, ovviamente, anche per Apple Store, nego-
zio virtuale tramite il quale possibile scaricare appli-
cazioni realizzate ad hoc per il gioiellino di Cupertino.
Attenzione per: alcuni analisti hanno smentito cruda-
mente le affermazioni di Apple.
Steve Jobs & C., infatti, avrebbero la cattiva abitudine
di conteggiare come venduto anche il quantitativo di
merce semplicemente inviato presso i rivenditori, i part-
ner e gli stessi Apple Store.
In pratica, gli iPhone venduti nel famoso weekend di
fuoco, sarebbe soltanto circa 500.000, cifra certamente
di tutto rispetto, ma ben lontana dalla milionata di te-
lefoni dichiarata da Jobs e soci. Si pensi anche che la stes-
sa Apple, per vendere un milione di iPhone di prima ge-
nerazione impieg infatti ben 74 giorni. C anche chi
scommette che il dispositivo si riveler un flop, superato
alla grande da concorrenti dietro langolo.
IPHONE: RECORD DI VENDITE
IN POCHE ORE. OPPURE NO
N
on una novit, quella che nei
processori Intel siano presenti
da tempo alcuni bug che possono es-
sere sfruttati per attaccare le mac-
chine che utilizzano tali CPU. Fino-
ra, per, nessuno ha mai sfruttato
realmente queste falle, n tantome-
no sono ancora stati creati dei malwa-
re o virus che approfittano delle sud-
dette debolezze. Kris Kaspersky (che
non ha nulla a che vedere con la fa-
mosa casa produttrice di software an-
tivirus, se non lomonimia del co-
gnome e linteresse per le questioni
legate alla sicurezza informatica), no-
to autore di numerosi testi sul cracking,
dimostrer alla prossima HITBSec-
Conf2008 come sia possibile far cra-
share da remoto un computer che uti-
lizza un processore Intel. Kaspersky ha
dichiarato che sar sufficiente del
normale codice Javascript accompa-
gnato da particolari pacchetti TCP/IP.
Tale metodologia, oltre a provocare
un corto del PC, potrebber con-
sentire la presa totale
di controllo del PC vit-
tima. A prescindere
dalla potenza dellat-
tacco e dai danni che
possono da questo es-
sere provocati, il rea-
le pericolo dovuto al
fatto che un eventua-
le virus, concepito
sfruttando queste fal-
le, potrebbe funzio-
nare a prescindere dal
sistema operativo e in-
fettare quindi macchine Windows,
Mac e Linux senza, di fatto, guar-
dare in faccia nessuno.
Preoccupante latteggiamento di In-
tel, che non ha mai fornito alcun tipo
di strumento per accertarsi che la pro-
pria macchina sia affetta dai questi
problemi che non sembrano pochi vi-
sto che, sempre a detta di Kaspersky, i
processori Core 2 contengono 128 bug
e quelli Itanium circa 230. Solo que-
stione di tempo, continua il ricercato-
re, prima che gli smanettoni cattivi di
tutto il mondo inizino a produrre ver-
miciattoli pronti a insinuarsi nelle
CPU. Staremo a vedere cosa succeder
a fine ottobre, quindi, quando Kris (che
ha promesso di rilasciare il codice del-
le sue scoperte sotto licenza Open
Source) prover a distruggere un Hard
Disk sfruttando i bug dei processori
Intel.
LE CPU INTEL POSSIBILI BERSAGLI DEI NUOVI HACKER
010-011:014-015 17-07-2008 12:52 Pagina 11
ht t p: / / www. i opr ogr ammo. i t
COVER STORY M
G
12
/Settembre 2008
Software e tecniche per programmare liPhone
IPHONE MANIA
L'oggetto dei desideri di molti italiani (e non
solo) finalmente sbarcato sul mercato tramite
canali ufficiali e ora che possibile acquistarlo
liberamente (disponibilit a parte), giunto il
tempo che vi mostri come realizzare soluzioni
software con questo piccolo gioiellino. Come
primo passo forniremo una descrizione delle
caratteristiche, delle novit presenti nel modello
3G rispetto al precedente, successivamente si
descriver la struttura del sistema operativo e
dell'SDK e, infine, mostreremo come realizzare
una semplice interfaccia.
Questo articolo indirizzato sia agli utenti pro-
prietari della versione 2G che quella 3G: non
faremo quindi distinzione tra i due modelli, a
meno di utilizzare qualche funzionalit specifica
che non sia presente, a causa una carenza
hardware, in uno o nell'altro dispositivo.
Iniziamo con il dire che riferirsi all'IPhone come
un telefono cellulare un'affermazione abba-
stanza restrittiva. Personalmente lo descriverei
come un dispositivo che fornisce una potente
piattaforma di sviluppo e abilitato alla telefonia.
Vedetelo quindi come uno smartphone evoluto.
Questa frase potr sembrer una puntualizzazio-
ne inutile, ma considerarlo in tale modo rende
pi giustizia alle sue intrinseche caratteristiche
(la registrazione di circa 300 brevetti su tale
dispositivo da parte di Apple ha sicuramente una
certa rilevanza in questa mia precisazione).
Ecco quindi le caratteristiche del "telefono"
(comuni sia al modello 2G che al 3G):
G Sistema operativo: iPhone OS;
G Processore: Samsung S5L8900 (412 MHz ARM
1176);
G Scheda video: PowerVR MBX 3D;
G Perifericha di input: Multi-touch screen;
G Risoluzione: 320 x 480 pixel a 163 pixel per pol-
lice;
G Fotocamera da 2 megapixel;
G Localizzazione utilizzando la posizione delle
celle e sfruttando anche le reti Wi-Fi disponibi-
li;
G Memoria: 128 MB DRAM;
G Memoria fisica disponibile: 8 GB o 16 GB di
memoria flash;
G UMTS (850/1900/2100);
G Quad band GSM (850/ 900 / 1800 / 1900) /
GPRS / EDGE;
G Wi-Fi (802.11b/g);
G Bluetooth 2.0 con EDR;
G Sensore di prossimit (per disabilitare lo scher-
mo quando si avvicina la testa al telefono per
rispondere o effettuare una telefonata).
Le differenze principali, a esclusione di quelle
estetiche/strutturali (pi plastica e meno metal-
lo nel nuovo modello)/durata della batteria, pre-
senti tra le due generazioni di IPhone, sono
l'aggiunta dell'A-GPS (assisted GPS), che ha per-
Conoscenze richieste
OOP - Object-C
Software
Sistema Operativo
Leopard 10.5.3
(necessario per
utilizzare l'SDK beta 7
o superiore), Iphone
SDK
Impegno
Tempo di realizzazione
REQUISITI
PROGRAMMARE
LAPPLE IPHONE
INIZIAMO A CONOSCERE L'AMBIENTE DI SVILUPPO E LE TECNOLOGIE PER REALIZZARE SOFTWARE
PER IL NUOVO GIOIELLO DI CASA APPLE. VEDREMO COME SI PROGETTA UNAPPLICAZIONE,
RIUSCENDO A TESTARLA ANCHE SE NON POSSEDIAMO IL COSTOSO SMARTPHONE
Fig. 1: La semplice interfaccia per dispositivo iPhone
che andremo a realizzare
012-021:032-035 16-07-2008 10:38 Pagina 12
messo di realizzare il photo geotagging (ogni foto
sar associata alla posizione misurata dal GPS,
questa funzionalit viene gi utilizzata in ambito
professionale fotografico, in genere naturalisti-
co), del supporto per l'UMTS, e dell' HSDPA.
L'A-GPS una tecnologia che stata realizzata
per ridurre il carico computazionale necessario
per la prima localizzazione (Fixing) e risolvere
quei casi in cui impossibile, in genere a causa
della presenza di barriere fisiche, rilevare almeno
i quattro satelliti necessari per la localizzazione
del dispositivo; utilizza quello che viene chiama-
to un Assistance Server, il cui scopo quello di for-
nire, venendo a conoscenza della cella a cui si
collegato il telefono, la sua posizione approssi-
mata e le informazioni su quali satelliti sono visi-
bili nelle vicinanze di tale cella. Se non disponete
di un software di navigazione, con relative
mappe, sarete costretti a utilizzare i servizi dispo-
nibili online, Google Maps in primis, rendendo
necessario il pagamento del traffico Internet uti-
lizzato per reperire tali informazioni. L'HSDPA
il protocollo attualmente utilizzato su reti UMTS
per raggiungere velocit di download oltre il
Mbit/s.
Mancano il supporto di memorie esterne rimo-
vibili, una fotocamera frontale per fare le
videotelefonate e il Flash Player! La seconda
carenza stata una scelta abbastanza inusuale
(anche se presente in alcuni modelli di cellula-
ri Nokia sempre UMTS) e preclude un possibi-
le sviluppo di applicazioni che sfruttino la
seconda videocamera: si sarebbe potuto svi-
luppare software per realizzare effetti da appli-
care sul volto dell'utente mentre effettuava una
videochiamata o possibili sistemi di sicurezza
tramite face detection, per citarne solo alcuni.
La mancanza del player Adobe Flash purtrop-
po dovuta a problemi di prestazioni, che sia
Adobe che Apple stanno cercando di risolvere;
una possibile esclusione da questo modello
sarebbe di sicuro una grave penalizzazione per
la fruizione dei contenuti disponibili in rete.
Queste tre mancanze sono, forse, quelle che
potrebbero scoraggiare molti utenti allacqui-
sto e invogliarli ad aspettare magari la terza
release hardware di questo piccolo telefo-
no/non telefono.
NOVIT NELL APPLE
IPHONE 2.0
I successivi aggiornamenti del sistema operativo
dell'IPhone hanno apportato migliorie e risolto
problemi pi o meno noti, sono state inoltre
aggiunte funzionalit per renderlo pi aperto alla
comunicazione con tecnologie non Apple.
possibile ora sincronizzarsi con Microsoft
Exchange ActiveSync, quindi avere appuntamen-
ti, contatti ed email sempre aggiornati con la
propria postazione fissa/mobile; stata aggiunto
il supporto per la connessione su reti VPN con
L2TP/IPSEC utilizzando tecnologia Cisco; ora
supporta il WPA2 Enterprise (tecnologia che uti-
lizza un server per autenticarsi) e il protocollo
autenticazione per reti 802.1X; pu gestire, inol-
tre, documenti Microsoft Word, Excel e
Powerpoint, Adobe PDF e Apple IWork. Segnali,
questi, di un forte indirizzamento verso il mondo
business e una volont di divenire un nuovo
dispositivo di riferimento per chi ha necessit di
gestire diverse tipologie di informazioni e con-
nettersi a organizzazioni che utilizzano tecnolo-
gie e documenti in formati diversi.
L'ITER DI SVILUPPO
SU IPHONE SECONDO
APPLE
Finch l'SDK sar distribuito come beta, avrete la
possibilit di realizzare qualunque software
senza alcun limite, ma questo stato durer anco-
ra per poco: quando verr rilasciata una versione
stabile si dovr acquistare una delle due licenze
disponibili. Lo Standard Program (attualmente il
prezzo dichiarato di 99$) dedicato a program-
matori intenzionati a realizzare software gratuito
e a pagamento sia per IPhone sia per ITouch,
L'enterprise Program ($299) indirizzato, invece,
allo sviluppo e alla distribuzione.
Prezzi comunque competitivi, ovviamente trala-
sciando il "leggero" requisito di possedere un
computer con Mac OS X 10.5.3 installato, oltre a
un IPhone per effettuare dei test sul campo. Il
centro nevralgico da cui fluisce qualunque
software , a meno di cambi di strategia da parte
di Apple, l'App Store, nel quale possibile inseri-
re le proprie creazioni, deciderne il prezzo (
inoltre concesso rilasciarle in maniera gratuita) e
ottenere un 70% di ricavi dalla loro vendita. Le
applicazioni non possono superare i 2GB di
grandezza e, nel caso non fossero gratuite,
dovranno costare non meno di 0.99$ e non pi di
999$. possibile disabilitare il download/utilizzo
a seconda del paese di appartenenza. Sar obbli-
gatorio firmare digitalmente la propria release
software con un sistema di chiavi (pubbli-
ca/privata) ottenute su richiesta direttamente ad
Apple, per avere accesso alla distribuzione onli-
ne; il vostro programma sar, inoltre, firmato
ulteriormente dalla casa di Cupertino prima di
venire resa effettivamente disponibile ai possibi-
li acquirenti: tutto questo allo scopo di garantire
la provenienza e l'originalit del software.
ht t p: / / www. i opr ogr ammo. i t
M
COVER STORY
Settembre 2008/
13
G
Software e tecniche per programmare liPhone
NOTA
RIFERIMENTI E
DOCUMENTAZIONE
Allindirizzo
http://developer.apple.co
m/iphone/program/
potrete ottenere tutta la
documentazione (in
formato HTML e/o PDF)
necessaria per realizzare
qualunque idea vi venga in
mente, inoltre, previa
registrazione, potrete
scaricare l'SDK (che
include inoltre XCode e
tutti gli strumenti
necessari per realizzare
una soluzione completa). I
manuali che ho consultato
per generare questo
articolo sono (scaricabili
gratuitamente dal sito
Apple appena citato):
IPhone OS Programming
Guide, Cocoa
Fundamentals Guide, The
Objective-C 2.0
Programming Language,
XCode User Guide, UIKit
Framework Reference,
Foundation Framework
Reference. Presso
http://en.wikipedia.org/w
iki/List_of_ISO_639-
1_codes e
http://en.wikipedia.org/w
iki/List_of_ISO_639-
2_codes troverete i codici
da utilizzare per
supportare la
localizzazione.
012-021:032-035 16-07-2008 10:38 Pagina 13
ht t p: / / www. i opr ogr ammo. i t
COVER STORY
M
G
14
/Settembre 2008
Software e tecniche per programmare liPhone
SENSORI, SENSORI
E ANCORA SENSORI...
Oltre all'accelerometro di sensibilit +/-5G , in
grado di fornire informazioni sulla posizione
(rotazione, rollio e beccheggio) e descritto in
maniera esaustiva in un precedente articolo per
utilizzare il controller della WII (i pi attenti
ricordano che la sua sensibilit invece di +/-
3G), sono integrati altri due tipi di sensori: uno
di luce ambientale, il cui scopo quello di misu-
rare l'intensit della luminosit esterna e regola-
re la propria conseguentemente, e laltro di pros-
simit, in grado di determinare se l'utente ha
posto il proprio volto vicino al telefono e il cui
unico intervento quello di spegnere l'LCD per
risparmiare batteria (semplice come idea ma
sicuramente efficace per aumentare di qualche
minuto la durata della non proprio performante
batteria).
IL CICLO DI VITA
DI UN'APPLICAZIONE
L'SDK permette di creare applicazioni esplici-
tamente grafiche in grado di essere eseguite
sull'IPhone OS, il sistema operativo dello
smartphone. Ogni applicazione installata
trova posto all'interno dellHome Screen, la
finestra principale che ogni utente si trova
davanti all'accensione del telefono, contenen-
te tutte le icone degli applicativi disponibili.
All'avvio, il vostro programma occuper tutto
lo schermo, ad esclusione del kernel e di alcu-
ni demoni di basso livello, sar l'unica applica-
zione a essere eseguita: dimenticatevi quindi
di poter avviare numerosi programmi in back-
ground e farli colloquiare come avviene in un
ambiente multitasking. La scelta di evitare
l'esecuzione in contemporanea giustificata
da Apple come una garanzia di accedere in
maniera esclusiva alle risorse disponibili.
Dopo che l'utente ha terminato di utilizzare il
sofware gli baster premere il tasto home,
quello posizionato sotto lo schermo, per ter-
minare il programma e tornare alla schermata
di benvenuto del telefono.
LINEE GUIDA
DI SVILUPPO
Dal primo utilizzo dell'IPhone si apprezza la
velocit del reperimento delle informazioni;
per tale motivo conviene sempre seguire alcu-
ne regole che miglioreranno l'esperienza che
fornirete ai vostri utenti. Pi renderete veloce
la vostra applicazione nell'avvio e nella chiu-
sura, pi sar utilizzata da un utente;
un'interfaccia intuitiva e nella quale l'accesso
alle informazioni importanti alla portata di
uno o due colpetti di dita, sar di sicuro un
incentivo per incrementare il numero di utiliz-
zi del vostro programma. importante memo-
rizzare in che menu si trovava l'utente prima
che uscisse durante il precedente utilizzo, in
modo da permettergli di accedere subito al
punto in cui si era fermato (a causa di una
telefonata o per altro motivo). Non create
decine di finestre di configurazione con poche
informazioni, ma raggruppate il pi possibile
tali dati, magari separandoli opportunamente
(dopo tre o quattro finestre consecutive in cui
si incrementa il dettaglio delle impostazioni, si
incrementa il senso di confusione di molti
utenti). Non cercate di ridurre il testo e/o le
immagini oltre l'umana visione per visualizza-
re tutto in una schermata, non abbiamo tutti
10/10: una soluzione quella di fornire la pos-
sibilit di cambiare a piacimento tali dimen-
sioni (come avviene in molti siti web accessi-
bili). Utilizzare prima quei controlli dell'inter-
faccia grafica forniti con l'SDK, poich sono
ben noti all'utente e ha esperienza nel loro uti-
lizzo: se fosse veramente necessario, sviluppa-
tene altri, cercando di ridurre al minimo la
loro complessit. Ricordate che molti di voi
realizzeranno soluzioni per un insieme etero-
geneo di utenti e che la gran parte di queste
persone non ha molta pazienza, essendo abi-
tuate ad avere tutto gi preconfigurato: sem-
plificate quindi il pi possibile!
COCOA E L'OBJECT-C
Cocoa il termine coniato da Apple per raggrup-
Fig. 2: I versi positivi degli assi di riferimento
dell'accelerometro
012-021:032-035 16-07-2008 10:38 Pagina 14
ht t p: / / www. i opr ogr ammo. i t
pare un'intera famiglia di framework, API e
software annesso, realizzati principalmente in
Object-C, che costituiscono il substrato neces-
sario per realizzare ogni applicazione indirizza-
ta per Mac OS X e Iphone OS. Il linguaggio con
cui dovrete confrontarvi sar quindi l'Object-C,
insieme di estensioni del linguaggio ANSI C, rea-
lizzato per fornire un approccio pi semplice
all'object orienting. Per chi avesse iniziato a pro-
grammare con linguaggi quali .NET o JAVA, e
non avesse mai avuto necessit di confrontarsi
(per molti sarebbe meglio dire scontrarsi) con il
linguaggio C e/o il C++ dovr abituarsi a gestire
la memoria utilizzata poich l'IPhone non sup-
porta il garbage collecting, presente invece in Mac
OS; questo, per i non pratici, significa che ogni
allocazione di risorse, utilizzare un qualunque
file presente sull'HD delll'IPhone, creare
un'istanza di una classe o una struttura dati,
comporter, ovviamente, un utilizzo di un certo
quantitativo di memoria: tale richiesta dovr
essere gestita personalmente da voi e sarete
responsabili del rilascio di tali informazioni.
Per nostra fortuna comunque disponibile un
sistema di gestione controllata della memoria
tramite i metodi autorelease e release. Malloc e free
sono comunque obbligatori per riservare e rila-
sciare blocchi di memoria. Un'altra sgradevole
notizia, a mio dire la pi grande limitazione,
che non potrete utilizzare pi risorse di quelle
disponibili (in termini di memoria) poich non
supportata alcuna tecnologia di swapping
(quindi non si potranno creare eccessive strut-
ture dati ad esempio, o caricare file di grandi
dimensioni): la memoria fisica a disposizione
l'unica che sar accessibile; il sistema operativo
cercher di liberare pi blocchi di RAM possibi-
le quando richiesto, rimuovendo quei program-
mi non necessari al momento. Caratteristiche
che potrebbero scoraggiare molti sviluppatori,
mentre di sicuro allettano quei programmatori
pi indirizzati all'ottimizzazione delle proprie
applicazioni, e magari con un background di
C/C++.
UN BREVE SGUARDO
ALL'OBJECT-C
Programmare in Object-C non cos difficile se
si ha una buona conoscenza di un linguaggio
object oriented, come Java o C#, ma sono neces-
sarie delle spiegazioni per ridurre al minimo il
disagio necessario per addentrarsi in un lin-
guaggio sicuramente pi spartano.
Per ogni classe troverete (e dovrete realizzare)
due file, uno con estensione .h e l'altro .m, il
primo conterr l'interfaccia, inclusa all'interno
delle direttive @interface e @end, contenente
solo i metodi (senza il corpo) e le variabili, men-
tre il secondo, l'implementazione, racchiusa tra
le direttive @implementation e @end, conterr
tutto il codice utilizzato da ogni metodo; ovvia-
mente quest'ultimo file dovr essere collegato al
file di estensione .h con la direttiva #import
filediinterfaccia.h. Un'istanza di una classe
viene creata tramite id nomeistanza =[[nomeclasse
alloc] init], in cui il tipo id utilizzato per identi-
ficare una variabile che contiene (in realt un
puntatore) un'istanza di una classe, alloc richie-
de l'allocazione di memoria per contenere
l'oggetto in questione, init invocher il costrut-
tore omonimo; la distruzione dell'oggetto
avverr tramite il metodo release/dealloc (a
seconda del metodo reso disponibile dalla clas-
se). I metodi si possono invocare utilizzando la
seguente sintassi: [nomeinstanza metodo: para-
metro1 :parame-troN]; possibile creare, auto-
maticamente, metodi getter e setter per una pro-
priet di una classe utilizzando la direttiva @syn-
thetize nomepropriet all'interno del codice del-
l'implementazione, descrivendo poi nell'inter-
faccia le caratteristiche di tali accessors nel
seguente modo: @nomepropriet(attributi) tipo
*nome; nel caso voleste creare dei metodi ad hoc
baster utilizzare la direttiva @dynamic e scrivere
il relativo codice. Nei prossimi numeri spiegher
ovviamente in dettaglio molte delle caratteristi-
che di questo linguaggio, ma le informazioni che
vi ho fornito sono sicuramente il minimo indi-
spensabile per riuscire a comprendere, almeno
superficialmente, il codice presente nell'appli-
cativo generato dall'SDK quando si crea un
nuovo progetto.
LA STRUTTURA DEL
SISTEMA OPERATIVO
Il kernel presente sull'IPhone una variante di
quello esistente su Mac OS X, il Mach kernel;
entrambi sono strutturati su alcuni livelli che
utilizzano i servizi forniti da quelli inferiori e ne
mostrano altri a quelli superiori (la tipica strut-
M
COVER STORY
Settembre 2008/
15
G
Software e tecniche per programmare liPhone
Fig. 3: La struttura a stack disponibile per lo svi-
luppo di programmi su iphone
012-021:032-035 16-07-2008 10:38 Pagina 15
ht t p: / / www. i opr ogr ammo. i t
tura a stack, come quella definita dal Modello
ISO/OSI utilizzato per la comuncazione tra com-
puter). Di seguito l'elenco dei layer disponibili:
G Core OS: fornisce tutto il necessario per acce-
dere all'IPhone OS al livello pi basso consen-
tito, quindi accesso ai file di sistema, thread
POSIX, socket BSD, servizi Bonjour (ricerca di
periferiche collegate, quali stampanti e web-
cam ad esempio), servizio DNS, allocazione
della memoria, funzioni matematiche etc.
Il codice qui implementao scritto completa-
mente in C;
G Core Services: questo layer fornisce il fra-
mework Core Foundation, supporta la gestio-
ne delle stringhe, delle date, delle preferenze,
thread e loop del metodo run, comunicazione
tramite socket, collezioni quali array, set e
altre strutture dati, supporto per i file bundle
(che andremo a mostrare in dettaglio, sono
comunque i contenitori delle applicazioni
che andremo a creare). Troviamo, inoltre, il
framework Address Book, per accedere e gesti-
re i contatti, il framework Address Book UI
responsabile della visualizzazione di tali voci,
il framework Core Location che vi fornir la
posizione del vostro telefono (quando possi-
bile) in termini di latitudine e longitudine, il
framework CFNetwork, che permette, attra-
verso astrazioni realizzate tramite program-
mazione a oggetti, di utilizzare i socket BSD,
resolving di indirizzi tramite DNS, creare con-
nessioni sicure utilizzando SSL o TLS, gestire
connessioni HTTP/S e/o FTP, avere accesso ai
servizi Bonjour. Il framework Security permet-
te di gestire certificati, chiavi pubbliche e pri-
vate, generare sequenze e criptare informa-
zioni sensibili sul vostro device. La libreria
SQLite consente di utilizzare un database
molto leggero. supportata la gestione di file
XML tramite le librerie libXML2 e libXSLT, la
seconda fondamentale per la trasformazione
veloce, in html ad esempio, dei vostri file xml
in formati human-readable. In questo layer
troviamo sia oggetti realizzati in C che in
Objective-C.
G Media: situato in posizione elevata nello stack
troviamo oggetti e funzioni realizzati in
Objective-C, come il Media Layer, per la gestio-
ne di 2D, 3D, contenuti audio e video, il sup-
porto per OpenGL ES, Quartz e Core Audio
(scritti invece in C), Open Audio (fornisce il
supporto per l'audio 3D). inoltre disponibile
la Core Animation, libreria Objective-C per la
realizzazione di animazioni in grado di sfrutta-
re un rendering ottimizzato.
G Cocoa Touch: la punta di questo iceberg di
servizi il livello Cocoa Touch, scritto quasi
completamente in Objective-C: al suo interno
sono disponibili il framework Foundation e
quello UIKit; compito di questi due servizi
quello di fornire il supporto per la gestione
degli eventi, delle finestre, dell'interfaccia
utente, dei controlli, dei testi, dei contenuti
web, dei dati provenienti dall'accelerometro,
della fotocamera, della libreria delle foto, delle
informazioni del vostro dispositivo, gestione
object oriented delle collezioni, dei file, delle
connessioni di rete. In questo layer troviamo
quindi la maggior parte delle classi e funzioni
necessarie per realizzare un'applicazione
completa.
Quartz sia il window server sia il motore di ren-
dering in grado di gestire contenuti grafici, gra-
dienti, font, colori, livelli, immagini, PDF e trac-
ciati, mentre UIKit, posizionato proprio sopra il
suddetto server, fornisce, tramite opportune
strutture e classi, quegli strumenti che rendono
pi semplice l'accesso e la modifica dei contenu-
ti forniti da Quartz.
Il consiglio quindi quello di iniziare a program-
mare partendo dal livello pi alto, e semplice, il
Cocoa Touch, per poi scendere in caso maturas-
se la necessit di realizzare soluzioni ad hoc che
non sono ancora disponibili.
IL PUNTO DI INIZIO
Unapplicazione, quando viene avviata, esegue
immediatamente il tipico metodo/funzione
main, presente nel file main.m localizzato
nella cartella Other Sources, nel quale obbli-
gatorio creare un oggetto responsabile del rila-
scio delle risorse (autorelease), invocare la fun-
zione UIApplicationMain e rilasciare l'oggetto
autorelease quando l'interfaccia terminata.
#import <UIKit/UIKit.h>
int main(argc, *argv[]) {
NSAutoreleasePool* pool = [[] ];
intretVal = (argc, argv, , );
[pool release];
returnretVal; }
Ogni applicazione che riceve eventi da parte di
un utente, o di altri componenti, deve utilizzare
un ciclo durante il quale li cattura e modifica
l'interfaccia grafica di conseguenza: tali funzio-
nalit sono abilitate dalla chiamata della funzio-
ne UIApplicationMain. Il sistema operativo rice-
ver le pressioni sul touch screen e le invier a
una coda (Event Queue) che provveder a instra-
COVER STORY
M
G
16
/Settembre 2008
Software e tecniche per programmare liPhone
012-021:032-035 16-07-2008 10:38 Pagina 16
ht t p: / / www. i opr ogr ammo. i t
dare le relative informazioni verso l'opportuno
oggetto della nostra applicazione: il primo a
rispondere a tali messaggi l'oggetto di tipo
UIView, che rappresenta la finestra visibile in
quel momento, altrimenti risale nell'albero
delle finestre (la cosiddetta responder chain)
venendo scartato nel caso peggiore. Questa serie
di risposte alle interazioni da parte dell'utente
posizionata all'interno di un ciclo chiamato main
event loop. La gestione di tocchi multipli viene
risolta incapsulando le relative informazioni in
un oggetto di tipo UIEvent, che conterr una serie
di oggetti UITouch, ognuno in grado di fornire i
dati di ogni singola pressione. La classe che vi
permetter di intercettare tali eventi sar la
UIResponder e dovrete quindi implementare i
relativi metodi. Ogni UITouch contiene come
informazioni almeno la fase (inizio della pressio-
ne UITouchPhaseBegan, movimento del dito
UITouchPhaseMoved o allontanamenteo dallo
schermo UITouchPaseEnded), la posizione e la
View che ha ricevuto tale evento. Il comporta-
mento in risposta a pi pressioni contempora-
nee viene gestito in maniera simile.
FORMATI
AUDIO/VIDEO/IMMAGINE
SUPPORTATI
I formati di immagini supportati sono: JPEG,
BMP, GIF, TIFF, PNG, ICO, CUR, XBM.
Il framework Mediaplayer responsabile della
visualizzazione corretta di file multimediali, le
estensioni supportate sono le seguenti: MOV,
MP4, M4V, 3GP. I codec supportati, invece sono:
H.264 (fino a 640x480 pixel a 30fps), MPEG-4,
MP3, AAC, Apple Lossless (ALAC), A-law,
IMA/ADPCM (IMA4), linear PCM, -law.
La registrazione dell'audio pu essere effettuata
nei seguenti formati: A-law, IMA-ADP CM
(IMA4), linear PCM, -law.
comunque probabile che il numero di tali for-
mati possa aumentare nei successivi aggiorna-
menti del sistema operativo (si vocifera un sup-
porto per i filmati Adobe Flash).
OTTIMIZZARE
LA MEMORIA
Come segnalato, importante tenere sotto con-
trollo le risorse allocate durante l'intera vita del
vostro software e per tale motivo necessario
fornire opportuni consigli:
G caricate in memoria una risorsa (file di testo,
immagine, suono, video) solo quando stretta-
mente necessario, appena prima di utilizzarla,
e non all'avvio del software;
G rilasciate appena possibile le risorse preceden-
temente allocate e non pi necessarie;
G riducete al minimo la dimensione dei file sal-
vati sul device poich, quando caricati, sarete
comunque obbligati ad allocare memoria per
gestirli;
G comprimete al meglio le immagini (PNG, che
utilizza un algoritmo lossless, se non volete
perdere informazioni importanti, mentre
JPEG, che invece ne sfrutta uno lossy, se siete
disposti a ridurne la qualit) e riducete le
dimensioni (intendo larghezza e altezza) al
minimo necessario;
G utilizzate SQLLite quale gestore dei vostri dati,
ovviamente quando necessario: questa solu-
zione vi permetter di ottenere solo le singole
entit (come record del database) invece di
dover gestire l'intera struttura dati;
G compilate usando il flag -mthumb, in grado di
ridurre il codice di circa un 30%, ma solo nel
caso non utilizziate pesanti calcoli in virgola
mobile (altrimenti potrebbe avere un effetto
degradante in termini di prestazioni, in tal
caso utilizzate le istruzioni ARM).
Resta comunque obbligatorio, per realizzare un
buon prodotto, utilizzare pi volte, durante
tutto il ciclo di sviluppo, Shark e Instruments,
per comprendere meglio, e possibilmente sem-
plificare e/o alleggerire, possibili punti critici
del vostro codice. Ma cosa succederebbe se si
utilizzassero tutte le risorse disponibili di
memoria? Il sistema lancerebbe una notifica
indirizzata al programma attualmente in primo
piano e spetter al codice, che avrete ovviamen-
te creato, intercettarla e cercare di rilasciare il
prima possibile quelle risorse che al momento
non sono necessarie. Altrimenti? Il vostro
software verr terminato automaticamente. Per
ricevere tali notifiche potrete:
G implementare il metodo applicationDidReceive
MemoryWarning;
G fare overriding del metodo didReceiveMemory
Warning se avete realizzato una sottoclasse
della UIViewController;
G registrarsi per ricevere la notifica tramite il
metodo UIApplicationDidReceiveMemmory
WarningNotification.
M
COVER STORY
Settembre 2008/
17
G
Software e tecniche per programmare liPhone
012-021:032-035 16-07-2008 10:38 Pagina 17
ht t p: / / www. i opr ogr ammo. i t
importante che, oltre ai file utilizzati, rimuovia-
te anche quelle finestre (views) che non sono visi-
bili sullo schermo. possibile inviare tale avviso
durante l'esecuzione nel simulatore utilizzando
il comando Simula avviso memoria disponibile
nel men Hardware.
PRESERVIAMO
LA DURATA
DELLA BATTERIA
Le non eccezionali prestazioni della batteria
sono ormai una certezza, ma con qualche picco-
lo consiglio riuscirete a non ridurne ulteriormen-
te la vita quando un utente eseguir un vostro
applicativo:
G Connettetevi utilizzando qualunque tecnologia
wireless solo quando strettamente necessario.
Evitate, inoltre, di effettuare richieste cicliche per
verificare se una data informazione disponibile
o un certo oggetto ha variato il suo stato;
G Se richiedete, o inviate, informazioni attraver-
so una rete, trasmettete solo il minimo indi-
spensabile, siate parsimoniosi!
G Se serve ottenere la posizione del device utilizza-
te i sistemi di localizzazione per il pi breve
tempo possibile (l'intervallo tra attivazione e
disattivazione sia il pi breve possibile).
OTTIMIZZAZIONE CON
SHARK E INSTRUMENTS
Shark e Instruments (oltre ad altri programmi
presenti nell'SDK) dovrebbero divenire i vostri
fedeli compagni di sviluppo, se avete un minimo
di interesse nel realizzare programmi perfor-
manti. Shark permette di visualizzare gli eventi
ricevuti e trasmessi, i thread in esecuzione, gli
interrupt, e altre informazioni pi o meno inte-
ressanti. Instruments , invece, stato realizzato
per fornire dettagliati log e grafici sull'utilizzo
delle risorse, della CPU, della memoria, del file
system, del traffico sulla rete e degli oggetti utiliz-
zati (solo per citarne alcuni).
IL TOOL XCODE
Nonostante non sia una legge scritta, sarebbe
lecito considerare quasi indissolubile il legame
Xcode-IPhone SDK: questo tool (insieme agli
altri ad esso collegati) permette di gestire
l'intero ciclo di sviluppo di una soluzione
software per IPhone. Insieme a questo editor
troviamo installato inoltre un debugger, un
profiler (Shark) e l'editor WYSIWYG (Interface
Builder) per velocizzare la realizzazione delle
interfacce grafiche. E' ovviamente possibile
utilizzare repository che utilizzano tecnologie
quali SVN, CVS e Perforce. La documentazione
pu essere richiamata immediatamente sia se
disponibile in locale che in remoto. XCode non
comunque un insieme di strumenti unica-
mente indirizzati allo sviluppo per IPhone poi-
ch fornisce tutto il necessario per sviluppare
in JAVA, AppleScript RUBY, Python, C, C++ su
Mac OS X: uno strumento veramente potente
e completo, che necessit di decine di ore
prima di venire utilizzato adeguatamente.
IL SIMULATORE
DELL'IPHONE
Chi non ha modo di acquistare un IPhone si
sentir escluso da questo articolo, ma non
cos: infatti possibile realizzare praticamente
qualunque applicazione senza possederlo!
Questo consentito dall'ottimo simulatore
presente nell'SDK che fornisce tutte le funzio-
nalit del telefono reale. stato inoltre per-
messo di emulare la pressione di due dita con-
temporaneamente utilizzando un tasto della
tastiera mentre si muove il mouse.
Sembrerebbe tutto rose e fiori, ma non lo ,
poich il vero dispositivo diventa necessario
quando si vuole testare un'appli cazione relati-
vamente complessa; inoltre obbligatorio se si
utilizzano i dati dell'accelerometro, oppure si
gestiscono ulteriori tocchi con le proprie dita,
e soprattutto quando se ne vogliono testare le
reali prestazioni. Il simulatore ha modo di
sfruttare il processore Intel Dual Core del
vostro Mac che non ha nulla a che fare con il
modello a "soli" 412Mhz che avrete effettiva-
mente a disposizione! Identico discorso per la
COVER STORY M
G
18
/Settembre 2008
Software e tecniche per programmare liPhone
Fig. 4: La pagina di selezione del tipo di studio
da effettuare in Instruments
012-021:032-035 16-07-2008 10:38 Pagina 18
ht t p: / / www. i opr ogr ammo. i t
memoria disponibile! Non potrete provare
ovviamente la vibrazione, il sensore di prossi-
mit e tutte quelle interazioni che necessitano
del vero telefono.
Attenzione, quindi, a tenere in considerazione
problemi quali un refresh rate troppo lento,
accesso a strutture dati "corpose" o trasforma-
zioni di immagini di dimensioni ragguardevoli.
Per il resto, se il vostro sviluppo verr affronta-
to in maniera attenta e con la consapevolezza
di tali limiti, potrete ridurre al minimo tali pro-
blematiche.
IL PATTERN MVC
Per chi sviluppa nel settore web, enterprise e non
(utilizzando ad esempio CakePHP o Symfony in
ambiente PHP, Struts in Java oppure ASP.NET
MVC framework di Microsoft), avr ormai matu-
rato una certa esperienza nella realizzazione di
soluzioni software in cui si scindono le tre com-
ponenti fondamentali di una soluzione informa-
tica in singoli raggruppamenti semantici di codi-
ce: si parla del design pattern chiamato MVC
(model-view-controller), il cui scopo quello di
separare l'interfaccia grafica (view, chiamato
strato di presentazione, una pagina web oppure
una vera e propria finestra con relativi controlli)
dal motore che gestisce i dati (model, chiamato
strato di business, in genere un database) dal
codice (controller) responsabile di mettere in
comunicazione i due precedenti livelli (ad
esempio responsabile del salvataggio in un
database dei dati inseriti da un utente e di
mostrarli al suo successivo accesso nelle relative
posizioni).
Questo approccio ha lo scopo di ridurre al mini-
mo la dipendenza (il termine inglese loose cou-
pling) tra i tre livelli lasciando libert agli svilup-
patori di trovare le soluzioni pi adatte senza
creare problemi in caso decidesse di modificare
una certa parte di codice (uno spostamento, ad
esempio, tra Mysql a MSQL risulterebbe cos
indolore per chi responsabile del layout del
sito). Tutto questo permesso a patto che siano
ben definite le interfacce di comunicazione tra i
tre gruppi logici e che non cambino, a meno di
casi eccezionali. Il sistema operativo dell'IPhone
in effetti realizzato in tal modo, un esempio?
Applicando una singola modifica alla finestra
principale noterete che tali operazioni non
influenzeranno i file di codice presenti nella car-
tella /Classes.
LE WINDOW E LE VIEW
Alla base di ogni applicazione per IPhone trovia-
mo una serie di finestre, chiamate View e
Window, in cui la seconda una semplice View
con alcune caratteristiche aggiuntive. Sono orga-
nizzate in un albero la cui radice principale
identificata da una Window, che a sua volta con-
tiene tutte le View creata.
Tutto quello che realizzerete sfruttando queste
View utilizzer la Core Animation, il cui scopo
quello di permettere di animarle, spostarle, sca-
larle, trasformarle, nasconderle, renderle parzial-
mente trasparenti variando il valore di alpha,
ruotarle utilizzando opportune operazioni
matriciali, tutto senza rendere necessario
M
COVER STORY
Settembre 2008/
19
G
Software e tecniche per programmare liPhone
Fig. 5: Struttura logica del design pattern MVC
Fig. 6: La struttura tipica di un'applicazione
012-021:032-035 16-07-2008 10:38 Pagina 19
ht t p: / / www. i opr ogr ammo. i t
aggiornare il loro contenuto (con un effettivo
guadagno di prestazioni e risparmio di risorse).
Ma cosa sono le View allora? Semplici regioni ret-
tangolari, in realt istanze della classe UIView
descritte da file XML di estensione .xib, in caso
utilizziate l'editor visuale, blocchi di codice se
preferirete un approccio pi diretto, il cui scopo
ricevere eventi e disegnare il proprio contenu-
to. Tra le classi da essa derivate segnaliamo:
G Tab Bar: posizionata in basso, pu contenere
pulsanti utili per attivare velocemente alcune
opzioni;
G Navigation Bar: consente di spostarsi tra le
varie view disponibili.
G Search Bar: accetta l'inserimento di testo che
pu essere poi ricercato all'interno di uno o
pi testi.
G Container: permette di raggruppare, separare
dei contenuti oppure gestisce situazioni in cui
spesso le informazioni mostrate sono pi gran-
di dell'area visibile, come avviene nel caso
della UIScrollView;
G Control: fanno parte di questa classe bottoni,
switch, campi di testo e barre di scorrimento;
G Alert: tipico popup di avviso che pu contenere
anche una richiesta di inserimento testo;
G Action: messagio che compare dal basso dello
schermo;
G TextField: visualizza il testo con font, colore,
allineamento definiti, oltre a permettere di
modificarlo;
Ricordiamo nuovamente devitare troppe fine-
stre aperte, visibili e non, per non rischiare di
esaurire la memoria disponibile. Non ripulite
quelle zone che non lo necessitano, non utilizza-
te troppe finestre con sfondo trasparente o semi-
trasparente, salvate i file PNG senza i canali
alpha, utilizzate immagini gi con le dimensioni
ideali, magari prediligete la creazione di pi ver-
sioni con diverse risoluzioni per evitare che il
sistema operativo debba ridimensionarle ripetu-
tamente. Il sistema di coordinate utilizzato
molto semplice: il punto (0,0) (valori float)
posizionato nell'angolo alto a sinistra, l'asse x
cresce in direzione orizzontale verso la destra del
telefono, mentre quello y verso il basso.
Le dimensioni e la posizione di una View rispetto
a quella che la contiene, chiamata superview,
sono calcolate utilizzando le sue tre propriet:
frame, bounds e center: la prima indica la posizio-
ne e la dimensione utilzzando il sistema di coor-
dinate della view padre; il campo bounds rappre-
senta i margini interni che definiscono l'area
utile per disporre i suoi contenuti; center indica la
posizione del centro geometrico del rettangolo
che identifica la view utilizzando le coordinate
della superview. possibile, come accennato in
recedenza, applicare delle trasformazioni ad una
view, che avranno diversi effetti a seconda di
come stato impostata la propriet transform,
UIView ContentModeScaleToFill, UIViewContent
ModeScale AspectFit, UIViewContentModeScale
AspectFill, in cui il primo valore distorce sempli-
cemente il contenuto senza mantenere le pro-
porzioni, il secondo, invece, tiene conto del rap-
porto tra larghezza e altezza, mentre l'ultimo
ingrandisce il contenuto cercando di occupare la
maggiore area possibile, uscendo anche dall'area
visibile. Il ridisegno delle zone segnalate come
dirty/sporche, oppure nuove, avviene solo al rien-
tro nel ciclo principale di loop, il framework UIKit
provveder, quindi, a navigare attraverso la
gerarchia di view e a verificare quali hanno reale
necessit di tale operazione; possibile comun-
que forzare tale evento e impostare solo una sot-
toarea da ridisegnare utilizzando la funzione
setNeeds DisplayInRect, invece di richiamare il
generico setNeedsDisplay, sempre con il fine di
migliorare le prestazioni del vostro programma.
LSDK E LAVVIO
DEL SIMULATORE
Dopo esservi registrati sul sito, da cui possibile
scaricare l'SDK, armatevi di buona pazienza poi-
ch un file di oltre 1GB (non un errore di
stampa mi dispiace); al temine di questa opera-
zione potrete procedere con l'installazione (che
occuper circa 4GB) che finalmente consentir
di accedere a tutti i software (presenti nella car-
tella /Developer/Applications per quanto riguarda
gli eseguibili). Avviamo XCode, creiamo un
nuovo progetto, una View Based Application
(notate la possibilit di creare un programma
OpenGL ES), noterete, quindi, la comparsa di
numerosi file nella colonna di sinistra. Premete il
tasto Build and GO per avviare il simulatore, vi
troverete davanti a un IPhone perfettamente
funzionante (potrete anche usare Safari per navi-
gare sul web e aggiungere nuovi contatti nella
rubrica). Il mouse sar equiparao alla pressione
del dito (tenete inoltre premuto il tasto Option
per simulare due dita contemporaneamente,
simultaneamente a Shift per il trascinamento
sullo schermo, doppio clic per zoomare nel
visualizzatore di immagini, la rotellina per fare
COVER STORY M
G
20
/Settembre 2008
Software e tecniche per programmare liPhone
012-021:032-035 16-07-2008 10:38 Pagina 20
ht t p: / / www. i opr ogr ammo. i t
scrolling. Utilizzando il tasto in basso all'IPhone
chiuderete il programma e tornerete alla Home.
STRUTTURA
DI UN'APPLICAZIONE
Il programma che realizzerete e andrete a installare
ed eseguire sar contenuto in un sandbox, un
ambiente protetto che eviter che i vostri dati ven-
gano modificati da programmi esterni, ma anche
che voi alteriate risorse di cui non avete il control-
lo; ad ogni programma installato viene associato
un numero identificativo unico che sar il nome
della relativa sottocartella che lo conterr situata in
/ApplicationRoot. La struttura la seguente:
Application Home/
G Programma.app
G Documents/
G Library/Preferences/
G tmp/
G Programma.app: il bundle contenente tutte le
risorse necessarie per l'esecuzione del pro-
gramma;
G Documents/: cartella in cui il programma ha il
permesso di salvare i dati;
G Library/Preferences/: cartella in cui vengono sal-
vati (utilizzando l'API CFPreferences) tutte le
impostazioni di configurazione;
G tmp/: i file temporanei possono essere qui scrit-
ti ma devono essere rimossi volontariamente
dal vostro applicativo.
Dovete comunque porre attenzione a bug, come i
buffer overflow, spesso scaturiti dal mancato con-
trollo dei dati di input forniti dall'utente, che per-
metterebbero a un programmatore di inserire del
codice per eseguire software malevolo. Il software,
come appena scritto, contenuto all'interno di un
bundle, un file la cui struttura simile al tipico tree
di un file system, di estensione .app.
Include tutte le risorse necessarie per il corretto
funzionamento dellapplicativo (immagini, video,
suoni, altri file ed eseguibili).
Un programma per IPhone dovrebbe contenere
almeno i seguenti file: Programma.app/, Pro gram-
ma, Settings.bundle, MainWindow.nib, Sfondo.png,
Icon.png, Default.png, Info.plist, en.lproj, it.lproj.
G Programma: l'eseguibile da noi realizzato;
G Settings.bundle: una cartella che contiene varie
impostazioni, e consente di renderle visibili
nella sezione Impostazioni/Settings del telefono;
G MainWindow.nib: il file utilizzato per definire
un'interfaccia grafica minimale;
G Icon.png e Default.png: due risorse utilizzate
per rappresentare l'icona (formato PNG, 57x57
pixel) che andremo a cliccare per farlo avviare
e quella dello splashscreen (formato PNG,
320x480 pixel); baster aggiungere l'Icon.png e
il file Default.png da voi creati tramite la voce
Project->Add to project per visualizzarli al suc-
cessivo avvio del simulatore;
G Sfondo.png: esempio di risorsa non localizzata,
questo tipo di file viene salvato nella root princi-
pale, poich non associato ad alcuna lingua
specifica;
G info.plist: contiene le informazioni associate al
software tra cui ID, versione e nome;
G en.lproj e it.lproj: cartelle contenenti tutte le tra-
duzioni necessarie per la corretta localizzazione
I file contenuti nella cartella en.lnproj/ sono i
seguenti:
InfoPlist.strings, Localizable.strings, flag.png. In cui:
InfoPlist.strings integra la traduzione delle voci
presenti nel file info.plist presente nella cartella
principale; Localizable.strings la traduzioni delle
stringhe presenti nel codice;
flag.png limmagine localizzata; in questo caso
potrebbe rappresentare la bandiera del Regno
Unito. Cliccando sul file Info.plist, presente nella
cartella Resources del vostro progetto, quando
siete in XCode, potrete modificare alcune impo-
stazioni del programma. Notate come sia impo-
stato nell'ultima voce il file nib (la finestra princi-
pale) che viene eseguito all'avvio (MainWindow
in questo caso). Cliccando, invece, due volte sui
file presenti nella cartella /NIB Files avrete modo
di eseguire l'Interface Builder. Apriamo, quindi,
tale editor sul file nomeprogetto ViewController.xib
e, cercando all'interno della finestra Library, tra-
sciniamo un oggetto Label e uno Data Picker: ese-
guite l'applicazione e avrete cos creato, con una
velocit strabiliante, una semplice interfaccia
grafica per il vosto amato Apple iPhone.
CONCLUSIONI
Nei prossimi numeri approfondiremo l'utilizzo
delle librerie disponibili e dell'interface builder allo
scopo di realizzare un programma completo.
Andrea Leganza
M
COVER STORY
Settembre 2008/
21
G
Software e tecniche per programmare liPhone
LAUTORE
Laureato in Ingegneria
Informatica, da oltre un
decennio realizza soluzioni
multimediali e software su
svariate piattaforme e con
diversi linguaggi.
Certificato EUCIP Core,
appassionato di fotografia,
lingua giapponese,
istruttore di nuoto FIN, ha
recentemente lavorato
come tester di dispositivi
mobili per un grande
operatore mobile italiano;
contattabile su
neogene@tin.it o
direttamente sul sito
www.leganza.it.
012-021:032-035 16-07-2008 10:38 Pagina 21
PROGETTI JAVA
CON ECLIPSE
QUESTA NUOVA RICETTA ILLUSTRA I PASSI NECESSARI PER LA CREAZIONE E LA GESTIONE
DI UN PROGETTO JAVA. SARANNO ILLUSTRATE LE PROSPETTIVE E LE VISTE CLASSICHE
PER LO SVILUPPO DI UNAPPLICAZIONE
E
clipse, con i suoi tanti plug-in, virtualmente un
ambiente di sviluppo per qualsiasi linguaggio e per
qualsiasi ambito. Pu essere impiegato per svilup-
pare codice C/C++, pu essere utilizzato anche per realiz-
zare documenti web (HTML, CSS, XML) e persino per
manipolare i contenuti di un database. Nella stragrande
maggioranza dei casi, per, Eclipse viene adoperato per lo
sviluppo di software Java. In questa lezione saranno illustrati
e dimostrati i concetti di base indispensabili per la creazione
e la manipolazione di un progetto Java in Eclipse.
CREARE
UN PROGETTO JAVA
La prima cosa da fare per creare un progetto Java in
Eclipse utilizzare lapposito wizard della piattafor-
ma. Dal menu bisogna selezionare File New Java
Project.
Immediatamente sar mostrata la schermata della
procedura di creazione del progetto.
La prima informazione richiesta il nome che si
vuole dare al progetto. Digitiamo Ciao Mondo per
la nostra applicazione esemplificativa. Le aree sotto-
stanti permettono di controllare alcuni parametri
fondamentali.. La prima area, titolata Contents,
chiede di stabilire come creare il progetto. La scelta
predefinita Create new project in workspace;
significa che un nuovo progetto inizialmente vuoto
sar creato nel workspace in uso (cfr. Ricetta #1,
ioProgrammo 129). In alternativa, selezionando
Create project from existing source possibile
creare un nuovo progetto importando dei sorgenti
gi esistenti. La seconda delle aree disponibili, quel-
la titolata JRE, permette di scegliere la piattaforma
di sviluppo da utilizzare fra quelle configurate pre-
cedentemente in Eclipse (cfr. Ricetta #1). Grazie a
questa opzione possibile sviluppare (e contempo-
raneamente verificare) il proprio software su una
specifica versione di Java. La terza area, Project lay-
out, permette di scegliere come organizzare i sor-
genti allinterno del nuovo progetto. Due le ipotesi
possibili: inserire i package e i sorgenti direttamente
allinterno della cartella principale del progetto,
oppure creare allinterno di questa una sotto-direc-
tory specifica per i sorgenti, tipicamente nominata
src. Nelle pi recenti versioni di Eclipse questultima
la scelta predefinita. Utilizzare una cartella specifi-
ca per i sorgenti, infatti, generalmente pi como-
do, in quanto il progetto pu contenere anche altri
tipi di cartelle e di file, come immagini, configura-
zioni ecc. Lultima area, Working sets, permette di
associare il progetto a un working set.
I working set sono una delle mille facilitazioni offer-
te da Eclipse per filtrare i progetti e imporre delle
viste sui contenuti.
SOFTWARE M Impariamo a utilizzare il framework Eclipse
ht t p: / / www. i opr ogr ammo. i t
G
22
/Settembre 2008
Conoscenze richieste
Rudimenti di Java
Software
Java SDK (JDK), Eclipse
Impegno

Tempo di realizzazione
REQUISITI
Fig. 1: Per creare un nuovo progetto Java selezionare dal menu di Eclipse la voce
File New Java Project.
Fig. 2: La prima schermata del wizard di creazione
di un nuovo progetto Java.
022-024:088-093-corsi-xsl 16-07-2008 9:10 Pagina 22
ht t p: / / www. i opr ogr ammo. i t
Settembre 2008/
23
G
Impariamo a utilizzare il framework Eclipse M
SOFTWARE
Per ora possibile tralasciare questo aspetto. Dopo
aver compilato, come si desidera, la schermata del
wizard, possibile passare immediatamente alla
configurazione di altre caratteristiche di progetto
con il tasto Next, oppure creare e utilizzare imme-
diatamente il progetto, con il tasto Finish.
Scegliamo questultima strada. Daltronde, la confi-
gurazione di un progetto pu sempre essere variata,
in qualsiasi momento, selezionando il progetto e
visualizzandone le propriet nel menu mediante
tasto destro.del mouse.
LE PROSPETTIVE
Laggettivo pi adatto per descrivere il piano di lavo-
ro di Eclipse : liquido. Ogni elemento pu essere
scelto, dimensionato e posizionato a piacere dallu-
tente. La piattaforma comprende centinaia di stru-
menti e gadget, e lo sviluppatore pu mescolare
insieme quelli a lui pi congeniali, in modo da crear-
si uno o pi set di riferimento. Queste combinazioni
prendono il nome di prospettive (perspective).
Eclipse, inoltre, mette a disposizione un buon
numero di prospettive predefinite. La distribuzione
di Eclipse dedicata agli sviluppatori Java comprende
almeno tre o quattro prospettive predefinite che si
adattano bene alla produzione del codice di questo
tipo. Tipicamente, lo sviluppatore Java passa la mag-
gior parte del proprio tempo sulla prospettiva chia-
mata genericamente proprio Java. la prospettiva
predefinita per i progetti Java, pu essere attivata
(qualora fosse stata cambiata) dal menu Window
Open Perspective Java. La medesima operazione
pu essere compiuta anche con alcuni bottoni pre-
senti solitamente nellangolo in alto a destra, nella
finestra principale del programma.
Ogni prospettiva formata da una serie di viste
(view), ognuna delle quali , di fatto, un componen-
te indipendente. La prospettiva predefinita per Java,
normalmente, comprende unarea di editing centra-
le contornata da una collezione di viste quali il
Package Explorer, la Console, lOutline ed altre anco-
ra. Ciascuna di queste viste pu essere trascinata
lungo lo schermo e venire riposizionata o ridimen-
sionata. possibile chiudere una vista, eliminando-
la cos dalla prospettiva, oppure possibile aggiun-
gere altri componenti, scelti fra quelli disponibili,
agendo con la voce di menu Window Show View.
Adesso facile immaginare quale grado di persona-
lizzazione possa raggiungere lambiente.
REALIZZAZIONE
DEI SORGENTI
Torniamo allargomento principale della ricetta,
cio alla realizzazione di un progetto Java. Per ora
disponiamo del progetto Ciao Mondo, vuoto. Il
miglior componente che lo sviluppatore Java pu
utilizzare per organizzare i contenuti del proprio
progetto, il Package Explorer che per default viene
posizionato a sinistra.
Questa vista permette di organizzare i sorgenti e le
risorse che sono dentro al progetto. Di base simile
ad un file system manager, in quanto visualizza i file
che sono nel progetto, ma fornisce alcune agevola-
zioni pensate appositamente per lo sviluppatore
Java.
I package, ad esempio, non vengono mostrati come
delle semplici cartelle, nidificate luna dentro laltra:
questo aspetto viene mascherato, e ciascun pac-
chetto mostrato come un elemento a s stante.
Provare per credere. Selezionate la cartella 7 del pro-
getto, aprite il men contestuale (quello che nella
maggior parte dei sistemi il men da tasto destro)
e scegliete New Package.
Nel wizard di creazione del nuovo pacchetto sceglia-
mo il nome it.ioprogrammo.test.
Il nuovo pacchetto, inserito nella cartella src, sar
presentato come un elemento unico, e non come tre
Fig. 3: Per cambiare prospettiva disponibile
lapposito menu Window Open Perspective.
Fig. 4: Creazione di un nuovo pacchetto con il Package
Explorer.
Fig. 5: Il wizard di creazione di un nuovo package Java.
NOTA
CARTELLA BIN
A ogni cartella di sorgenti
presente in un progetto
Java di Eclipse corrisponde
una cartella di eseguibili.
Normalmente alla cartella
di sorgenti predefinita src
abbinata la cartella di
compilati bin. In pratica, i
file .class compilati
automaticamente
dallambiente, vengono
conservati in questo
percorso. Il Package
Explorer di Eclipse tiene
nascoste le cartella con i
compilati, ma possibile
localizzarla con il file
manager del proprio
sistema operativo o con la
vista di Eclipse chiamata
Navigator.
022-024:088-093-corsi-xsl 16-07-2008 9:10 Pagina 23
SOFTWARE M Impariamo a utilizzare il framework Eclipse
ht t p: / / www. i opr ogr ammo. i t
G
24
/Settembre 2008
cartelle nidificate.
Molto comodo! Adesso selezionate il package appe-
na creato e, sempre con il menu contestuale, andate
a scegliere la voce New Class.
Il wizard di creazione di una nuova classe Java com-
prende numerose facilitazioni. Agendo con i
comandi dellinterfaccia possibile scegliere i modi-
ficatori della classe (public, private ecc.), eventuali
superclassi estese ed interfacce implementate, e
molte altre cose. Ad esempio si pu lasciare allam-
biente il compito di generare lo scheletro dei meto-
di astratti che la classe deve implementare. Tutto ci
fa risparmiare tempo allo sviluppatore. Utilizzando
il wizard creiamo la classe pubblica CiaoMondo, nel
pacchetto it.ioprogram mo.test, e dotiamola del
metodo main() con lapposita opzione.
Agiamo ora sul codice generato dallambiente, in
modo che corrisponda al seguente:
package it.ioprogrammo.test;
public class CiaoMondo {
public static void main(String[] args) {
System.out.println("CIAO
MONDO!");
}
}
Non dimenticate di salvare le modifiche apportate al
sorgente.
ESEGUIRE UNA CLASSE
Prima di eseguire un software Java sempre neces-
sario compilarlo. Eclipse provvede automaticamen-
te alla compilazione dei sorgenti, nel momento stes-
so in cui vengono salvati, in modo tale che non sia
necessario compilare esplicitamente prima di ogni
lancio. Lambiente, quindi, nasconde il passaggio da
sorgente a bytecode. Per lanciare lesecuzione di una
classe necessario, per regola Java, che questa con-
tenga un metodo public static void main(String[]).
La classe it.ioprogrammo.test.CiaoMondo contiene
uno di questi punti di avvio, quindi possibile utiliz-
zarla allo scopo. Selezioniamola dal Package
Explorer, quindi agiamo con il menu Run Run As
Java Application, oppure selezionando lopzione
corrispondente che si ha dalla freccia a fianco del
bottone tipo tasto play (Fig. 9).
Il programma, a questo punto, verr eseguito inter-
namente a Eclipse. Loutput prodotto viene mostra-
to nella speciale vista chiamata Console, solitamen-
te posizionata nella parte bassa dellambiente.
NELLA PROSSIMA
RICETTA
La prossima ricetta insegner come inserire delle
librerie in un progetto Java e come esportarne le
proprie creazioni, in modo da poterle distribuire a
terzi.
Carlo Pelliccia
Fig. 6: Creazione di una nuova classe con il Package
Explorer.
Fig. 7: Il wizard di creazione di una nuova classe Java.
Fig. 8: Il codice della classe CiaoMondo allinterno del-
leditor.
Fig. 9: Run As Java Application permette di esegui-
re una classe contenente un metodo main() valido.
Fig. 10: Loutput prodotto dalla classe CiaoMondo,
come mostrato dalla vista denominata Console.
NOTA
DISATTIVARE
LA COMPILAZIONE
AUTOMATICA
La compilazione
automatica dei sorgenti ,
nella maggior parte dei
casi, utile e proficua. Pu
per capitare che si
preferisca disattivarla, in
modo che il progetto venga
compilato solo su esplicita
richiesta. possibile farlo
deselezionando lopzione di
menu Project Build
Automatically. Per
compilare, a questo punto,
bisogner richiamare la
voce Project Build
Project. Con lopzione
Project Clean, invece,
possibile cancellare gli
eseguibili generati da una
compilazione precedente,
automatica o manuale che
sia, in modo da ripulire
eventuale sporcizia
accumulata sul file system.
NOTA
SCORCIATOIE UTILI
G CTRL + S
Salva il file corrente.
G ALT + INVIO
Apre la finestra delle
propriet dellelemento
corrente.
G CTRL + M
Espande o normalizza le
dimensioni della vista
selezionata.
G CTRL + SHIFT + R
Mostra la finestra di ricerca
risorse, grazie alla quale
possibile cercare molto
velocemente dei sorgenti o
delle risorse presenti
allinterno di un progetto.
022-024:088-093-corsi-xsl 16-07-2008 9:10 Pagina 24
J CD J WEB
drupal.zip
cdrom.ioprogrammo.it
ht t p: / / www. i opr ogr ammo. i t
ioProgrammo Web
M
G
26
/Settembre 2008
Un plug-in per implementare una galleria fotografica
C
creare un portale da zero diventa-
to semplice grazie ai software di tipo
CMS (Content Management System).
Il primo stato PhpNuke, poi PostNuke e ora
la ne esistono per tutti i linguaggi di program-
mazione. Alcuni di essi sono basilari, altri sono
avanzati, modulari ed espandibili ed altri
ancora, quelli pi complessi per intenderci,
sono considerati CMF (Content Management
Framework). Tra questi ultimi, quelli che
vanno per la maggiore nel mondo LAMP
(Linux Apache Mysql PHP) sono Joomla e
Drupal.
Abbiamo scelto Drupal con lintenzione di
mostrare come sia semplice aumentarne le
potenzialit, creando dei moduli da inserire
all'interno del core, cos da permetterci di rea-
lizzare quello di cui abbiamo bisogno. In que-
sto articolo partiremo, dunque, dalla base
della modularit di Drupal, facendo la nostra
conoscenza con gli Hook.
BASI PER LA STESURA
DI UN MODULO
La prima cosa da fare per scrivere il nostro
modulo, da ora in poi mymod, quello di crea-
re una directory all'interno del path dedicato
ai moduli che non fanno parte del core di
Drupal (/modules): sites/all/modules. Il nome
di questa directory dovr essere lo stesso scel-
to per il modulo, quindi mymod, al suo interno
dovranno essere creati i due file che rappre-
sentano la base del nostro modulo. Anche in
questo caso questi file dovranno avere come
nome quello del modulo, ma uno avr esten-
sione .info, l'altro estensione .module.
Il primo, mymod.info, serve a Drupal per
mostrarci le informazioni sul modulo al
momento della sua installazione all'interno
della sezione di admin, mentre il secondo,,
mymod.module, il modulo vero e proprio.
A questi due file possibile aggiungerne un
terzo, non sempre richiesto, che avr come
nome sempre quello del modulo, e come
estensione .install. Scopo di questo file quel-
lo di definire le operazioni SQL necessarie alla
corretta installazione del nostro modulo all'in-
terno del sistema, il che si traduce di solito
nella creazione della tabella o delle tabelle
dedicate al modulo stesso. Se vi state chieden-
do il perch di questa divisione, la risposta
molto semplice: nella versione 4 di Drupal, la
divisione tra .info e .module non esisteva, e
quello che ora nel .info era contenuto all'in-
terno di una funzione del modulo. Si era nota-
to, per, che questa scelta si ripercuoteva sulle
performance del sito perch tutto il file del
modulo, e tutti i file che venivano inclusi tra-
mite include e/o require, erano parsati dall'in-
terprete PHP solamente per riuscire ad avere
indietro quei pochi dati che ora sono contenu-
ti nel file con estensione .info.
CARATTERISTICHE
DEL .INFO
Il contenuto del file mymod.info molto sem-
plice:
; $Id$
name = MyMod;
description = Il mio primo modulo
version = "0.1x"
package = IoProgrammo Ed Master
dependencies = thickbox
La prima riga sempre ;$Id$ ed avrebbe un
significato soltanto se usassimo il cvs, l'svn o
altro sistema analogo. La seconda (name)
dichiara il nome del modulo in linguaggio
umano, e sar usato all'interno della sezione
di amministrazione di Drupal. Da non confon-
dere con il nome del modulo che abbiamo
scelto (mymod) all'inizio dell'articolo, e che ci
porteremo dietro per tutta la sua durata. La
CREARE UN NUOVO
MODULO PER DRUPAL
UNA DELLA POTENZIALIT DEI NUOVI CMS QUELLA DI POTERNE AUMENTARE LE FUNZIONA-
LIT ATTRAVERSO LA CREAZIONE DI MODULI DEDICATI A COMPITI PARTICOLARI, FACILMENTE
GESTIBILI E INTEGRABILI ALL'INTERNO DEL CORE DELLAPPLICAZIONE
Conoscenze richieste
Programmazione di
base PHP, installazione
e gestione del CMS
Drupal
Software
Drupal
Impegno
Tempo di realizzazione
REQUISITI
026-029:032-035 22-07-2008 15:24 Pagina 26
ht t p: / / www. i opr ogr ammo. i t
terza riga corrisponde alla descrizione del
modulo, sempre in linguaggio a noi compren-
sibile; la quarta alla versione del modulo e la
quinta permette di raggruppare i moduli,
all'interno di una stessa area, vedi Fig. 1.
Vi poi la sesta riga dependencies, il cui
scopo quello di definire quali sono i moduli
necessari per il funzionamento di quello che
andremo a creare. Questi devono essere gi
attivi all'interno del sistema prima di tentare
l'installazione del nostro modulo; in Fig. 1 si
pu notare come il mymod non sia seleziona-
bile essendo Thickbox non installato (la scritta
missing in rosso autoesplicativa). Come si
notato, essendo questi dei prerequisiti, la
mancanza (o la non attivazione) anche di uno
solo render impossibile l'installazione del
nostro nuovo modulo. In questo modulo la
richiesta di Thickbox solo una questione di
spiegazione, che noi trasformeremo in bellez-
za visiva del risultato finale. Quindi installia-
molo ed attiviamolo prima di tentare di attiva-
re il nostro modulo.
COSA VOGLIAMO
REALIZZARE
Siamo pronti alla scrittura del nostro modulo
ma, a ben vedere, ancora non abbiamo deciso
lo scopo: iniziamo dalle basi e definiamo i vari
elementi:
G tutti possono utilizzare il nostro modulo
G tutto quello di cui abbiamo bisogno gi
presente all'interno di una directory del
nostro sito web.
Ok, ma allora cosa deve fare il nostro modulo?
Una cosa molto semplice: mostrare a video,
leggasi passare al browser, il codice HTML
necessario alla visualizzazione di tutte le
immagini contenute in una particolare direc-
tory. Utilizzeremo il plugin Thickbox di Jquery
(la libreria AJAX usata da Drupal) per dare quel
tocco di originalit al nostro output.
Attenzione a non confondere il plugin
Thickbox di Ajax con il modulo Thickbox di
Drupal: quest'ultimo ci permette di usare il
primo all'interno del nostro portale, ma non
ha niente a che fare con Ajax. Prima di proce-
dere, controlliamo di aver creato la directory
madre delle nostre gallerie (la chiameremo
galleria/), una sotto directory per il nostro
esempio (la chiameremo galleria1/) e, all'in-
terno di quest'ultima, due directory: mini/ che
conterr le thumbnail delle nostre immagini e
tb/ che conterr le immagini in dimensione
reale. Ovviamente, questa una struttura
semplicistica, non ottimizzata; il codice pro-
posto, come vedrete, salta alcuni dei controlli
basilari, focalizzando lattenzione solo su
quanto di nosto reale interesse.
Ricapitolando, la struttura delle nostre cartel-
le sar cos formata:
/ {la root di drupal}
gallery/
galleria1/
mini/
tb/
INIZIAMO A SCRIVERE
IL CODICE
Ora che abbiamo definito cosa vogliamo fare,
e abbiamo definito la base su cui lavorare, ini-
ziamo a scrivere il codice del nostro modulo.
Partiamo indicando al core di Drupal di pre-
stare attenzione anche al nostro modulo, vigi-
lando quando l'utente cerca di accedere a un
determinato path:
function mymod_menu($may_cache)
{
$items = array();
if ($may_cache)
{
$items[] = array
(
'path' => 'galleri,
'title' => 'Directory galleri,
'description' => 'Le nostre gallerie',
'callback' => 'mymod_main',
//'callback arguments' => array(''),
'access' => TRUE,
'type' => MENU_CALLBACK
);
}
return $items;
}
Analizziamo il codice, partendo dalla defini-
zione della funzione: la prima parte del nome
mymod, esattamente uguale al nostro
M
ioProgrammo Web
Settembre 2008/
27
G
Un plug-in per implementare una galleria fotografica
NOTA
RISORSE WEB
Ecco alcune risorse che
sicuramente vi saranno
utili:
Drupal.org
(http://www.drupal.org):
il quartier generale di
Drupal.
Drupal.it
(http://www.drupal.it):
la comunit italiana
dedicata a Drupal. Se non
siete anglofoni o se
comunque cercate aiuto in
Italia quello che fa per
voi.
ZioBuddalabs.it
(http://www.ziobuddalab
s.it): se state cercando una
azienda che possa
realizzare i vostri progetti
usando Drupal come base,
avete trovato le persone
giuste.
Fig. 1: Il nostro modulo all'interno della sezione
apposita
026-029:032-035 16-07-2008 9:19 Pagina 27
ht t p: / / www. i opr ogr ammo. i t
modulo, mentre la seconda _menu($may_
cache). Se provate ad aprire altri file .module
noterete che tutti contengono una funzione
simile, dove quello che cambia il solo nome
del modulo.
Questo perch Drupal, per conoscere chi
gestisce un certo path (galleria/) opera un
ciclo sui moduli installati e attivati, richia-
mando da questi tutte le funzioni che vengo-
no formate, quindi unendo il nome fisico del
modulo (mymod) e la stringa _menu(), quello
che in gergo viene definito come hook.
Per capirci, se dovessimo eseguire delle istru-
zioni ogni volta che viene eseguito il cron, ci
basterebbe definire una funzione interna al
nostro modulo chiamata mymod_ cron() e
,automaticamente, il core la richiamerebbe
allo scoccare di ogni ora (oppure ogniqualvol-
ta si deciso di impostare il tempo di cron).
Esistono anche hook per le operazioni sugli
utenti (mymod_user), quelli sui nodi (mymod_
no deapi) e, ancora, quelli per i form (mymod
_form_alter).Per una lista esaustiva vi riman-
diamo alla seguente URL:
http://api.drupal.org/api/group/hooks/5
Ritorniamo alla nostra funzione. Il parametro
$may_ cache consente a Drupal di memoriz-
zare il contenuto della funzione e, nel con-
tempo, gestire gli elementi che devono essere
modificati a runtime; un esempio potrebbe
essere un modulo sulle quotazioni di borsa, in
cui il titolo non dovrebbe essere Quotazioni
di oggi, ma Quotazioni del 23 Agosto 2008
alle 10.30.
Siamo cos giunti alla creazione del singolo
elemento ($items[]), formato dai campi:
G path: rappresenta la base del percorso che
viene gestito dal modulo. In questo modo il
core di Drupal sempre a conoscenza di
qual il modulo delegato alla gestione di una
pagina web, nonch di tutte le sue sottopagi-
ne.
G title: il titolo dell'elemento. Questo campo
necessario perch, di default, Drupal asso-
cia ogni elemento a un link inserito all'inter-
no di un menu che viene presentato all'uten-
te (sempre che l'utente abbia i permessi per
visualizzarlo). Quale sia questo menu dipen-
de dal path: pi il path articolato, maggiore
sar il sottolivello del menu che verr linka-
to, sempre che ci siano altri $items che defi-
niscono dei path di livello superiore.
G description: la descrizione dell'elemento e,
come per title, utile quando ci si trova
all'interno di un menu.
G callback: rappresenta il cuore dell'elemen-
to, il suo contenuto la funzione da richia-
mare quando viene invocata una pagina
web corrispondente a questo elemento.
G callback_arguments: alla funzione definita
tramite callback possibile passare dei para-
metri oltre a quello che viene fornito dal core
(vedrete tra poco cosa intendiamo).
Tale parametro utile quando vogliamo far
gestire alla stessa funzione due URL diverse,
diversificando il comportamento della fun-
zione a seconda dell'URL richiesta; gli ele-
menti di questo parametro devono essere
racchiusi all'interno di un array() e verranno
passati alla funzione di callback come primi
argomenti.
G access: permette di gestire gli accessi alla
pagina da parte dell'utente collegato, basan-
do questo controllo sui permessi dell'utente
stesso. Nel nostro modulo, non avendo parti-
colari restrizioni da considerare, settiamo il
parametro direttamente a 7, mentre, in caso
contrario, avremmo dovuto utilizzare la fun-
zione user_access(). La descrizione del fun-
zionamento di questa routine esula dallo
scopo di questo articolo.
G type: come detto per i parametri title e
description, Drupal lega questo elemento
all'interno di un menu che viene visualizzato
dall'utente. Tuttavia esistono vari tipi di
menu, ed esiste anche la possibilit che non
ci debba essere nessun tipo di collegamento.
Nel nostro esempio con MENU_CALLBACK,
abbiamo indicato a Drupal che la nostra
scelta quella di non legare l'elemento a un
menu in particolare.
Prima di continuare, cerchiamo di comprende-
re meglio la funzione del campo path, perch
questo rappresenta una delle componenti
principali di tutto il modulo.
Il funzionamento di Drupal, quando cerca qual
il responsabile di una certa URL, il
seguente: preso il path nella sua interezza e
diviso in pezzi pi piccoli tramite il divisore /
(slash) controlla se qualche modulo lo gestisce
per intero: in caso di risposta affermativa viene
chiamata la callback associata a tale path, pas-
sando NULL come argomento. In caso di rispo-
sta negativa, viene tolto l'ultimo pezzo e
riformulata quest'ultima domanda. Tutto que-
sto termina quando la risposta diventa positi-
va: c' un elemento che riesce a gestire l'URL, e
alla callback associata vengono passati tanti
parametri quanti sono i pezzi che sono stati
ioProgrammo Web
M
G
28
/Settembre 2008
Un plug-in per implementare una galleria fotografica
NOTA
INSTALLIAMO
SEMPRE DEVEL
Quando si inizia a
programmare per Drupal
sempre consigliabile
installare ed attivare il
modulo devel che
permette tra le altre cose
di cancellare tutta la
cache, di vedere cosa
registrato nella nostra
sessione, ma soprattutto ci
consente di vedere il
contenuto del nodo che
abbiamo appena caricato.
Inoltre quando sviluppate
togliete la cache
dall'hook_menu()
inserendo la dicitura ||
1==1 prima della ) di
chiusura dell'if.
026-029:032-035 16-07-2008 9:19 Pagina 28
ht t p: / / www. i opr ogr ammo. i t
tolti, in cui il valore di ogni parametro il
pezzo che stato eliminato. Nel nostro caso,
mymod gestisce, ad esempio, l'URL galleria
(nessun parametro passato), galleria/kde
(dovremo poter gestire un parametro di fun-
zione) e galleria/kde/4 (dovrebbe poter gestire
due parametri di funzione).In modo analogo,
ma molto pi semplicemente, vengono pre-
sentati all'utente i vari menu: si raggruppano
tutti i path definiti negli $items[] , e li si mette
in ordine alfabetico ascendente; poi, per ogni /
contenuto nel path, l'elemento viene indenta-
to. Questa indentazione legata anche alla
necessit che ci sia un elemento che gestisca
lelemento padre. Ad esempio, galleria/ e
sistema/ saranno mostrati allo stesso livello,
mentre aggiungendo, dopo sistema/, galle-
ria/kde/ questo verr posto dal motore di tem-
plate sotto galleria/ (mostrato in modo che si
noti che un sottolivello e magari rendendolo
nascondibile),ma prima di sistema.
LA FUNZIONE
DI CALLBACK
Non ci resta che vedere come implementata la
funzione di callback dell'elemento definito
allinterno di hook_ menu():
function mymod_main($galleria = NULL) {
$tmpl = '<ahref="/galleria/'.$galleria.'/tb/%
FILE%" class="thickbox"><img
src="/galleria/'.$galleria.'/mini/%FILE%"></a>';
$handle =
opendir("/var/www/iop/galleria/".$galleria."/mini");
$output = '<div class="zbimg">
<h1>'.$galleria.'</h1><br>
';
if ($handle)
{
$files = array();
while (false!==($dir=readdir($handle)))
{
if ($dir!='.'&&$dir!='..' &&
!strpos($dir,"_resize"))
{
array_push($files,$dir);
}
}
closedir($handle);
sort($files);
foreach($files as $file)
{
$output .=
str_replace('%FILE%',$file,$tmpl);
}
$output .= "</div>";
}
else
{
$output = "Non esiste quella galleria";
}
return $output;
}
Questa funzione molto semplice, e non essen-
do questo un corso sul PHP, analizzeremo sola-
mente il funzionamento della stessa.
Lo scopo quello di prendere il nome di tutte le
immagini contenute all'interno della directory
mini/ di una directory definita dal parametro
$galleria e, dopo averle ordionate, creare un
HTML basato su un template costruito alluopo,
Il codice da noi sviluppato tiene conto della scel-
ta di utilizzare il plugin Thickbox di Jquery: all'u-
tente viene mostrata una versione in miniatura
dell'immagine reale, quando egli cliccher sulla
thumbnail, la stessa sar ingrandita; il plugin
Thickbox entrer in funzione, mostrando l'imm
agine vera senza la necessit di cambiare la pagi-
na. Il codice dellultima riga:
return $output;
il tipico costrutto che si trova all'interno delle
funzioni di callback definite dai vari hook_
menu(); il contenuto di $output deve essere
l'HTML che il browser dell'utente dovr oppor-
tunamente gestire. el nostro caso, $output con-
terr l'HTML delle immagini della galleria che
vogliamo visualizzare.
Michel Zio Budda Morelli
M
ioProgrammo Web
Settembre 2008/
29
G
Un plug-in per implementare una galleria fotografica
Fig. 2: Unanteprima di come apparir la galleria di immagini
che abbiamo imparato a creare leggendo questo articolo
026-029:032-035 16-07-2008 9:19 Pagina 29
J CD J WEB
zend.zip
cdrom.ioprogrammo.it
ht t p: / / www. i opr ogr ammo. i t
ioProgrammo Web
M
G
30
/Settembre 2008
Ambienti per lo sviluppo di Web Application in PHP
T
ra i fattori che rendono PHP ancora appe-
tibile come linguaggio di programmazio-
ne per applicazioni Web, a distanza di
oltre dieci anni dal suo primo rilascio, la sua
capacit di disporre di una serie pressoch infi-
nita sia di estensioni, sia di applicazioni riusabi-
li Open Source. In particolare, lintroduzione di
un nuovo motore ad oggetti con la versione 5, ha
iniettato nuova linfa al progetto, permettendogli
di accedere ad unarea molto interessante della
programmazione: quella dei framework ad
oggetti. Ovviamente, nel caso del PHP, quelli di
interesse sono i Web Application Framework,
ovvero finalizzati allo sviluppo di Web Services e
Web Applications.
Alla base dellutilizzo di un framework vi un
semplice concetto: risparmiare tempo nella ste-
sura di codice che svolge compiti eguali o simili
a quello gi sviluppato da altri, evitando cos di
reinventare ogni volta soluzioni a problemi gi
noti. Un classico campo di applicazione di tale
filosofia si trova nelle interfacce grafiche, dove
tale approccio divenuto, col tempo, sempre pi
applicabile in quanto gli elementi di interazione
con lutente appartengono ad un ben identifica-
to insieme. Dal punto di vista della programma-
zione, un framework prevede un approccio full
object oriented, nel senso che una applicazione
(o parte di essa, come una GUI) possono essere
viste come delle specializzazioni di una applica-
zione pi generica, dalla quale ereditano una
serie di funzioni e propriet, alcune delle quali
dovranno essere specializzate, altre potranno
essere lasciate come sono. Pertanto si applicano
i vari concetti del paradigma OO non tanto a sin-
goli elementi (come le classi) quanto ad un insie-
me coordinato costituente una intera applica-
zione.
Ad oggi, PHP dispone di diversi framework, pi o
meno noti. In questo articolo e nei successivi
che seguiranno, verr esaminato uno di quelli
pi noti in assoluto: Zend Framework. In parti-
colare, in questo primo articolo, prima di adden-
trarci nel costruire una applicazione di esempio,
andremo a vedere come si installa e quali sono
gli elementi cardine del framework in questione,
facendo riferimento allultima versione disponi-
bile mentre scriviamo: la 1.5.2.
PREREQUISITI
DI INSTALLAZIONE
Prima di addentrarci nellinstallazione, bene
rilevare una caratteristica cardine del nostro fra-
mework: la strutturata interna a componenti.
Come da manuale, ogni componente offrir un
servizio ben identificato, non legato ad un con-
testo specifico e riusabile; inoltre pu essere
usato a prescindere dalla presenza di altri com-
ponenti, e disporr di una interfaccia ben defini-
ta con lesterno grazie allutilizzo dei metodi
pubblici. Nella versione 1.5.2, troviamo ben 39
componenti, che vanno dalla gestione di Access
Control List (ACL) alla creazione di server e/o
client per XML-RPC.
In generale, un framework costituito da una o
pi librerie, che devono essere agganciate alla
nostra applicazione. Zend Framework non fa
eccezione, dove la libreria che deve essere instal-
lata non prevede dei file binari, ma una libreria
full php.
Dato che tale architettura sfrutta pesantemente
il motore PHP dovremo verificare, a seconda dei
componenti che intendiamo utilizzare, che nel
motore siano disponibili una serie di estensioni
a loro volta necessarie per costruire corretta-
mente il componente e quindi indispensabili
per attivare correttamente i servizi offerti. Ad
esempio: il componente Zend_Db, che fornisce
dei servizi di interfaccia verso database con
accesso tramite SQL standard, a seconda della
base dati a cui vogliamo realmente agganciarci,
a sua volta necessita della presenza delle esten-
sioni PHP che permettono la comunicazione col
database specifico. Per cui, avendo un database
di tipo MySQL dovremo curare che il motore
PHP abbia attiva lestensione mysqli. Inoltre il
PRIMI PASSI CON
ZEND FRAMEWORK
ESAMINIAMO IN DETTAGLIO LA STRUTTURA DEL PI NOTO AMBIENTE PER WEB APPLICATION
PHP. GETTEREMO LE BASI PER PROGETTARE UNAPPLICAZIONE BASATA SUL PARADIGMA MODEL
VIEW CONTROLLER
Conoscenze richieste
Buona conoscenza di
PHP e dei PATTERN
Software
PHP, APACHE
Impegno
Tempo di realizzazione
REQUISITI
030-033:032-035 16-07-2008 9:21 Pagina 30
ht t p: / / www. i opr ogr ammo. i t
motore stesso deve essere almeno aggiornato
alla versione 5.1.4 o successiva (in particolare si
consiglia la 5.2.3 o successiva, in quanto da
quella versione vengono introdotti una serie di
miglioramenti di performance e sicurezza).
La lista completa delle estensioni necessarie ad i
vari componenti indicata alla URL http://frame -
work.zend.com/manual/en/requirements.extensions.ht
ml e non viene qui replicata per brevit.
Chiaramente, se le estensioni necessarie ad un
componente non sono presenti, quel compo-
nente non potr essere usato (ma ci non com-
promette lutilizzabilit di altri componenti con
requisiti diversi).
INSTALLAZIONE
E PRIMI PASSI
CON ZEND FRAMEWORK
Per come strutturato, linstallazione della
libreria contenente i vari componenti del fra-
mework risulta particolarmente banale come
si vede nellapposito riquadro. Per riferimento,
indicheremo la directory dove stato decom-
presso il file della libreria con $ZEND_HOME.
Costruiamo rapidamente un primo, banalissi-
mo, test per verificare che linstallazione sia
andata a buon fine, richiedendo di stampare a
video il numero della versione. Vi infatti un
componente, chiamato Zend_Version, che mette
a disposizione una costante VERSIONcontenen-
te il numero di versione e il metodo compare
Version($versione) che permette di valutare la
versione corrente rispetto a una di riferimento,
passata al metodo (che ritorna 0 in caso la ver-
sione corrente sia la stessa indicata, numeri
positivi se la versione corrente pi aggiornata
o numeri negativi in caso la versione corrente sia
meno aggiornata). Luso di tale componente
permette, costruendo applicazioni ridistribuibi-
li, di verificare che sul server vi sia una versione
compatibile con quanto richiesto dal nostro
codice.
Il file, che chiameremo zf_test_base.php ed inseri-
remo in una directory visibile via web sar sem-
plicemente:
<?php
require_once "Zend/Version.php";
print "Versione di ZF installata: " .
Zend_Version::VERSION;
?>
Chiaramente loutput sar una scritta nel brow-
ser del tipo: Versione di ZF installata: 1.5.2
Da questo semplicissimo esempio si possono
notare immediatamente due elementi cardine
della programmazione col Zend Framework:
prima di poter utilizzare un componente
dovremo caricare la parte della libreria che lo
contiene tramite una chiamata require_once
e, una volta caricato il componente, per poter-
lo usare correttamente, dovremo usare il suo
namespace completo. In particolare, per il
caricamento del componente, se andiamo ad
esaminare il contenuto della sottodirectory
Zend di $ZEND_ HOME, troveremo una
serie di file PHP che costituiscono la porta di
accesso ad i vari componenti.
Ricordarsi di includere il corretto file PHP per
usare un dato componente senza ombra di
dubbio un qualcosa che vorremmo evitare, dato
che sicuramente una attivit soggetta ad erro-
ri e dimenticanze. Per questo motivo possibile
sfruttare un componente, chiamato Zend_Load,
che permette in generale di includere file PHP
dal nome variabile (o che contengono una data
classe) e di gestire lautoloader dei file delle clas-
si messe a disposizione dal framework, regi-
strandosi come PHP SPL Autoloader per le clas-
si Zend_*. Usando tale componente, il file di test
diviene:
<?php
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
print "Versione di ZF installata: " .
Zend_Version::VERSION;
?>
Chiaramente, usando solo una classe non
possibile apprezzare lutilit dellutilizzo del-
lautoloader. Proviamo, quindi, a estendere il
test usando i servizi di data, messi a disposi-
zione dal componente Zend_Date. In partico-
lare chiediamo di stampare la data corrente,
formattata in base alle impostazioni della lin-
gua da noi scelte. Per far ci dovremo definire
un nuovo oggetto della classe Zend_Date e di
questo usare il metodo get, passandogli
come parametro una costante che specifica la
formattazione come sopra indicata. Lesempio
diviene quindi:
M
ioProgrammo Web
Settembre 2008/
31
G
Ambienti per lo sviluppo di Web Application in PHP
NOTA
LA NASCITA
DI ZEND
Zend, note come The PHP
Company lazienda
fondata da Andi Gutmans e
Zeev Suraski nel 1999 per
fornire servizi professionali
e prodotti utili per lo
sviluppo in PHP. Per
quanto sia una azienda
che commercializza anche
prodotti non Open Source,
mantiene sempre una
forte leadership per tutto
ci che riguarda il mondo
PHP, contribuendo
fortemente allo sviluppo
delle versioni aggiornate
del motore e supporta
progetti Open Source,
come il Zend Framework
ed il plugin di sviluppo
PHP per Eclipse (PDT).
Il pattern Front Controller
concepito appositamente per le
Web Application e prevede di
inviare le diverse, possibili
richieste, a prescindere della
visualizzazione effettiva da
effettuare, ad un unico gestore
delle viste, che a sua volta
composto da: 1) una sezione
comune alle diverse tipologie
di viste possibili 2) una o pi
sezioni che vengono caricate a
runtime (dette command
object) in base alle
caratteristiche peculiari della
vista specifica da gestire.
IL PATTERN FRONT CONTROLLER
030-033:032-035 16-07-2008 9:21 Pagina 31
ht t p: / / www. i opr ogr ammo. i t
<?php
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
// Utilizzo di due classi Zend_*
$date = new Zend_Date();
print "Versione di ZF installata: " .
Zend_Version::VERSION . " data corrente: " .
$date->get(Zend_Date::DATE_MEDIUM);
?>
Come si vede, non stato necessario specificare i
require_once delle due classi usate.
IL PARADIGMA MVC:
LO STATO DELLARTE
DELLE WEB APP
Lultima caratteristica che vogliamo esaminare di
Zend Framework come questo permetta di
costruire applicazioni basandosi sul paradigma
Model-View-Controller (MVC).
Dietro questo three-letter acronym vi lo stan-
dard di fatto nella costruzione delle moderne
Web Applications complesse, in cui si deve tene-
re presente che creare pagine in cui vi un misto
di codice e markup, nel caso di applicazioni
complesse, pu risultare poco gestibile se non
dallo sviluppatore originale, nonch, visto che la
costruzione dellinterfaccia utente oggi divenu-
ta unarte a se stante, spesso possono esservi nel
team degli esperti di creazione di interfacce, che
non conoscono bene come invece deve essere
gestita la logica di back end della stessa. Infine la
logica di funzionamento di una applicazione
deve dipendere esclusivamente dai dati e non da
come questi vengono presentati e/o inseriti dal-
lutente tramite linterfaccia.
Quanto appena detto, porta sia a separare il codi-
ce della business logic da quello della presenta-
tion logic della nostra applicazione, sia a separa-
re i ruoli nel team che si occupa di costruire tutta
lapplicazione.
Il paradigma MVC realizza tale separazione distin-
guendo tre elementi nella nostra applicazione (che
possono corrispondere a tre diverse professionalit
nel team): la parte di MODEL, che rappresenta le
funzionalit basilari della nostra applicazione (e.s.:
in genere laccesso ad i dati viene gestito da qui); la
parte di VIEW, che gestisce come viene effettuata la
presentazione dei dati allutente (nel caso di una
Web Application qui troviamo la sezione HTML) e
la parte di CONTROLLER, che rappresenta il lega-
me tra il MODEL ed il VIEW, dove viene deciso
come gestire la parte di presentazione (ovvero
quali parti del VIEW mandare effettivamente a
video) e quali funzioni del MODEL necessario
attivare.
Vediamo ora di iniziare a sviluppare la base di una
applicazione MVC con il nostro framework; come
inizio ovviamente creeremo un hello world e poi
nei prossimi articoli proseguiremo costruendo un
applicazione strutturata. Una applicazione svilup-
pata in base a questo paradigma con Zend, preve-
de di organizzare lalberatura delle directory con
una struttura che separi i tre elementi del pattern.
In particolare dobbiamo far riferimento alla strut-
tura di Fig. 1.
Limplementazione del paradigma MVC usata dalla
Zend usa un altro pattern di base che il Front
Controller, pertanto necessario fare in modo di
direzionare laccesso iniziale ad una pagina specifi-
ca che inizializzer il pattern, e quindi attiver le
sottosezioni specifiche a seconda della vista reale
da gestire. Su un sistema LAMP, supponendo di
aver definito un virtual server APACHE per
LOCALHOST che punta alla directory PUBLIC
della Fig. 2, questo passo coincide con la creazione,
nella directory PUBLIC 1) di un file .htaccess conte-
nente le seguenti righe di codice:
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
Che permette di direzionare tutte le richieste di
file che non abbiano le estensioni elencate verso
la pagina index.php. La pagina index.php, che
deve contenere un puntatore ad una pagina di
ingresso allinterno della sezione APPLICATION
della nostra alberatura, contenente la parte
comune alle viste, ovvero:
ioProgrammo Web
M
G
32
/Settembre 2008
Ambienti per lo sviluppo di Web Application in PHP
NOTA
PHP. LE ORIGINI
Un po di storia. Il PHP
nasce nel 1994 come una
collezione di script CGI per
la gestione della pagine
personali, ad opera di
Rasmus Lerdorf. A quel
tempo il prodotto si
chiamava infatti PHP/FI
(Form Interpeter). Dalla
versione 3, rilasciata nel
1998, nella quale il motore
venne riscritto in larga
parte da Andi Gutmans e
Zeev Suraski con un
approccio analogo a quello
usato da ASP, il nome
diviene semplicemente
PHP.
Fig. 1: Schema ad albero del progetto MVC
030-033:032-035 16-07-2008 9:21 Pagina 32
ht t p: / / www. i opr ogr ammo. i t
<?php
require '../application/app_comune.php'; ?>
A questo punto necessario costruire la nostra
pagina di base app_comune.php allinterno della
directory application. Questa dovr contenere,
dopo lattivazione dellautoloader, la chiamata al
pattern Front Controller (gestito dal framework
tramite un singleton per assicurare che vi sia una
singola istanza per request del browser) che a sua
volta si preoccupa di passare la palla ad un con-
troller.
<?php
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
// Gestione del singleton del front controller
$frontController =
Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
// Puntatore alla directory dei controller
$frontController-
>setControllerDirectory('../application/controllers');
// Attivazione del controller
$frontController->dispatch();
?>
Non avendo specificato un evento particolare da
gestire, il controller che verr attivato quello di
default, detto Index (che Zend si aspetta di tro-
vare nel file IndexController.php posto nella direc-
tory dei controllers, come indicato nel parametro
del metodo setControllerDirectory).
Sar proprio nel file controller che dovremo ini-
ziare ad inserire la classe di gestione contenente
il codice che attiva una particolare vista a secon-
da delle nostre necessit.
<?php
require_once 'Zend/Controller/Action.php';
class IndexController extends Zend_Controller_Action
{ public function indexAction() { } } ?>
In questo primo esempio supponiamo sempre
di voler attivare la vista di default (anchessa
chiamata Index), per cui la classe sar vuota.
Quello che manca ora per finire proprio la
vista, che (non avendo specificato nulla) dovr
trovarsi views/scripts/index/index.phtml (in cui
lestensione phtml usata come best practi-
ce da Zend per segnalare che il file non contie-
ne solo codice PHP, ma anche tag HTML). La
vista che andremo a costruire conterr final-
mente il nostro hello world.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Strict//EN"; "http://www.w3.org/TR/
xhtml1/DTD/xhtml1-strict.dtd>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8"/>
<title>Zend Framework Hello Word</title>
</head><body>
<h1 align="center"><?php echo 'HELLO WORLD
dalla mia prima applicazione Zend Framework MVC'
?></h1>
</body></html>
chiaro che un hello world non permette di
apprezzare a pieno la modularit che si intro-
duce col pattern MVC . Tuttavia con i prossimi
articoli potremo meglio valutarne la potenza
costruendo una applicazione pi complessa.
Guido Pennella
M
ioProgrammo Web
Settembre 2008/
33
G
Ambienti per lo sviluppo di Web Application in PHP
Acquisire il file e decomprimerlo
in una directory accessibile dal
motore PHP, che definiremo $ZEND_
HOME. Con wget il path : http://fra -
mework.zend.com/releases/ZendFrame
work-1.5.2/ZendFramework1.5.2.tar.gz
Editare il file PHP.INI per aggior-
nare la variabile include_path,
che contiene una lista di directory se-
parate da ;, inserendo il path com-
pleto della sottodirectory library che
si creata decomprimendo il file scari-
cato in $ZEND_HOME
Vediamo i passi necessari per installare Zend Framework nel nostro sistema
PASSI DI INSTALLAZIONE DEL SOFTWARE
Rendere operativa la modifica
al file PHP.INI a seconda del
tipo di architettura (es.: nel caso di
un sistema LAMP/WAMP con PHP
gestito come estensione di Apache,
riavviare lo stesso Apache)
1 2 3
LAUTORE
Guido Pennella un
ingegnere esperto di
informatica, laureato
allUniversit di Roma
La Sapienza. Si occupa
principalmente dello
sviluppo di sistemi sia via
Web, sia di applicazioni
embedded real time
distribuite. E possibile
contattarlo allindirizzo di
posta elettronica
guidopennella@virgilio.it
030-033:032-035 16-07-2008 9:21 Pagina 33
J CD J WEB
roundcube.zip
cdrom.ioprogrammo.it
ht t p: / / www. i opr ogr ammo. i t
ioProgrammo Web
M
G
34
/Settembre 2008
Script pronti alluso per il tuo sito web
T
utti coloro che, per lavoro o per diletto, svi-
luppano siti web e/o portali, prima o poi
hanno lesigenza di utilizzare un webmail
reader. Si tratta di interfacce per visualizzare e gesti-
re la posta elettronica collegandosi direttamente via
browser a un dato indirizzo Internet. Illustri esempi
sono i famosissimi Hotmail, Yahoo e il pi recente,
ma gi molto diffuso, Gmail di Google. Spesso, nel
pacchetto acquistato per registrare un proprio
dominio, viene fornito dello spazio web con caratte-
ristiche variabili delle offerte, che hanno quasi sem-
pre in comune la possibilit di creare e gestire via
browser le caselle di posta elettronica legate al
dominio stesso. Ancor pi spesso, in bundle, viene
fornita la possibilit di utilizzare la posta elettronica
anche via web, generalmente collegandosi ad un
indirizzo del tipo webmail.nomedominio.ext.
A volte, per, i programmi preinstallati dai fornitori
del servizio di hosting e/o mantainer non rispec-
chiano le esigenze dellutente, sia per quanto
riguarda laspetto grafico sia quello dellusabilit,
che, addirittura, gli aspetti legati allaggiornamento
alle ultime versioni disponibili. Un esempio su tutti
potrebbe essere Squirremail (www.squirrelmail. org):
storico e leggero webmail reader (spesso installato
di default quando si acquista uno spazio web), con
con diverse utilissime funzionalit, ma che come
aspetto grafico lascia sicuramente molto a desidera-
re. In questo articolo tratteremo dellinstallazione di
un webmail open source di nuova generazione, che
segue uno stile certamente molto Web 2.0, grafica-
mente accattivante, e dotato di funzioni avanzate
per la gestione della posta. Il webmail in questione
si chiama Roundcube Webmail Project, disponibi-
le allindirizzo Internet http://roundcube.net/ .
DUE PAROLE
SU ROUNDCUBE
Roundcube, abbiamo gi detto, un client e-mail
da utilizzare via browser. Supporta i server IMAP e
utilizza uno stile che pu ricordare un'applicazione
desktop. Include il supporto MIME, una comoda
rubrica, la gestione delle cartelle, la ricerca all'inter-
no dei messaggi e la correzione del testo. Tra l'altro,
l'aspetto di questo webmail facilmente persona-
lizzabile modificando i fogli di stile CSS, le imposta-
zioni avanzate permettono di intervenire su nume-
rosi parametri, come il server SMTP da utilizzare.
Inoltre, Roundcube dotato di un comodo editor
visuale per la composizione delle e-mail in formato
HTML. Questa caratteristica, per, non viene instal-
lata di default: necessario specificarla in fase di
installazione, vedremo pi avanti come e quando.
METTIAMO I FILE DI
ROUNDCUBE SUL SERVER
Roundcube disponibile in download dal sito origi-
nale (http://roundcube.net) o da sourceforge.net. Gli
sviluppatori mettono a disposizione dei pacchetti
preinstallati, pronti da utilizzare su alcune distribu-
zioni Linux, come Gentoo e Mandriva. Stranamente
manca il pacchetto precompilato .deb da utilizzare
sulla distribuzione Linux pi diffusa ad oggi:
Ubuntu. Noi, per mantenere la massima compatibi-
lit con la distro che ospiter il nostro Roundcube,
utilizzeremo il file con i sorgenti in formato TGZ.
Una versione disponibile anche nel CD-Rom di
questo mese, ma comunque preferibile scaricare
la release pi recente visitando la pagina web
http://roundcube.net/downloads. Una volta ottenuta il
file compresso da installare, si possono seguire due
vie diverse per lupload sul server: decomprimere il
pacchetto con un software come 7Zip, e uploadare i
file sul server utilizzando un qualsiasi client FTP (ad
esempio Filezilla, gratuito e reperibile allindirizzo
http://filezilla-project.org/) per trasferire sul server i
file appena decompressi. Avendo a disposizione un
server che lo permetta, invece, si potr utilizzare
SSH per scaricare direttamente su di esso il file com-
presso con linstallazione di Roundcube, per
decomprimerlo successivamente nelle cartelle di
destinazione. La prima cosa da fare, una volta
copiati tutti i file, sar quelle di impostare i giusti
permessi di scrittura per le cartelle temp e logs.
ROUNDCUBE.
LA POSTA IN PHP!
INSTALLIAMO E CONFIGURIAMO UN POTENTE SOFTWARE GRATUITO DI WEBMAIL.
CON ROUNDCUBE AVREMO UN SISTEMA CAPACE DI GESTIRE I MESSAGGI COS COME FANNO
I MOSTRI SACRI GMAIL, HOTMAIL E YAHOO!
Conoscenze richieste
Base di PHP, Linux,
utilizzo di client FTP o
SSH
Software
Linux, Web server
Apache, PHP, MySQL,
server di posta con
supporto IMAP
Impegno
Tempo di realizzazione
REQUISITI
034-036:032-035 16-07-2008 17:00 Pagina 34
ht t p: / / www. i opr ogr ammo. i t
Se si usa SSH baster digitare quanto segue nella
console:
chmod R 777 temp
chmod R 777 logs
Altrimenti, utilizzando un client FTP, la procedura
per impostare i permessi dipender dallapplicazio-
ne adoperata.
PREPARARE LA BASE
DATI PER ROUNDCUBE
Il passo successivo la creazione del database
MySQL, che servir a contenere le impostazioni di
Roundcube, oltre ai messaggi stessi. Sempre a
seconda delle caratteristiche installate sul server, si
potranno utilizzare svariati metodi per intervenire
sul server MySQL. Il pi comune phpMyadmin,
famoso tool in PHP, di solito installato di default dai
servizi di hosting che vendono lo spazio. Un meto-
do pi da desktop installare un programma
come MySQL-Front, che facile da utilizzare e,
soprattutto, gratuito. Il nome del DB indifferente,
non c bisogno di crearne uno in particolare. Il
nostro, ad esempio, si chiamer iop_roundcube
Ora siamo pronti per iniziare con linstallazione
vera e propria.
LINSTALLAZIONE
PASSO PASSO
Eseguiti tutti gli step citati finora, baster collegarsi
al browser predefinito di sistema e digitare
lindirizzo WEB di riferimento della nostra installa-
zione di Roundcube, aggiungendo il percorso
/installer. Ad esempio: http://mioserver.est/round
cube/installer. Nel dare il benvenuto nella procedura
di installazione, lo script avvisa che cliccando sul
pulsante START INSTALLATION verr effettuato
un controllo sul sistema per accertarsi che i requisi-
ti minimi per lutilizzo di Roudcube siano soddisfat-
ti.
importante prestare attenzione a che siano instal-
lati almeno i componenti marcati con required,
indispensabili per il funzionamento del webmail.
Se i requisiti minimi non saranno soddisfatti, la pro-
cedura si arrester impedendo linstallazione.
Se tutto ok, baster cliccare sul pulsante next per
avviare il processo.
Nella pagina proposta dopo il clic, si avr modo di
configurare alcuni parametri del sistema di web-
mail; possibile lasciare invariato il valore di molti
di questi, ci limiteremo, quindi, a indicare quelli che
necessariamente vanno configurati ex-novo,
sezione per sezione:
General configuration
G product_name: nome che verr adoperato come
titolo delle pagine di Roundcube
Database setup
G Database type: MySQL
G Database server: nome host del server mysql
G Database name: nome del database che abbiamo
precedentemente creato
G Database user name: lutente che usa il DB. Dovr
necessariamente avere i permessi di scrittura
G Database password: la password del suddetto
utente
IMAP Settings
G default_host: nome host del server che offre
laccesso IMAP
G username_domain: indicare il dominio da
aggiungere automaticamente in fase di login del-
lutente
SMTP Settings
G smtp_server: nome host del server che permet-
ter linvio della posta. Solitamente uguale a
quello del server IMAP.
G smtp_user/smtp_pass: spuntare il checkbox Use
the current IMAP username and password for
SMTP authentication
Display settings & user prefs
G locale_string: visto che siamo in Italia, bisogner
scrivere il valore it_IT nellapposito campo di
testo
G preview_pane: spuntare questo checkbox se si
desidera visualizzare il pannello di anteprima dei
messaggi
G htmleditor: checkbox da spuntare se si desidera
adoperare di default leditor WYSYWYG per com-
porre i messaggi
G draft_autosave: imposta il tempo per il salvatag-
gio automatico dei messaggi durante la scrittura
degli stessi.
comunque consigliabile dare almeno uno sguar-
do alle altre configurazioni che qui non abbiamo
menzionato, fosse anche soltanto per capire a cosa
servono. La lingua di default dellinstallazione
linglese, ma sicuramente di facile comprensione.
Dopo aver controllato accuratamente le imposta-
zioni che stiamo indicando allinstaller, si potr
cliccare sul pulsante CREATE CONFIG. La succes-
siva pagina proporr due grandi textarea, allinter-
no delle quali sar presente il codice dei due file di
configurazione necessari al funzionamento di
Roundcube. Bisogner copiare il codice presente
nelle due textarea e creare, rispettivamente, il file
main.inc.php (la prima textarea partendo dallalto)
e db.inc.php. Il primo file contiene i parametri di
M
ioProgrammo Web
Settembre 2008/
35
G
Script pronti alluso per il tuo sito web
NOTA
LERRORE
DECRYPT_PASSWO
RD()
Se nel terzo step
dellinstallazione si riceve
un errore relativo alla
funzione
decrypt_password, non
ci si preoccupi pi di tanto.
Il programma funziona
correttamente;
probabilmente si tratta
soltanto di un errore di
inclusione di un file.
NOTA
INSTALLAZIONE
SU IIS CON
HMAILSERVER
Se non si dispone di un
server Linux, per provare
linstallazione di
Roundcube, esistono
metodi alternativi che ne
permettono lutilizzo anche
sul server di Microsoft: IIS.
Collegatevi al seguente
indirizzo per visualizzare le
informazioni necessarie:
http://www.hmailserver.c
om/forum/viewtopic.php
?t=5591
034-036:032-035 16-07-2008 17:00 Pagina 35
ht t p: / / www. i opr ogr ammo. i t
sistema, il secondo si occupa di conservare le infor-
mazioni necessarie per la connessione al server
MySQL. Questi due file sono ampiamente commen-
tati al loro interno anche se in inglese. Il consiglio, al
solito, quello di dare unocchiata un po pi
approfondita, per vedere come funziona il tutto.
Dopo aver creato i file, quindi, bisogner spostarli
nella directory /config nella root di Roundcube.
Se si sta utilizzando un server Linux o Unix, consi-
gliamo di creare questi file con un editor che per-
metta di impostare il document type sul formato
Unix, per evitare spiacevoli incompatibilit di enco-
ding. Una volta uploadati i file sul server (attenzione,
se si utilizza FTP la modalit di trasferimento dovr
essere impostata su ASCII), cliccare ancora sul pul-
sante CONTINUE, subito sotto la seconda casella
di testo. Si acceder, quindi, allultima pagina di
configurazione, quella di test e controllo dei para-
metri. Primo passo, quello di inizializzazione del
database, ovvero la creazione delle tabelle che con-
terranno i dati di Roundcube. Cliccare su Inizialize
Database per avviare la creazione delle suddette
tabelle nel DB. Sar quindi buona norma testare il
corretto funzionamento del server di posta, nella
sezione Test SMTP settings. Indicare un mittente
(valido) e un destinatario, quindi cliccare su Send
test mail, e attendere larrivo della mail di prova
creata da Roundcube. Ultimo test da effettuare,
quello che riguarda la connessione al server IMAP.
Un clic su check login per effettuare il test. Se tutto
andato per il meglio, la fase di configurazione ter-
minata. Come da raccomandazione del programma
stesso necessario ora, per motivi di sicurezza, eli-
minare fisicamente tutta la directory /installer dal
server. Se non si ancora certi che tutto sia andato
bene, per, si potr soltanto rinominarla, magari per
effettuare ancora la configurazione in un secondo
momento. Ricordiamo comunque che nella pagina
di installazione, in alto a destra, sempre disponibi-
le un link al wiki dellHOW-TO ufficiale dinsta -
llazione.
MISSIONE COMPIUTA:
EFFETTUIAMO IL LOGIN
Siamo finalmente pronti a loggarci per la prima
volta sul nostro nuovo sistema di webmail.
Raggiungiamo con il nostro browser lindirizzo
web. Se durante linstallazione abbiamo indicato il
dominio di default del sistema, ci baster scrivere
soltanto il nome utente nel campo username e,
ovviamente, la password nellomonimo campo.
Lo scenario che si presenter davanti ai nostri
occhi sar una pagina divisa in tre pannelli. Sulla
sinistra sar visualizzato lelenco delle cartelle,
mentre i due pannelli di destra indicheranno,
rispettivamente e visti dallalto verso il basso,
lelenco dei messaggi presenti sul server e la loro
anteprima. Proviamo a scrivere un messaggio di
posta, giusto per essere sicuri che tutto funziona
come dovrebbe. Cliccando sullicona contrasse-
gnata da una piccola matita sar visualizzata
lapposita interfaccia.
Non c bisogno di descrivere i passi da compiere
per comporre e inviare una mail, linterfaccia offer-
ta da Roundcube molto semplice e intuitiva.
Da rimarcare che in basso a destra sempre pre-
sente un checkbox che consente di cambiare il tipo
di messaggio che si sta componendo, passando
agevolmente dal formato HTML a quello soltanto
testo. In alto, inviece, presente il checkbox per
richiedere al destinatario la conferma di lettura
delle-mail. Una nota per quanto riguarda gli alle-
gati: la dimensione accettata per un file in attach
alla mail dipende dalle configurazioni del server
web che ospita Roundcube. In caso di problemi,
consigliamo di dare uno sguardo approfondito al
file php.ini ed eventualmente modificare le variabi-
li: file_uploads, upload_max _filesize e anche
max_execution_time.
Diamo infine uno sguardo alla rubrica messa a
disposizione da Roundcube. Poco da osservare, in
realt. Si tratta di una comune rubrica con i soliti
campi da compilare per memorizzare i dati dei
contatti. Da notare, per, che la rubrica sar
memorizzata sul database di Roundcube, e non sul
server. Non sar quindi disponibile utilizzando altri
client che usano IMAP per la connessione.
CONCLUSIONI
Abbiamo visto quanto sia semplice installare e con-
figurare Roundcube su un server di posta che sup-
porti il protocollo IMAP. Per quando riguarda la per-
sonalizzazione dellinterfaccia, segnaliamo che sul
sito http://roundcubefo rum.net, sono disponibili molti
temi gi pronti da utilizzare, Buon divertimento,
allora, con il vostro nuovo webmail client!
Piero Mannelli
ioProgrammo Web
M
G
36
/Settembre 2008
Script pronti alluso per il tuo sito web
Fig. 1: La pagina per comporre un nuovo messaggio di posta in HTML.
NOTA
ALTERNATIVE
A ROUNDCUBE
Roundcube non ,
ovviamente, lunico client
web di posta Open Source
reperibili online e
gratuitamente. Segnaliamo
il leggero Squirrelmail
(http://www.squirrelmail.
org), il completo ma
complesso Horde
(http://orde.org), e
litalianassimo Overlook
(http://www.openit.it),
derivato da Squirrelmail
ma molto pi accattivante
e completo per
caratteristiche.
034-036:032-035 16-07-2008 17:00 Pagina 36
J CD J WEB
Paypal1Schema.zip
cdrom.ioprogrammo.it
ht t p: / / www. i opr ogr ammo. i t
M
ioProgrammo Web
Settembre 2008/
39
G
Integrazione di PayPal nei siti di e-commerce
Q
uando si progetta un sito di e-commerce,
importante decidere quale debba essere la
modalit di pagamento del carrello degli
acquisti. Lesercente che si appresta a fare una scelta
deve tener presente caratteristiche quali la facilit duso
del sistema di pagamento, la confidenza che il consu-
matore ha gi nei confronti del servizio che si andr a
implementare (al fine di abbattere le eventuali barriere
legate alluso dello strumento), la sua diffusione, non-
ch i costi sulle transazioni. Tutti questi elementi devo-
no essere valutate in maniera bidirezionale: utente-
esercente. Fondamentale , inoltre, considerare gli
aspetti inerenti la sicurezza: un acquirente senzaltro
restio a trasmettere on-line i dati della propria carta di
credito per trasferire denaro attraverso un sito che non
si avvalga di un sistema di prelievo certificato e assolu-
tamente affidabile. Nato come istituto di credito lus-
semburghese, con servizi limitati alla moneta elettro-
nica, ed in seguito acquisito da eBay nel 2002, Paypal
il sistema di pagamento on-line pi diffuso al
mondo, utilizzabile in ben 55 paesi. Funziona
molto similmente a un comune conto corrente
bancario elettronicom al quale ciascuno pu acce-
dere per inviare e ricevere denaro. PayPal, inoltre,
arricchito con funzionalit specifiche studiate per
il Web; lapertura di un conto PayPal possibile per
chiunque sia in possesso di un indirizzo e-mail.
Ci preoccuperemo di spiegare in maniera tecnica e
dettagliata, ma quanto pi semplicemente possi-
bile, il funzionamento di tale sistema. Ne spieghe-
remo larchitettura e i termini di interazione tra
acquirente, istituto bancario, Paypal ed esercente.
Andando nello specifico, poi, implementeremo il
codice per permette ai propri clienti di effettuare
un pagamento di tipo Standard direttamente dal
proprio sito,.
LE FUNZIONALIT
Il sistema di pagamenti on-line Paypal uno dei
metodi pi sicuri per ricevere ed inviare denaro
on-line perch tali operazioni vengono effettuate
unicamente fornendo l'indirizzo e-mail specifica-
to in fase di registrazione sul sito www.Paypal.it,
unico strumento necessario per ricevere dei paga-
menti praticamente da tutte le societ che fanno
parte del circuito. I tipi di conto possono essere tre:
il tipo Personal, il Premier e il Business. Il primo,
consigliato a chi intende effettuare solo dei paga-
menti mediante il conto dedicato, permette di ese-
guire ogni tipo di addebito tramite carta di credito
o saldo Paypal: limitato, per, per quanto riguar-
da la ricezione di fondi, che possono essere tra-
smessi soltanto da un altro conto Paypal e in
numero di massimo due allanno; dunque per un
utilizzo sporadico, non adatto alle aziende.
I pagamenti possono, invece, essere ricevuti senza
limitazioni da parte degli utenti Premier, per le cui
transazioni vengono trattenute delle commissioni
pari ad un fisso di 0,35pi il 3,4% della somma
ricevuta. Il Business un po pi completo e speci-
ficamente dedicato alle aziende che svolgono atti-
vit commerciali su Internet: i soldi che sono stati
accreditati nel conto Paypal possono essere trasfe-
riti in un conto corrente bancario di propriet del
sottoscrivente oppure verso carte di credito di tipo
Visa, Visa Electron o Postepay con una commissio-
ne di 1solo nel caso in cui la somma trasferita sia
uguale o inferiore a 100: se maggiore, il costo
della transazione gratuito. Lutilizzo veramente
semplice: la configurazione del sito web richiede
pochi passi e per limple mentazione si pu fare
riferimento al team di sviluppo messo a disposi-
zione appositamente. Inoltre, il negoziante non ha
bisogno di un gateway o di un conto commerciale
a parte, conveniente per le aziende di qualsivo-
glia dimensione, i suoi clienti non hanno bisogno
Paypal.
PAYPAL E SICUREZZA
Requisito fondamentale per la scelta di un siste-
ma di pagamento elettronico, le cui informazio-
ni viaggino on-line, la sicurezza.
Approfondiamo come sono gestiti gli aspetti ad
essa relativi al fine di testare laffidabilit del ser-
IL TUO SITO PRONTO
PER PAYPAL
IN QUESTO PRIMO ARTICOLO CI OCCUPEREMO DI DESCRIVERE LINSIEME DEI SERVIZI
DI PAGAMENTO SICURO OFFERTI DA PAYPAL. ANALIZZEREMO, ALTRES, GLI STRUMENTI
PER LINTEGRAZIONE DELLIPN ALLINTERNO DI UN PROPRIO SITO WEB
Conoscenze richieste
HTML e PHP
Software
-
Impegno
Tempo di realizzazione
REQUISITI
039-043:032-035 16-07-2008 9:23 Pagina 39
ht t p: / / www. i opr ogr ammo. i t
vizio sia dal punto di vista del commerciante che
dellacquirente, in particolare per quel che
riguarda la possibilit di storno delle operazioni
effettuate, e poi in merito alla protezione da
frodi. In termini generali, Paypal si impegna nella
protezione della privacy e dellidentit degli
utenti ed esibisce, come garanzia, i dati relativi
alla percentuale di perdite sulle transazioni effet-
tuate con il sistema che risultano essere inferiori
a 0,5%: il valore pi basso del settore. Questo, per
quel che riguarda laspetto generale dellutilizzo.
Analizziamo le specifiche strategie usate per ren-
dere efficace e sicuro il sistema delle transazioni.
GUIDA AI CHARGEBACK
Cos come specificato nel contratto, il cliente ha
180 giorni di tempo per dichiararsi insoddisfatto
dellacquisto e stornare loperazione di addebito
attraverso la societ emittente la carta di credito.
Questo pu avvenire per diversi motivi: il pi
banale che non ha ricevuto loggetto, o anche
perch loggetto notevolmente diverso da quello
che era stato descritto o illustrato dallimmagine,
piuttosto che per un pagamento non autorizzato,
per sottrazione o uso fraudolento del numero di
carta. Egli, dunque, richiede alla societ emittente
di stornare lammontare della transazione fatta,
quandanche questa fosse stata gi liquidata,
secondo i regolamenti e gli accordi previsti in
termini di chargeback dallistituto di credito
interessato. Partendo dal presupposto che
chiunque accetti pagamenti con carta di credito
esposto al rischio di ricevere richieste di
chargeback e quindi, per questo, tale aspetto debba
essere considerato come una possibile perdita da
parte dellacquirente e dunque come costo di
attivit, Paypal fornisce supporto per la loro
gestione in termini di strumenti per la
comprensione e la contestazione. Una volta che un
acquirente inoltra una richiesta di chargeback
verr inviata unemail al venditore per informarlo
appena listituto di credito inoltra la procedura di
recupero, bloccando i fondi in questione
(ovviamente, solo temporaneamente),
collaborando col venditore per risolvere il
chargeback nel modo pi efficace possibile con la
banca, entro circa 70-100 giorni (questi infatti sono
i tempi per la risoluzione della contestazione). Ma
c di pi: Paypal offre degli strumenti per ridurre
quanto pi possibile la possibilit di ricevere
chargeback. Spesso il motivo dei chargeback
dipende dalla difficolt del compratore di
contattare il venditore, qualora ci fossero problemi
al ricevimento della merce acquistata. sempre
importante, a tal fine, fornire un indirizzo e-mail e
dei numeri telefonici per cercare di risolvere tutte
le incomprensioni. Utilissimo, inoltre, stabilire un
contatto prima di concludere la compravendita
qualora loggetto abbia un costo rilevante.
Non solo. importante anche che la risposta a
ciascuna richiesta di contatto sia tempestiva e
professionale, di modo che lacquirente non abbia
la sensazione che i suoi problemi siano rimasti
irrisolti. Se proprio lacquirente deciso a inoltrare
la richiesta di storno, consigliando di aprire la
contestazione al Centro Risoluzioni di Paypal,
viene offerta la possibilit di risoluzione tramite
questultimo, che collabora direttamente con il
venditore. Alcune altre semplici accortezze
possono poi essere quella di stipulare
unassicurazione per la spedizione del pacco, per
contrastare la possibilit che loggetto si perda in
fase di spedizione, e fornire descrizioni delloggetto
quanto pi accurate possibili allinterno del sito
che ne propone lacquisto.
LA PROTEZIONE FRODI
Paypal forte di un team antifrode composto da
oltre 1.000 addetti presenti in tutto il mondo, attivo
24 ore su 24, 7 giorni su 7 per la totale garanzia in
termini di sicurezza delle transazioni e la riserva-
tezza delle informazioni finanziarie, utilizza sofisti-
catissimi modelli di rischio antifrode proprietari,
in grado di rilevare e prevedere transazioni fraudo-
lente prima che possano compromettere lazienda.
Luso intenso della crittografia, ancora pi accen-
tuato rispetto ad altri istituti finanziari, protegge-
dalleventualit che i dati sensibili inerenti le carte
possano essere carpiti mentre viaggiano in rete e,
dunque, utilizzati in maniera fraudolenta.
Per quanto concerne gli aspetti relativi alla sicurez-
za degli acquirenti, essi sono salvaguardati non
solo perch la loro identit finanziaria non viene
comunicata ai venditori, ma anche perch vengo-
no fatti dei test per verificare lesistenza dei dati
forniti allatto di registrazione: lAVS (Address
Verification System) che controlla che l'indirizzo
utilizzato dall'utente in fase di ordine coincida con
quello associato effettivamente alla carta di credito
(cos come risulta nel database delle societ emit-
tenti) e il CSC (altrimenti detto CVV2), ovvero il
numero di tre o quattro cifre presenti sul retro delle
carte di credito di nuova generazione.
Per il momento ancora in fase di brevetto, il siste-
ma per la verifica dei conti corrente bancari, un
ulteriore livello di autenticazione.
GLI UTENTI VERIFICATI
Iniziamo, quindi, a interagire col sistema.
Una volta che si eseguita la procedura di regi-
ioProgrammo Web
M
G
40
/Settembre 2008
Integrazione di PayPal nei siti di e-commerce
NOTA
PI BUONI CON
PAYPAL
Tra gli strumenti messi a
disposizione del venditore,
vi anche la possibilit di
destinare una parte del
pagamento a delle
associazioni no-profit,
opportunamente scelte.
039-043:032-035 16-07-2008 9:23 Pagina 40
ht t p: / / www. i opr ogr ammo. i t
strazione, se non viene associata alcuna carta di
credito allaccount definito, lutente viene
dichiarato non verificato. Questo significa che le
operazioni sul conto sono limitate, innanzitutto,
per quel che riguarda il valore delle transazioni.
Per evitare ci, necessario partecipare al
Programma codice di verifica: questo consentir di
eliminare il limite di 750 nei pagamenti e di
garantire maggiore sicurezza ricevendo una cer-
tificazione sul conto Paypal che aumenter
laffidabilit come fruitore del servizio. neces-
sario inserire nellaccount i dati di una carta di
credito ( accettata anche la ricaricabile
Postepay) e poi cliccare sulla scritta Partecipa
al programma codice di verifica. Perch
loperazione vada a buon fine, importante
poter visualizzare, in formato cartaceo o tele-
matico, l'estratto conto della propria carta di
credito. Questo servir a controllare il codice
delloperazione di prelievo di 1,50 che Paypal
effettuer sul conto, al fine di evitare frodi. Una
volta che la transazione fatta, si copier il
codice attribuito e si provveder ad inserirlo
nella finestra relativa al proprio account. In
questo modo si permette a Paypal di verificare
lesatta corrispondenza tra intestatario della
carta e chi ha effettuato loperazione di regi-
strazione della carta. Limporto prelevato verr
poi restituito al prima acquisto che si far col
sistema.
COME FUNZIONA
PAYPAL
Sul sito Paypal vengono elencati e descritti i
sistemi che possono essere implementati per
effettuare dei pagamenti. Il venditore pu sce-
gliere tra i pagamenti via e-mail e i pagamenti
attraverso il sito Web, di tipo Standard ed
Express. La prima opzione, rapida e sicura,
permette di ricevere la transazione senza
neanche la necessit di avere un proprio sito,:
basta inviare unemail con una richiesta di
pagamento al proprio cliente che, attraverso
un pulsante o un link in essa contenuto viene
reindirizzato al sito di Paypal : laddebito
avviene direttamente da l. Cos si permette di
ricevere pagamenti senza avere un conto spe-
cifico di tipo Business, senza spese mensili e
tariffe di configurazione, ma semplicemente
pagando una piccola trattenuta sullimporto.
Limmagine seguente, cos come illustrato sul
sito, mostra graficamente come avviene la
transazione.
Il venditore invia un e-mail allacquirente in cui
appare un link o un bottone che indirizza al sito
di Paypal per la richiesta di pagamento e
leffettuazione della transazione in modo sicuro.
Molto simile il funzionamento dellopzione di
pagamento dal proprio sito web. Come mostrato
in Fig.2, basta inserire un pulsante allinterno
della propria pagina web in cui siano presenti le
opzioni di scelta dei sistemi pagamento, e il
cliente viene immediatamente re-indirizzato al
sito Paypal, pagando con carta di credito o con
conto Paypal: limporto viene subito accreditato
sul fondo del venditore.
Sul sito del venditore appare un bottone perso-
nalizzato che richiama il sito Paypal, cliccando
sul quale si viene rediretti verso una pagina per
effettuare il pagamento con carta o saldo Paypal.
Limporto viene accreditato subito sul conto del
venditore e il cliente pu continuare la naviga-
zione.
La modalit Express non molto diversa concet-
tualmente ma un po pi complicata da imple-
mentare: la differenza sta sostanzialmente nel
fatto che il cliente viene re-indirizzato sul sito
Paypal per confermare la modalit di pagamento
e subito dopo riportato sul sito per completare la
procedura di acquisto con i dati di spedizione.
Il cliente sceglie la modalit di pagamento: se
gi utente Paypal viene reindirizzato subito al
sito, altrimenti dovr inserire i dati di fatturazio-
ne dal sito di e-commerce. Dopodich paga su
Paypal e visualizza la conferma dellordine sul
sito del venditore.
Con il Pagamento Express, i clienti saranno tra-
sferiti su PayPal solo per il pagamento, quindi
reindirizzati al sito web per completare il proprio
ordine.
M
ioProgrammo Web
Settembre 2008/
41
G
Integrazione di PayPal nei siti di e-commerce
Fig. 1: Schema di interazione tra cliente e vendito-
re per il pagamento via e-mail.
Fig. 2: Schema di interazione tra cliente e vendito-
re per il pagamento Standard
NOTA
PAYPAL OVUNQUE
Non solo on-line!
Epossibile pagare anche
attraverso sms, con
trasferimenti di piccole
somme di danaro:
Paypal mobile
039-043:032-035 16-07-2008 9:23 Pagina 41
ht t p: / / www. i opr ogr ammo. i t
Adoperando, invece, la modalit Standard ,i
clienti saranno trasferiti su PayPal per effettuare
il pagamento e completare l'ordine.
In questo modo i clienti effettuano gli acquisti
sul sito web e i pagamenti tramite PayPal.
IMPLEMENTAZIONE DEL
PAGAMENTO STANDARD
Questo sistema permette sia lacquisto di artico-
li singoli, che attraverso un carrello elettronico,
quando il sito offre un catalogo di prodotti.
In tal modo si permette di ricevere pagamenti,
approfittando dei sofisticati sistemi di sicurezza
del servizio, anche da chi non possiede un
account Paypal.
Entrando nel dettaglio, la tecnica basata su un
re-indirizzamento a partire dal sito del venditore:
un form html e un pulsante di tipo Acquista redi-
reziona il cliente dal sito di e-commerce a quello di
Paypal: egli cos si logga, verifica i dati di paga-
mento e seleziona come pagare, tra le alternative
precedentemente indicate al momento della
registrazione, accetta il pagamento e richiede,
eventualmente, di stampare la ricevuta.
Fatto ci, viene riportato sul sito di partenza per
poter continuare tranquillamente la sua naviga-
zione.
Come utilizzare tale soluzione? La prima cosa da
fare inserire un bottone di tipo Pagamento
Paypal. Questo verr automaticamente generato,
una volta che si inseriscono i propri dati allatto
dellacquisto del bottone stesso, e dunque per-
sonalizzato. Riportiamo il codice di un bottone-
tipo. Perch esso sia integrato e funzionante,
bisogna inserire allinterno della propria pagina
web il seguente script.
<form action="https://www.paypal.com/
cgi-bin/webscr" method="post">
<input type="hidden" name="cmd"
value="_xclick">
<input type="hidden" name="business"
value="nomeVenditore @nomeAzienda.com">
<input type="hidden" name="item_name"
value="Descrizione articolo">
<input type="hidden" name="item_number"
value="Numero articolo">
<input type="hidden" name="amount"
value="200.00">
<input type="hidden" name="no_shipping"
value="2">
<input type="hidden" name="Ic" value="IT">
<input type="hidden" name="currency_code"
value="EUR">
<input type="hidden" name="bn"
value="IC_Esempio">
<input type="image"
src="https://www.paypal.com/it_IT/i/btn/x-click-
but01.gif"
name="submit" alt="PayPal, il modo sicuro di
pagare e farsi pagare online!>
<img alt=""
src="https://www.paypal.com/en_US/i/scr/pixel.gif"
width="1" height="1">
</form>
Lazione implementata la creazione di un form,
invisibile, il quale invia con metodo POST un rife-
rimento allindirizzo e-mail che il venditore ha
inserito in fase di registrazione (value="nome
Venditore @nomeAzienda.com"), la descrizione
dellarticolo oggetto dellacquisto (value="Descri -
zione articolo"), il numero associato ("Numero
ioProgrammo Web
M
G
42
/Settembre 2008
Integrazione di PayPal nei siti di e-commerce
Fig. 3: : Schema di interazione tra cliente e vendi-
tore per il pagamento Express
Innanzi tutto visitiamo lindirizzo
www.paypal.it e clicchiamo su
Registrati. E possibile scegliere
tra tre opzioni. Il Conto Personale
- gratuito, veloce e sicuro - il pi
indicato per chi utilizza il servizio
prevalentemente per acquisti on-
line. Fornisce, inoltre, la
possibilit di accettare un numero
limitato di pagamenti all'anno
finanziati tramite carta di credito
o prepagata a tariffe contenute.
Il Conto Premier aggiunge alle
funzionalit del conto personal
anche la possibilit di accettare
ogni tipo di pagamento in modo
immediato e sicuro. Orientato alle
vendite, soprattutto tra privati,
offre, strumenti gratuiti come il
Carrello PayPal, il pulsante per
accettare pagamenti direttamente
dal proprio sito web e la
possibilit di personalizzare il
flusso di pagamento attraverso le
funzioni API. Il profilo Conto
Business appositamente
studiato per le transazioni
commerciali e dedicato alle
attivit di business on-line:
permette di accettare pagamenti
immediati da tutto il mondo,
svolgendo lattivit sotto la
propria ragione sociale e
beneficiare gratuitamente dei
vantaggiosi strumenti di e-
commerce PayPal, soprattutto in
termini di charge back e sicurezza
delle transazioni. Il contratto che
necessario accettare specifica i
termini del diritto di recesso da
parte dellacquirente: esso, infatti,
pu essere esercitato per i
successivi 180 giorni dalla data di
addebito della somma
corrisposta. possibile utilizzare
carte ricaricabili (ma non usa e
getta), senza obbligo di fornire il
numero della carta di credito
associata a un conto corrente,
aumentando la sicurezza.
APRIRE UN CONTO PAYPAL
039-043:032-035 16-07-2008 9:24 Pagina 42
ht t p: / / www. i opr ogr ammo. i t
articolo"), il prezzo (value="200.00"), la quantit, la
lingua (value="IT"), la valuta in euro e lindirizzo
dellimmagine che deve essere caricata (<input
type="image"..).
La modalit automatica per la creazione del bot-
tone dal sito , invece, la seguente:
1. Accedere al proprio conto PayPal Premier o
Business.
2. Immette il seguente link nella barra indirizzi
del proprio browser web: https://www.paypal.com/
it/cgi-bin/webscr?cmd=_web-tools
3. Inserire i dettagli sul pulsante e scegliere la
tipologia che si preferisce.
4. Cliccare su Crea pulsante adesso.
Un consiglio: opportuno, al momento della
creazione del pulsante, attivare l'opzione corri-
spondente di crittografia, per evitare che il codi-
ce possa essere manipolato esternamente da
terzi. La soluzione precedentemente descritta
serve a implementare un esempio di acquisto di
un prodotto singolo. In realt, nei siti di commer-
cio elettronico, la prassi utilizzare i carrelli elet-
tronici.
Occupiamoci, dunque, del trasferimento del
contenuto di un carrello per il pagamento.
Di seguito il codice.
<form action="https://www.paypal.com/cgi-
bin/webscr" method="post">
<input type="hidden" name="cmd" value="_cart" />
Specifichiamo che si tratta di oggetti che sono in
un carrello:
<input type="hidden" name="upload" value="1" />
La riga precedente, il cui valore deve essere
impostato sempre a 1, informa PayPal che ver-
ranno trasmessi i valori di un carrello.
<input type="hidden" name="business"
value="nomeVenditore@nomeAzienda.com" />
<input type="hidden" name="item_name_1"
value="Articolo 1" />
<input type="hidden" name="amount_1"
value="1.00" />
<input type="hidden" name="item_name_2"
value="Articolo 2" />
<input type="hidden" name="amount_2"
value="2.00" />
Definiamo i nomi degli oggetti del carrello e il
loro valore:
<input type="submit" value="PayPal" />
</form>
Mandiamo il tutto a Paypal. In maniera pi sofi-
sticata, potremmo voler implementare prima
linserimento di oggetti nel carrello, poi per tra-
sferire gli stessi a Paypal per il pagamento.
<form name="_xclick" target="paypal"
action="https://www.paypal.com" method="post">
<input type="hidden" name="cmd" value="_cart">
Specifichiamo che stiamo adoperando un carrel-
lo elettronico:
<input type="hidden" name="business"
value="nomeVenditore@nomeAzienda.com">
<input type="hidden" name="currency_code"
value="EUR">
<input type="hidden" name="item_name"
value="Descrizione Articolo">
<input type="hidden" name="item_name"
value="200.00">
Indichiamo il venditore, identificato tramite il
proprio indirizzo e-mail, la valuta in euro,
larticolo da aggiungere ed il suo prezzo.
<input type="image"
src="http://www.paypal.com/it_IT/i/btn/sc-but-
01.gif" border="0" name="submit" alt="Effettua i
tuoi pagamenti con PayPal. ">
<input type="hidden" name="add" value="1">
Visualizziamo limmagine al cui clic verr
aggiunto loggetto al carrello ed effettuiamo
linserimento.
</form>
Dopo aver fatto tutte le operazioni, possiamo
chiudere il form.
Mentre, per inviare lammontare di un carrello,
senza specificare di quali oggetti si tratti, optere-
mo per la seguente soluzione:
<form action="https://www.paypal.com/
cgi-bin/webscr" method="post">
<input type="hidden" name="cmd"value="_xclick"/>
<input type="hidden" name="business"value=
"nomeVenditore@nomeAzienda.com" />
<input type="hidden"
name="item_name"value="Descrizione Articolo" />
<input type="hidden" name="amount"
value="15.00" />
<input type="submit" value="PayPal" />
</form>
Caterina Patrizia Morano
M
ioProgrammo Web
Settembre 2008/
43
G
Integrazione di PayPal nei siti di e-commerce
NOTA
DIFFUSIONE DEL
SERVIZIO
Da una statistica Nielsen
del 2007 risulta che un
acquirente online su tre ha
un conto PayPal e ogni 24
secondi viene aperto un
nuovo conto.
039-043:032-035 16-07-2008 9:24 Pagina 43
J CD J WEB
visualizzatoreimmagini.zip
cdrom.ioprogrammo.it
ht t p: / / www. i opr ogr ammo. i t
ioProgrammo Web
M
G
44
/Settembre 2008
Introduzione alla Visual Library di Net Beans
M
olti sviluppatori di applicazioni desktop e
applet Java hanno apprezzato il lancio
del visual editor di NetBeans chiamato
Matise. Questo strumento ha reso pi rapida e pia-
cevole la creazione di GUI (Graphic User Interface)
basate su swing/AWT che, per molto tempo, sono
state un punto dolente delle applicazioni Java.
Spesso, per si ignora che NetBeans fornisce una
piattaforma composta da una serie di API che ci
aiuta a migliorare le nostre applicazioni. Una di
queste API la Visual Library. Vedremo come sia
possibile sfruttare questa libreria per creare in pochi
e semplici passi un visualizzatore di immagini dota-
to, di funzionalit complesse come lo zoome il pan.
Il risultato finale che desideriamo ottenere
mostrato nellimmagine che segue:
La Visual Library (VL) una libreria open source
distribuita come parte di NetBeans; essa permette
di creare strumenti di visualizzazione evoluti nelle
applicazioni Java. La VL viene utilizzata in vari
moduli di NetBeans: nel visual designer di Jasper
Reports, per il Mobility Pack e per leditor JSF si veda
la Fig. 2. Comunque possibile usare la libreria
anche in applicazioni che non siano estensioni di
NB. Vedremo come trarre vantaggio da questa libre-
ria in unapplicazione standalone per la visualizza-
zione di immagini.
La Visual Library 2.0 prende il posto di Graph, usata
nelle versioni di NetBeans precedenti alla 6.0. Infatti
Graph era pensata per supportare la creazione di
schemi e grafi, la VL invece uno strumento di
visualizzazione general purpose sfruttabile in modo
creativo nelle nostre applicazioni.
CONOSCERE E UTILIZZARE
I WIDGET
La struttura di un sistema che fa uso della VL simi-
le a quella di una normale applicazione swing.
Si costruisce e si opera su un albero di elementi
visuali chiamati Widgets. Un Widget un elemento
visuale primitivo, come un JCompo nent lo per
unapplicazione swing. Esso contiene le informazio-
ni relative alla sua posizione, al tipo di contorno, alle
dimensioni, al layout e poco altro. Inoltre, possibi-
le agganciare e rimuovere child di tipo Widget ad
ogni elemento di tipo Widget. I principali tipi di wid-
get forniti dalla VL sono:
G LabelWidget: Rappresenta una singola linea di
testo manipolabile tramite i metodi getText() e
setText().
G ImageWidget: Rappresenta unimmagine mani-
polabile tramite i metodi getImage() e setImage().
Tra le altre cose questo elemento supporta le
immagini animate. Questo Widget sar la base
per il nostro visualizzatore.
La radice dellalbero dei Widget costituita dalla
CREARE UN IMAGE
VIEWER CON JAVA
SCOPRIAMO COME SFRUTTARE ALCUNE DELLE FUNZIONI PRINCIPALI DELLA VISUAL LIBRARY,
UNA LIBRERIA OPENSOURCE DISTRIBUITA COME PARTE DI NETBEANS. LA ADOPEREREMO
PER REALIZZARE UN VISUALIZZATORE DI IMMAGINI CON POCHISSIME RIGHE DI CODICE
Conoscenze richieste
Java, Swing
Software
JDK, Netbeans 6.x
Impegno
Tempo di realizzazione
REQUISITI
Fig. 1: Il visualizzatore dimmagini che realizzeremo.
Fig. 2: La Visual Library usata per leditor dei colle-
gamenti nelle pagine JSF.
044-047:032-035 16-07-2008 9:29 Pagina 44
ht t p: / / www. i opr ogr ammo. i t
classe Scene che permette di gestire i parametri
della visualizzazione e funge da contenitore per
tutti i Widget. Per coerenza con la struttura dellal-
bero, la classe Scene lestensione di un Widget.
Esistono alcune specializzazioni della classe Scene
che possono essere usate come radici alternative:
G ObjectScene: Questa classe permette di separare
gli oggetti del modello dai Widget presenti nella
scena ottenendo un livello dastrazione superio-
re.
G GraphScene: Questo tipo di scena permette di
gestire con facilit visualizzazioni di grafi. Infatti
questa scena composta da archi e nodi.
Differentemente da quello che ci si potrebbe aspet-
tare la classe Scene e i Widget non sono direttamen-
te dei JComponent da poter inserire nelle nostre
applicazioni. Tramite la classe Scene per possibi-
le recuperare un JComponent che contiene la vista
sulla struttura realizzata richiamando il metodo
Scene.createView().
Inoltre il metodo Scene.createSatelliteView() per-
mette di ottenere una vista secondaria per facilitare
le operazioni di pan e zoom.
Un ulteriore tipo di Widget rappresentato dai
LayerWidget. Si tratta di elementi che permettono
di organizzare in modo ottimale la logica di visua-
lizzazione dellapplicazione. I layer vengono nor-
malmente inseriti nella scena o allinterno di altri
Widget. Un Layer rappresenta un glass-pane come i
JGlassPane per swing. Spesso useremo i seguenti
LayerWidget allinterno di una scena:
G backgroundLayer: per le interazioni temporanee
in background come la selezione rettangolare.
G mainLayer: Contiene i Widget principali dellap-
plicazione.
G connectionLayer: Si tratta di un livello molto
usato nella visualizzazione di grafi per rappresen-
tare le connessioni tra gli elementi e velocizzare la
validazione della scena.
G interactionLayer: per interazioni in primo piano,
per esempio per manipolare le maniglie di ridi-
mensionamento o le frecce di connessione tra i
nodi di un grafo.
A questo punto conosciamo tutti gli elementi
essenziali che ci permettono di realizzare
unapplicazione VL, vediamo come usarli.
LINTERFACCIA
Iniziamo a mettere le mani sul codice per scoprire
le potenzialit della VL. Seguendo la normale pro-
cedura proposta dalla documentazione della VL
dovremmo creare un modulo aggiuntivo da inglo-
bare nel nostro progetto. Il metodo proposto inve-
ce pi rapido e permette di avere un solo progetto
su cui operare. Creiamo un nuovo progetto allin-
terno di NetBeans di tipo Java Application.
Per poter usare le funzionalit della VL necessario
specificare il riferimento alla libreria nelle propriet
del progetto. A questo punto dobbiamo creare la
finestra principale della nostra applicazione. Il
modo pi semplice di sfruttare le funzionalit del
visual editor di NetBeans, quindi selezioniamo file-
>New File, creiamo un JFrame Form dalla sezione
GUI Swing e chiamiamolo MainFrame
La VL permette di creare una vista principale nella
quale poter inserire e agire sui Widget, allinterno di
questa vista saranno possibili molte operazioni tra
cui lo zoom e il pan. Inoltre, sfrutteremo la vista
secondaria che permette di navigare facilmente
nella globalit della vista principale.
Per creare un contenitore per la vista principale
usiamo uno JScrollPane; questo componente ci
permette di avere le barre di scorrimento orizzonta-
li e verticali nel caso gli elementi della vista princi-
pale non siano visualizzati completamente. Per la
vista secondaria creiamo un JPanel. In Fig.3 il detta-
glio della vista secondaria.
Lapplicazione presentata un semplice visualizza-
tore dimmagini e ha bisogno solo di un Widget in
grado di contenere limmagine che stata aperta.
Sarebbe possibile evitare di usare i layer ma
importante imparare il loro utilizzo, che ritorner
utile nello sviluppo di applicazioni pi evolute o per
estendere il nostro visualizzatore. Il codice che ne
deriva veramente semplice:
private JComponent view;
private Scene scene;
private LayerWidget layer;
private ImageWidget iw;
public MainFrame() {
initComponents();
//Creazione della Scene e associazione dei
M
ioProgrammo Web
Settembre 2008/
45
G
Introduzione alla Visual Library di Net Beans
NOTA
ALTERNATIVE
La Visual Library di
NetBeans non lunica
libreria a fornire le
funzionalit descritte
nellarticolo, una valida
alternativa JGraph anche
se questa risulta
nettamente orientata ai
grafi un po pi
complessa.
Fig. 3: possibile agire con il mouse direttamente
nella vista satellite prima per selezionare la zona
da visualizzare.
044-047:032-035 16-07-2008 9:29 Pagina 45
ht t p: / / www. i opr ogr ammo. i t
Component
scene = new Scene();
view = scene.createView();
jSPImage.setViewportView(view);
jPanelSatelite.add(scene.createSatelliteView(),
BorderLayout.CENTER);
//Inserimento del layer
layer = new LayerWidget(s);
s.addChild(layer);
//Creazione del widget per l'immagine
iw = new ImageWidget(scene);
layer.addChild(iw);
}
SELEZIONE
DELLIMMAGINE
Per fare in modo che lutente possa selezionare
unimmagine da visualizzare, inseriamo un pulsante
nel MainFrame e ad esso associamo unazione che
apre un JFileChoser. Per semplificare la selezione del
file da visualizzare inseriamo un FileNamed
ExtensionFilter. Questa classe ci permette di limitare
gli elementi visualizzati in base allestensione che ci
interessa. Nel nostro caso visualizzeremo solo i file
con estensione jpg. Il codice da inserire nellazione
il seguente:
JFileChooser jFileChooser1 = new JFileChooser();
jFileChooser1.setMultiSelectionEnabled(false);
jFileChooser1.setApproveButtonText("Scegli");
jFileChooser1.setControlButtonsAreShown(true);
jFileChooser1.setDialogTitle("Seleziona
l'immagine dell'articolo");
jFileChooser1.setDialogType(JFileChooser.OPEN_DIALOG)
FileNameExtensionFilter filter = new
FileNameExtensionFilter("Immagini JPG", "jpg");
jFileChooser1.addChoosableFileFilter(filter);
if (jFileChooser1.showOpenDialog(this) ==
JFileChooser.APPROVE_OPTION){
try{
File f = jFileChooser1.getSelectedFile();
setImage(f.getCanonicalPath());
}catch(Exception e){
JOptionPane.showMessageDialog(this,
"Impossibile aprire l'immagine.\n" + e);
}}
Come si nota, nel caso in cui lutente abbia effettiva-
mente selezionato un file, si richiama il metodo
setImage(String), cos definito:
private void setImage(String path){
iw.setImage(new ImageIcon(path).getImage());
scene.validate();
setTitle ("File: " + path);}
Il metodo carica unimmagine nel Widget che abbia-
mo inserito nella scena. Per ottenere limmagine dal
path selezionato stata usata la classe ImageIcon.
Unalternativa che permetterebbe di caricare anche
le immagini animate rappresentata da Toolkit.
createImage(String). Si noti la chia mata al metodo
scene.validate(); quando agiamo su un Widget
necessario indicare alla Scene che costituisce la radi-
ce dellalbero degli elementi visuali la necessit di
rielaborare le informazioni per aggiornare la vista
principale e le viste secondarie.
IL MAIN
DELLAPPLICAZIONE
Il main dellapplicazione tipico per le applicazioni
swing. Modifichiamo quello proposto da NetBeans
in modo da richiamare il LookAndFeel relativo al
sistema dellutente:
UIManager.setLookAndFeel(UIManager.getSystemLook
AndFeelClassName());
Sebbene il normale L&F delle applicazioni Java sia
piuttosto gradevole, preferibile fornire allutente
uninterfaccia coerente con le altre applicazioni pre-
senti sul suo sistema.
INSERIAMO LE AZIONI
Il codice presentato in precedenza praticamente
completo. Infatti possiamo aprire e visualizzare le
immagini e muoverci usando le barre di scorrimen-
to o la vista secondaria. Aggiungiamo qualche fun-
zione pi evoluta. Come detto in precedenza voglia-
mo che il nostro visualizzatore permetta allutente
di zoommare avanti e indietro e se il fattore di zoom
non permette di visualizzare tutta limmagine nella
vista principale vogliamo poter spostare la sezione
visualizzata con loperazione di pan. Ecco il codice
completo per creare lo zoom:
scene.getActions().addAction(ActionFactory.create
MouseCenteredZoomAction(1.1d));
Inseriamo questa istruzione in coda al costruttore
della classe MainFrame. In questo modo avremo a
disposizione loperazione di zoom centrata sulla
posizione del mouse, come parametro impostiamo
il fattore di variazione. A questo punto se ricompilia-
mo il progetto e posizionando il mouse al centro
della vista principale, premendo il tasto CTRL pos-
siamo usare la rotellina del mouse per zoommare
avanti e indietro. Davvero notevole no?
Linserimento dellazione di pan e del tutto simile a
quanto fatto in precedenza. Ecco il codice:
ioProgrammo Web
M
G
46
/Settembre 2008
Introduzione alla Visual Library di Net Beans
NOTA
RIFERIMENTO ALLA
VISUAL LIBRARY
1. Dopo aver creato il
nuovo progetto, fate clic
con il pulsante destro del
mouse sulla cartella
libraries e selezionate add
library. A meno che non
abbiate gi usato la Viual
Library sar necessario
creare un nuovo
riferimento ai file della
libreria. Quindi premete
Create.
2. Inserire come nome
Viual Library quindi
premere OK. A questo
punto si possono
selezionare i file premendo
sul pulsante Add
Jar/Folder. In riferimento
alla cartella di installazione
di NetBeans i file da
inserire sono:
netbeans/platform8/lib/or
g-openide-util.jar e
netbeans/patform8/mod
ules/org-netbeans-api-
visual.jar.
044-047:032-035 16-07-2008 9:29 Pagina 46
ht t p: / / www. i opr ogr ammo. i t
scene.getActions().addAction(ActionFactory.createPan
Action());
A questo punto, tenendo premuto il pulsante cen-
trale del mouse sopra limmagine visualizzata pos-
siamo spostare la sezione di immagine visibile.
Evidentemente queste azioni sono molto comode e
potenti, per probabile che lutente non ricordi
esattamente le combinazioni di tasti necessarie a
eseguirle. Inseriamo, quindi, due pulsanti aggiuntivi
che permettono di ottenere la funzione di zoom in e
zoom out. A questi associamo il seguente codice:
private void jButtonZoomInActionPerformed
(java.awt.event.ActionEvent evt) {
scene.setZoomFactor(scene.getZoomFactor() + 0.1d);
scene.validate(); }
private void jButtonZoomOutActionPerformed
(java.awt.event.ActionEvent evt) {
scene.setZoomFactor(scene.getZoomFactor() - 0.1d);
scene.validate();}
Come si pu notare dal codice, sufficiente agire sul
metodo setZoomFactor() della scena per impostare il
nuovo livello di zoom. Come sempre bisogna ricor-
darsi di chiamare il metodo validate() per aggiorna-
re linterfaccia. La nostra scena piuttosto semplice
in quanto composta da un solo widget per contene-
re limmagine, quindi qualcuno potrebbe pensare
che queste operazioni non sarebbero poi molto
complicate anche se realizzate con Java2D. Si consi-
deri, per, che il codice proposto rimane inalterato
anche per scene estremamente complesse conte-
nenti molti widget di vario tipo e vari collegamenti
tra gli stessi.
ANIMAZIONI
Per lungo tempo stato sottovalutato limpatto di
uninterfaccia ben realizzata e ricca dinterattivit.
Di fatto, per, il mercato richiede GUI che oltre ad
essere funzionali devono essere gradevoli. Sempre
pi speso si parla di RIA (Rich Internet Application) e
certo lambiente desktop non pu essere da meno.
Purtroppo, per i linguaggi di programmazione e i
sistemi di gestione delle finestre non offrono grandi
funzionalit per rendere rapida la realizzazione di
interfacce attive. Vediamo come la Visual Library
permette di migliorare la nostra applicazione dan-
dole un aspetto pi moderno e vivo. La libreria con-
tiene una serie di istruzioni per la realizzazione di
animazioni tramite la classe SceneAnimator rag-
giungibile attraverso il metodo Scene.getScene
Animator(). In particolare, le animazioni che trovia-
mo sono:
G preferedLocation: Permette di ottenere sposta-
menti morbidi.
G preferedBounds: Permette di variare le dimensioni
di un Widget.
G backgrondColor e foregroundColor: Rispetti -
vamente per creare effetti di colore sullo sfondo e
sul primo piano. Si possono ad esempio creare dei
fade.
Proviamo, quindi, a inserire unanimazione costitui-
ta da uno scorrimento orizzontale quando una
nuova immagine viene aperta. Per farlo inseriamo il
seguente codice nel metodo setImge(). Grazie alle
funzionalit della VL il codice molto semplice:
iw.setPreferredLocation(new Point
(jSPImage.getSize().width, 0));
scene.validate();
scene.getSceneAnimator().animatePreferredLocation
(iw, new Point(0,0));
scene.validate();
Per prima cosa posizioniamo il widget contenente
limmagine al di fuori dello spazio visibile e chiamia-
mo la validate. Quindi richiamiamo la funzione
animatePreferedLocation() a cui passiamo un ogget-
to di tipo Point che contiene la nuova posizione del-
limmagine. Chiamare la validate in due istanti
diversi permette di attivare lanimazione solo dopo
che le operazioni sono state completate, ottenendo
un movimento pi fluido.
Possiamo anche modificare le funzioni di zoom che
abbiamo creato per i due pulsanti, sostituendo il
codice con quello relativo allanimazione di zoom:
scene.getSceneAnimator().animateZoomFactor
(scene.getZoomFactor() + 0.1d);
Per lo zoom in, mentre per lo zoom out avremo:
scene.getSceneAnimator().animateZoomFactor
(scene.getZoomFactor() - 0.1d);
A questo punto premendo sui pulsanti di zoom
otterremo unanimazione morbida che d leffetto
di avvicinamento e allontanamento dallimmagine.
CONCLUSIONI
La Visual Library di NetBeans offre una grande
variet di funzioni che permettono di semplificare
notevolmente compiti di visualizzazione anche
molto complessi. Se avessimo realizzato il visualiz-
zatore dimmagini tramite Java2D, avremmo dovuto
scrivere ben pi codice.
Marco Buccio
M
ioProgrammo Web
Settembre 2008/
47
G
Introduzione alla Visual Library di Net Beans
SUL WEB
Il sito ufficiale della
libreria, da cui possibile
accedere alla
documentazione e a una
serie di demo :
http://graph.netbeans.
org
LAUTORE
Marco Buccio ha
conseguito la laurea
specialistica in Scienze
dellInformazione presso
lUniversit di Milano con
una tesi riguardante
sistemi di collaborazione
basati sullAugmented
Reality. Appassionato di
innovazione e tecnologia
sviluppa applicazioni Java
e programmi per il
supporto alla didattica.
Se desiderate contattarlo:
marco.buccio@gmail.com
044-047:032-035 16-07-2008 9:29 Pagina 47
ht t p: / / www. i opr ogr ammo. i t
TIPS&TRICKS M
G
48
/Settembre 2008
Una raccolta di trucchi da tenere a portata di mouse
JAVA
CONTROLLARE
SE UN GIORNO LAVORATIVO
public boolean giorno lavorativo(Date date) {
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(date);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
if ((dayOfWeek Calendar.SATURDAY) || (dayOfWeek
Calendar.SUNDAY)) {
return false;
}
return true;
}
COPIARE UN FILE DA UNA
POSIZIONE ALL'ALTRA
public static void fileCopy( File in, File out )
throws IOException
{
FileChannel inChannel = new FileInputStream( in
).getChannel();
FileChannel outChannel = new FileOutputStream( out
).getChannel();
try
{
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = inChannel.size();
long position = 0;
while ( position < size )
{
position += inChannel.transferTo( position, maxCount,
outChannel );
}
}
finally
{
if ( inChannel != null )
{
inChannel.close();
}
if ( outChannel != null )
{
outChannel.close();
}
}
}
LEGGERE UN FILE
DI CONFIGURAZIONE
// il formato del file : chiave=valore
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
public class Configure extends Properties{
public Configure(){
}
public Configure(File configFile) throws IOException{
load(configFile);
}
public Configure(InputStream inputStream) throwsIOException{
load(inputStream);
}
public Configure(Properties props) throws IOException{
load(props);
}
public void load(Properties props) {
Enumeration<String> names = (Enumeration<String>)
props.propertyNames();
while(names.hasMoreElements()){
String name = names.nextElement();
String value = props.getProperty(name);
setProperty(name,value);
}
}
public void load(File configFile) throws IOException{
I trucchi del mestiere
Tips & Tricks
Questa rubrica raccoglie trucchi e piccoli pezzi di codice, frutto dellesperienza di chi programma, che solitamente non
trovano posto nei manuali. Alcuni di essi sono proposti dalla redazione, altri provengono da una ricerca su Internet, altri
ancora ci giungono dai lettori. Chi volesse contribuire, potr inviare i suoi Tips&Tricks preferiti. Una volta selezionati,
saranno pubblicati nella rubrica. Tutti i Tips elencati sono anche presenti nel supporto CD-Rom che accompagna la rivista
048-052:082-083 16-07-2008 10:26 Pagina 48
ht t p: / / www. i opr ogr ammo. i t
load(new FileInputStream(configFile));
}
}
CERCARE UNA STRINGA
IN UN TESTO
class ContinueWithLabelDemo {
public static void main(String[] args) {
String searchMe = "Cerco una stringa in me";
String substring = "stringa";
boolean foundIt = false;
int max = searchMe.length() - substring.length();
test:
for (int i = 0; i <= max; i++) {
int n = substring.length();
int j = i;
int k = 0;
while (n-- != 0) {
if (searchMe.charAt(j++)
!= substring.charAt(k++)) {
continue test;
}
}
foundIt = true;
break test;
}
System.out.println(foundIt ? "Trovata!" :
"Non trovata!");
}
}
STAMPARE A SCHERMO
LE PROPRIET DI SISTEMA
package test;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Properties;
public class Proprietes {
public static void main(String[] args) {
Properties proprietes = System.getProperties();
Enumeration<String> noms =
(Enumeration<String>)proprietes.propertyNames();
List<String> tabObj = new ArrayList<String>();
String nom;
while((nom = getElements(noms)) != null){
tabObj.add(nom);
}
for(int i = 0; i < tabObj.size(); i++){
System.out.println (tabObj.get(i)
+ " : " +
proprietes.getProperty(tabObj.get(i)));
}
}
public static String getElements(Enumeration<String>
enumeration){
try{
return enumeration.nextElement();
}
catch(NoSuchElementException e){
return null;
}
}
}
ELENCARE IL CONTENUTO
DI UNA DIRECTORY
File dir = new File("NomeCartella");
String[] children = dir.list();
if (children == null) {
// La directory non esiste, o non una cartella
} else {
for (int i=0; i<children.length; i++) {
// Get filename of file or directory
String filename = children[i];
}
}
SIMULARE IL "GOTO" IN JAVA
public class Goto
{
public static int END = Integer.MAX_VALUE;
public static void main(String[] args)
{
int _goto = 0;
do
{
switch(_goto)
{
case 0:
case 1:
System.out.println("Pip");
_goto = 3;
continue;
case 2:
System.out.println("pu");
_goto = END;
continue;
case 3:
System.out.println("po");
M TIPS&TRICKS
Settembre 2008/
49
G
Una raccolta di trucchi da tenere a portata di mouse
048-052:082-083 16-07-2008 10:26 Pagina 49
ht t p: / / www. i opr ogr ammo. i t
_goto = 2;
continue;
}
} while(false)
}
}
LISTA DEI PAESI E DEI CODICI ISO
SUPPORTATI DALLA JVM
for (Locale locale : Locale.getAvailableLocales()) {
final String contry = locale.getDisplayCountry();
if (contry.length() > 0) {
System.out.println("Paese = " + contry + ". codice ISO:
" + locale.getISO3Country());
}
}
CALCOLARE FACILMENTE
L'HASH MD5
import java.security.*;
import java.math.*;
public class MD5 {
public static void main(String args[]) throws Exception{
String s="Questo un test";
MessageDigest
m=MessageDigest.getInstance("MD5");
m.update(s.getBytes(),0,s.length());
System.out.println("MD5: "+new
BigInteger(1,m.digest()).toString (16));
}
}
SPLITTARE UNA STRINGA
private String[] splitString(String str, String delims)
{
if(str == null)
return null;
else if(str.equals("") || delims == null ||
delims.length() == 0)
return new String[]{ str };
String[] s;
Vector v = new Vector();
int pos = 0;
int newpos = str.indexOf(delims, pos);;
while(newpos != -1)
{
v.addElement(str.substring(pos,
newpos));
pos = newpos + delims.length();
newpos = str.indexOf(delims, pos);
}
v.addElement(str.substring(pos));
s = new String[v.size()];
for(int i=0, cnt=s.length; i<cnt; i++)
s[i] = (String) v.elementAt(i);
return s;
}
C#
LEGGERE UNA CHIAVE
DI REGISTRO
using Microsoft.Win32;
RegistryKey masterKey = Registry.LocalMachine.CreateSubKey
("SOFTWARE\\Test\\Preferences");
if (masterKey == null)
{
Console.WriteLine ("Masterkey nulla!");
}
else
{
Console.WriteLine ("MiaChiave = {0}", masterKey.GetValue
("MiaChiave"));
}
masterKey.Close();
UNA TABELLA PER CALCOLARE
GLI INTERESSI DI UN PRESTITO
public class CalculateInterestTable
{
public static void Main (string[] args)
{
Console.Write ("Immettere importo principale: ");
decimal principal =
Convert.ToDecimal (Console.ReadLine());
if (principal < 0)
{ // principal cannot be negative
Console.WriteLine ("Importo principale non pu essere un
numero negativo");
principal = 0;
}
Console.Write ("Inserire il tasso di interesse : ");
decimal interest = Convert.ToDecimal (Console.ReadLine());
if (interest < 0)
{ // interest cannot be negative
Console.WriteLine ("Interesse non pu essere un numero
negativo");
interest = 0;
}
Console.Write ("Inserire la durata, specificata in anni: ");
TIPS&TRICKS M
G
50
/Settembre 2008
Una raccolta di trucchi da tenere a portata di mouse
048-052:082-083 16-07-2008 10:26 Pagina 50
ht t p: / / www. i opr ogr ammo. i t
int noYears = Convert.ToInt32 (Console.ReadLine());
Console.WriteLine ("\nPrincipal = " + principal
+ "\nInterest = " + interest + "%"
+ "\nDuration = " + noYears + " years\n");
// looppa attraverso il numero degli anni specificati
int year = 1;
while (year <= noYears)
{
// calcola l'interesse
decimal interestPaid = principal * (interest / 100);
// calcola il nuovo importo principale
principal += interestPaid;
// arrotonda all'euro pi vicino
principal = decimal.Round (principal, 2);
Console.WriteLine ("Anno " + year + " " + principal);
year++;
}
Console.WriteLine ("\nPremi invio per fermare");
Console.Read();
}
}
COPIARE TUTTO UN ARRAY O
PARTE DI ESSO IN UN SECONDO
ARRAY
using System;
public class CopyArray
{
public static void Main()
{
int[] integers = new int[] {5, 10, 15};
double[] doubles = new double[3];
Array.Copy (integers, doubles, 2);
Console.Write ("array di elementi integer:" );
foreach (int integer in integers)
{
Console.Write("{0,3}", integer);
}
Console.Write ("array di elementi doubles:" );
foreach (double duble in doubles)
{
Console.Write ("{0,3}", duble);
}
Console.WriteLine();
}
}
RECUPERARE IL NOME NETBIOS
E DNS DAL PC LOCALE
static string GetLocalHostName ()
{
string netBiosName = System.Environment.MachineName;
return netBiosName;
string dnsName = System.Net.Dns.GetHostName();
return dnsName;
}
ELENCARE GLI ELEMENTI DI UN
ARRAY IN ORDINE ASCENDENTE
using System;
public class ReverseArraySort
{
public static void Main()
{
string[] strings = {"beta", "alpha", "gamma"};
Console.WriteLine ("Array elements: ");
DisplayArray (strings);
Array.Sort (strings); // ordina gli elementi
DisplayArray (strings);
}
public static void DisplayArray (Array array)
{
foreach (object o in array)
{
Console.Write ("{0} ", o);
}
Console.WriteLine();
}
}
RECUPERARE LA DATA
DI CREAZIONE DI UNA CARTELLA
using System;
using System.IO;
class DirectoryCreationTime
{
public static void Main()
{
string directoryString =
Directory.GetCurrentDirectory() + @"\DirDiProva";
Directory.CreateDirectory (directoryString);
DateTime dateTime = Directory.GetCreationTime
(directoryString);
Console.WriteLine("Creation time: {0}", dateTime);
Directory.Delete (directoryString);
}
}
M TIPS&TRICKS
Settembre 2008/
51
G
Una raccolta di trucchi da tenere a portata di mouse
048-052:082-083 16-07-2008 10:26 Pagina 51
ht t p: / / www. i opr ogr ammo. i t
ELENCARE LE SOTTOCARTELLE
DI UNA DIRECTORY
using System;
using System.IO;
class DirectorySubfolders
{
public static void Main()
{
string directoryString =
Directory.GetCurrentDirectory();
int i = directoryString.LastIndexOf ('\\');
directoryString = directoryString.Remove (i,
directoryString.Length - i);
Console.WriteLine ("Ler cartelle sotto \"{0}\" sono...",
directoryString);
string[] directories = Directory.GetDirectories (directoryString);
foreach (string directory in directories)
{ Console.WriteLine ("Subdirectory: \"{0}\"", directory); }
}
}
RECUPERARE
LA DIRECTORY CORRENTE
using System;
using System.IO;
class DirectoryCurrent
{
public static void Main()
{
Console.WriteLine ("Directory corrente: \"{0}\"",
Directory.GetCurrentDirectory());
}
}
RICAVARE LO SPAZIO LIBERO
DAI DISCHI CONDIVISI IN RETE
using System;
using System.Management;
class NetworkSpace
{
static void Main(string[] args)
{
SelectQuery query = new SelectQuery(
"select name, FreeSpace from win32_logicaldisk where
drivetype=4");
ManagementObjectSearcher searcher = new
ManagementObjectSearcher(query);
foreach (ManagementObject mo in searcher.Get())
{
Console.WriteLine("Lettera unit: {0}", mo["name"]);
Console.WriteLine("Spazio libero sull':unit {0}",
mo["FreeSpace"]);
}
// Evitare la chiusura involontaria
Console.WriteLine("\nPremi invio per uscire.");
Console.Read();
}
}
MISURARE IL TEMPO DI
ESECUZIONE DI UN PROGRAMMA
DateTime startTime = DateTime.Now;
Console.WriteLine ("Applicazione avviata alle: {0}", startTime);
// Esegue l'applicazione da monitorare
for (int i=1; i < 100000; i++){}
DateTime stopTime = DateTime.Now;
Console.WriteLine ("Applicazione stoppata alle: {0}", stopTime);
TimeSpan elapsedTime = stopTime - startTime;
Console.WriteLine ("Tempo trascorso: {0}", elapsedTime);
Console.WriteLine ("in ore :" + elapsedTime.TotalHours);
Console.WriteLine ("in minuti :" + elapsedTime.TotalMinutes);
Console.WriteLine ("in secondi :" + elapsedTime.TotalSeconds);
Console.WriteLine ("in millisecondi:" +
elapsedTime.TotalMilliseconds);
CONTROLLARE CHE UNA
STRINGA SIA DI SOLI NUMERI
using System.Text.RegularExpressions;
const string ALL_NUMERIC_PATTERN = "[a-z|A-Z]";
static readonly Regex All_Numeric_Regex =
new Regex (ALL_NUMERIC_PATTERN);
static bool AllNumeric ( string inputString )
{
if (All_Numeric_Regex.IsMatch ( inputString ))
{
return false;
}
return true;
}
RIMUOVERE I TAG HTML
DA UN TESTO
using System.Text.RegularExpressions;
const string HTML_TAG_PATTERN = "<.*?>";
static string StripHTML (string inputString)
{
return Regex.Replace
(inputString, HTML_TAG_PATTERN, string.Empty);
}
TIPS&TRICKS M
G
52
/Settembre 2008
Una raccolta di trucchi da tenere a portata di mouse
048-052:082-083 22-07-2008 15:26 Pagina 52
ht t p: / / www. i opr ogr ammo. i t
MOBILE M
G
54
/Settembre 2008
Interfacce grafiche di alto livello
L
a classe Screen (javax.microedition.lcdui.
Screen), con le sue derivate, fornisce tutti gli
strumenti necessari per costruire interfacce
grafiche di alto livello: campi di testo, etichette,
immagini e cos via. Una sorta di ridottissimo AWT
per apparecchi MIDP, per dirla con poche parole.
Bench il nostro interesse sia principalmente rivol-
to alle interfacce di basso livello, quelle ottenibili
estendendo Canvas e Game Canvas, la conoscenza
delle classi derivate da Screen potr lo stesso tor-
narci utile in numerose occasioni, oltre ad aiutarci
nel familiarizzare maggiormente con la program-
mazione dei dispositivi portatili.
LA CLASSE FORM
Tale classe (javax.microedition.lcdui.Form),
che gi abbiamo impiegato negli esempi
mostrati nelle puntate precedenti, offre un con-
tenitore all'interno del quale possibile intro-
durre, uno dietro l'altro, gli elementi per
l'interazione con l'utente. Possiamo scegliere
fra due costruttori:
G public Form(String title)
Crea un oggetto Formcon il titolo specificato.
G public Form(String title, Item[] items)
Crea un oggetto Form con il titolo specificato,
contenente gli elementi presenti nell'array for-
nito come secondo argomento.
Item, sulla quale torneremo tra pochissimo, la
classe di base per l'implementazione degli ele-
menti introdotti nel contenitore. Form gestisce
tali elementi mostrandoli in successione, secon-
do la modalit scelta dall'implementazione del
particolare dispositivo in uso. Tutti i metodi
introdotti da Form servono per gestire tali ele-
menti e gli eventi ad essi collegati:
G public int append(Item item)
Aggiunge un nuovo elemento al contenitore.
G public int append(String str)
Aggiunge un nuovo elemento al contenitore,
creandolo automaticamente a partire da una
stringa.
G public int append(Image img)
Aggiunge un nuovo elemento al contenitore,
creandolo automaticamente a partire da
un'immagine.
G public void insert(int itemNum, Item item)
Inserisce un elemento all'interno del conteni-
tore, disponendolo alla posizione itemNum e
traslando in avanti tutti gli altri elementi even-
tualmente gi presenti a partire dalla posizione
indicata.
G public void delete(int itemNum)
Elimina l'elemento alla posizione itemNum.
G public void deleteAll()
Elimina tutti gli elementi presenti nel conteni-
tore.
G public void set(int itemNum, Item item)
Imposta l'elemento alla posizione itemNum,
rimpiazzando un altro elemento eventual-
mente gi presente allo stesso indice.
G public Item get(int itemNum)
Restituisce l'elemento alla posizione item
Num.
G public int size()
Restituisce il numero degli elementi presenti
nel contenitore.
G public void setItemStateListener (ItemState
Listener iListener)
Imposta uno ItemStateListener per il conte-
nitore, rimpiazzando quello eventualmente
gi presente. Se l'argomento fornito null, il
listener eventualmente gi presente viene
rimosso.
Conoscenze richieste
Rudimenti di Java
Software
JDK, JWT, Eclipse
Impegno
Tempo di realizzazione
REQUISITI
VIDEOGIOCHI IN JAVA
PER CELLULARI (quarta parte)
DOPO AVER INTRODOTTO I PRINCIPI DI PROGRAMMAZIONE DELLE MIDLET, IL CORSO PROSEGUE
ILLUSTRANDO I COMPONENTI GRAFICI DI ALTO LIVELLO, INDISPENSABILI IN QUALSIASI
APPLICAZIONE MIDP: ETICHETTE, BOTTONI E GESTIONE DELLE IMMAGINI
J CD J WEB
videogiochi_per_cellulari_04.zip
cdrom.ioprogrammo.it
054-059:032-035 16-07-2008 9:36 Pagina 54
Ricordiamo che Form estende Screen e imple-
menta, oltre ai metodi appena descritti, anche
quelli richiesti dall'interfaccia Displayable (cfr.
lezione precedente).
La classe astratta Item (javax.microedition.lcdui.
Item) definisce le funzionalit comuni a tutti gli
elementi che possono essere inseriti in un conte-
nitore. Fra i suoi metodi i pi essenziali sono:
G public void setLabel(String label)
Imposta un'etichetta per l'elemento. Con argo-
mento null si specifica di non abbinare
un'etichetta all'elemento.
G public String getLabel()
Recupera l'etichetta dell'elemento. Restituisce
null se nessuna etichetta associata all'ele-
mento.
G public void setLayout(int layout)
Imposta la direttiva di layout per il posiziona-
mento dell'elemento sullo schermo
Disponibile a partire da MIDP 2.0.
G public int getLayout()
Restituisce la direttiva di layout per il posizio-
namento dell'elemento sullo schermo.
Disponibile a partire da MIDP 2.0.
G public void addCommand(Command cmd)
Aggiunge un comando specifico per l'ele
mento. Disponibile a partire da MIDP 2.0.
G public void removeCommand(Command cmd)
Rimuove uno fra i comandi specifici dell'ele-
mento. Disponibile a partire da MIDP 2.0.
G public void setDefaultCommand(Command
cmd)
Imposta il comando predefinito per
l'elemento, che il dispositivo render facilmen-
te accessibile quando l'elemento in uso.
Il comando specificato viene aggiunto alla lista
dell'elemento, senza che ci sia bisogno di chia-
mare anche addCommand(). Se l'argomento
null, il comando predefinito eventualmente gi
presente viene annullato. Quando un coman-
do predefinito annullato, perch rimpiazzato
da un nuovo comando o perch l'argomento
null, questo non rimosso dalla lista dei
comandi collegati all'elemento: perde sempli-
cemente il suo status di comando predefinito.
Disponibile a partire da MIDP 2.0.
G public void setItemCommandListener(Item
Com mandListener l)
Imposta un ItemCommandListener per il conte-
nitore, rimpiazzando quello eventualmente gi
presente. Se l'argomento fornito null, il liste-
ner eventualmente gi presente viene rimosso.
Disponibile a partire da MIDP 2.0.
A partire da MIDP 2.0 stata aggiunta la possibi-
lit di associare dei comandi direttamente a un
elemento, anzich al form che lo contiene.
Inoltre, diventato possibile controllare il layout
dell'elemento con delle apposite direttive.
Per quanto riguarda i comandi, tutto funziona
come per quelli associati ad un oggetto Form(cfr.
lezione precedente), con l'unica differenza che
saranno visualizzati solo quando l'elemento cui
fanno riferimento selezionato ed attivo. Nei
prossimi paragrafi torneremo sull'argomento,
mettendo in pratica degli esempi. Per quanto
riguarda il layout, Item definisce le seguenti
costanti statiche:
G Item.LAYOUT_DEFAULT
Un valore che identifica la regola di posiziona-
mento predefinita.
G Item.LAYOUT_LEFT
Allineamento orizzontale a sinistra.
G Item.LAYOUT_RIGHT
Allineamento orizzontale a destra.
G Item.LAYOUT_CENTER
Allineamento orizzontale al centro.
G Item.LAYOUT_TOP
Allineamento verticale in alto.
G Item.LAYOUT_BOTTOM
Allineamento verticale in basso.
G Item.LAYOUT_VCENTER
Allineamento verticale al centro.
G Item.LAYOUT_NEWLINE_BEFORE
Indica che l'elemento deve essere posizionato
all'inizio di una nuova riga.
G Item.LAYOUT_NEWLINE_AFTER
Indica che l'elemento successivo dovr essere
posizionato all'inizio di una nuova riga.
G Item.LAYOUT_SHRINK
L'elemento pu essere ridotto alla sua minima
larghezza.
G Item.LAYOUT_VSHRINK
L'elemento pu essere ridotto alla sua minima
altezza.
G Item.LAYOUT_EXPAND
ht t p: / / www. i opr ogr ammo. i t
M
MOBILE
Settembre 2008/
55
G
Interfacce grafiche di alto livello
NOTA
MIDP JAVADOC
Ora che si sta iniziando a
lavorare con le API di Java
ME, in particolare con
quelle di MIDP, un po di
documentazione javadoc
fa sempre comodo.
Il vostro WTK contiene i
javadoc di numerose
librerie collegate alla
piattaforma. Quelli per
MIDP li trovate ad un
percorso del tipo:
<DIRECTORY DEL
WTK>/docs/api/midp
054-059:032-035 16-07-2008 9:36 Pagina 55
ht t p: / / www. i opr ogr ammo. i t
MOBILE M
G
56
/Settembre 2008
Interfacce grafiche di alto livello
L'elemento pu essere espanso sino ad occu-
pare orizzontalmente tutto lo spazio disponi-
bile.
G Item.LAYOUT_VEXPAND
L'elemento pu essere espanso sino ad occu-
pare verticalmente tutto lo spazio disponibile.
G Item.LAYOUT_2
Un valore per indicare che sull'elemento si
stanno usando le regole di allineamento di
MIDP 2.0, e non le pi semplificate di MIDP
1.0.
Tutti questi valori, quando non sono in conflitto
fra loro, possono essere combinati con
l'operatore binario | (OR). Ad esempio:
Item.CENTER | Item.VCENTER
Questa combinazione genera una direttiva di
allineamento al centro, sia in posizione orizzon-
tale sia in posizione verticale. Tra qualche para-
grafo vedremo un'applicazione concreta di que-
ste direttive.
Altre tre costanti, comprese nella classe Item,
sono Item.PLAIN, Item.HYPERLINK e Item. BUT-
TON. Anche queste saranno trattate a breve.
LINTERFACCIA
ITEMCOMMANDLISTENER
L'interfaccia ItemCommandListener (javax.mi -
croe di tion.lcdui.ItemCommandListener), introdot-
ta da MIDP 2.0, simile a CommandListener (cfr.
lezione precedente), ma specializzata per gestire
i comandi collegati ad uno specifico elemento
anzich al suo contenitore. Il solo metodo richie-
sto da ItemCommandListener :
G public void commandAction(Command c, Item
item)
Il primo argomento il comando attivato,
mentre item l'elemento sul quale stato atti-
vato.
LA CLASSE STRINGITEM
StringItem (javax.microedition.lcdui.StringItem)
un elemento che mostra del testo all'utente.
A partire da MIDP 2.0 l'elemento supporta diver-
se modalit di visualizzazione. La classe offre
due costruttori:
G public StringItem(String label, String text)
Costruisce uno StringItem di testo semplice
con etichetta label (null per nessuna etichetta)
e contenuto text.
G public StringItem(String label, String text, int
appearanceMode)
Costruisce uno StringItem con etichetta label
(null per nessuna etichetta) e contenuto text.
In pi, permette di definire una modalit di
visualizzazione (appearanceMode). Disponibile
a partire da MIDP 2.0.
L'argomento appearanceMode pu essere:
G Item.PLAIN
Testo semplice.
G Item.HYPERLINK
Collegamento ipertestuale.
G Item.BUTTON
Bottone.
Il valore di appearanceMode definisce il modo di
apparire dell'elemento, ma non ne influenza il
grado dinterattivit: uno StringItemcon
appearanceMode pari a Item.BUTTONnon auto-
maticamente un bottone, ma soltanto uno
StringItem che il dispositivo disegner come
fosse un bottone. L'apparenza inganna! Per ren-
dere effettivamente l'elemento un bottone,
oppure un collegamento ipertestuale (Item.
HYPERLINK), necessario associargli un'azione
mediante un comando predefinito.
I metodi offerti, oltre a quelli di Item, sono:
G public String getText()
Recupera il testo contenuto nell'elemento.
G public void setText(String text)
Imposta il testo contenuto nell'elemento.
G public int getAppearanceMode()
Restituisce il modo di apparire dell'elemento
(Item.PLAIN, Item.HYPERLINK o Item.BUTTON).
Disponibile a partire da MIDP 2.0.
G public void setFont(Font font)
Imposta il Font dell'elemento. Disponibile a
partire da MIDP 2.0.
G public Font getFont()
Recupera il Font dell'elemento. Disponibile a
partire da MIDP 2.0.
Sulla classe Font torneremo tra qualche lezione.
Esempio 1
Il seguente esempio introduce diversi StringItem
NOTA
QUALE VERSIONE
DI MIDP?
Allindirizzo
http://www.club-
java.com/TastePhone/J2M
E/MIDP_mobile.jsp
troverete uninteressante
lista, in continuo
aggiornamento, che
abbina a ogni modello di
cellulare la versione di
MIDP supportata.
054-059:032-035 16-07-2008 9:36 Pagina 56
ht t p: / / www. i opr ogr ammo. i t
in un solo contenitore, in modo da dimostrare le
funzionalit sinora discusse. L'esempio orga-
nizzato in due classi da inserire all'interno del
medesimo package mypackage. La prima di que-
ste classi StringItemDemoForm, che estende
Forme utilizza StringItem:
package mypackage;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import
javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.lcdui.StringItem;
public class StringItemDemoForm extends Form
implements ItemCommandListener {
private StringItem plainStringItem;
private StringItem hyperlinkStringItem;
private StringItem buttonStringItem;
private StringItem outputStringItem;
private Command hyperlinkCommand;
private Command buttonCommand;
public StringItemDemoForm() {
super("StringItemDemo");
plainStringItem = new
StringItem("Elemento 1",
"Questo
uno StringItem PLAIN", Item.PLAIN);
hyperlinkStringItem = new
StringItem("Elemento 2",
"Questo
uno StringItem HYPERLINK", Item.HYPERLINK);
hyperlinkCommand = new
Command("Prova link", Command.ITEM, 1);
hyperlinkStringItem.setDefaultCommand(hyperlink
Command);
hyperlinkStringItem.setItemCommandListener(this);
buttonStringItem = new
StringItem("Elemento 3",
"Questo
uno StringItem BUTTON", Item.BUTTON);
buttonCommand = new
Command("Prova bottone", Command.ITEM, 1);
buttonStringItem.setDefaultCommand(button
Command);
buttonStringItem.setItemCommandListener(this);
outputStringItem = new
StringItem("Output", "", Item.PLAIN);
append(plainStringItem);
append(hyperlinkStringItem);
append(buttonStringItem);
append(outputStringItem);
}
public void commandAction(Command c,
Item item) {
if (c == hyperlinkCommand) {
outputStringItem.setText("Hai azionato il link");
} else if (c == buttonCommand)
{
outputStringItem.setText("Hai azionato il bottone");
}
}
}
Il form realizzato contiene quattro StringItem: il
primo ha aspetto Item.PLAIN, il secondo
Item.HYPERLINK e il terzo Item.BUTTON, mentre
il quarto usato per emettere dell'output quan-
do vengono attivati i comandi associati al link e
al bottone. Per far funzionare lesempio neces-
sario disporre di una MIDlet che inserisca il
form nel display del cellulare. Per questo andia-
mo a realizzare la classe StringItemDemo MIDlet:
package mypackage;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.midlet.MIDlet;
public class StringItemDemoMIDlet extends MIDlet
implements CommandListener {
private Display display;
private Command exit;
private Form form;
public StringItemDemoMIDlet() {
display =Display.getDisplay(this);
exit = new Command("Esci",
Command.EXIT, 1);
form = new StringItemDemoForm();
form.addCommand(exit);
form.setCommandListener(this);
}
protected void startApp() {
display.setCurrent(form);
}
protected void pauseApp() {
}
protected void destroyApp(boolean
unconditional) {
}
public void commandAction(Command c,
Displayable d) {
if (c == exit) {
M
MOBILE
Settembre 2008/
57
G
Interfacce grafiche di alto livello
054-059:032-035 16-07-2008 9:36 Pagina 57
ht t p: / / www. i opr ogr ammo. i t
destroyApp(true);
notifyDestroyed();
}
}
}
Lanciate la MIDlet in un emulatore o in un
dispositivo compatibile con MIDP 2.0. Dovreste
ottenere un risultato estremamente simile a
quello mostrato in Fig.1.
LELEMENTO
IMAGEITEM
ImageItem (javax.microedition.lcdui. ImageItem) fa
da involucro ad un'immagine da mostrare sul
display del dispositivo. Sono offerti due costrut-
tori:
G public ImageItem(String label, Image img, int
layout, String altText)
Crea un ImageItemcon etichetta label (null per
nessuna etichetta) ed immagine contenuta
img. L'argomento layout serve per posizionare
l'immagine rispetto agli altri elementi che la
contornano, e deve essere elaborato combi-
nando le costanti idonee della classe Item. La
stringa altText imposta un testo alternativo
all'immagine, nel caso questa non possa esse-
re visualizzata (ad esempio perch il display
non supporta le propriet dell'immagine for-
nita).
G public ImageItem(String label, Image image, int
layout, String altText, int appearanceMode)
Con questo costruttore inoltre possibile spe-
cificare come l'elemento dovr apparire.
Valgono tutte le considerazioni gi fatte per gli
elementi StringItem. Disponibile a partire da
MIDP 2.0.
Di immagini, in futuro, se ne parler abbondan-
temente. Per ora accontentatevi di qualche pic-
cola anticipazione. La classe Image (javax.mi -
croedition.lcdui.Image) fa da involucro ad un'
immagine bitmap.
Le immagini possono essere caricate servendosi
del metodo:
G public static Image createImage(String name)
throws IOException
Il parametro fornito il percorso del file, relati-
vamente all'applicazione.
Fate attenzione al fatto che un dispositivo pu
gestire il proprio file system in maniera case-sen-
sitive, cio facendo distinzione tra lettere minu-
scole o maiuscole. Per questo motivo, dopo aver
dato un nome a un file, invocatelo nel codice
delle vostre applicazioni senza scambiare minu-
scole e maiuscole. Le immagini vanno deposita-
te nella cartella res di un progetto del WTK o di
EclipseME (cfr. prima e seconda lezione), o in
una sua sottocartella. Limmagine potr poi esse-
re caricata alla seguente maniera:
Image img =
Image.createImage("/nome_immagine.png");
oppure:
Image img =
Image.createImage("/sottocartella/nome_immagine.
png");
I formati supportati dipendono dal peculiare
dispositivo in uso. L'unico formato espressa-
mente richiesto da MIDP 2.0 PNG, e quindi
conviene non fare uso di altri formati. Il metodo
lancia una java.io.IOException nel caso venga
riscontrato un problema durante il recupero o la
decodifica del file.
I metodi offerti da ImageItem, oltre a quelli eredi-
tati da Item, sono:
G public void setImage(Image img)
Imposta l'immagine.
G public Image getImage()
Restituisce l'immagine.
G public void setAltText(String text)
Imposta il testo alternativo associato all'imma-
gine.
MOBILE M
G
58
/Settembre 2008
Interfacce grafiche di alto livello
Fig. 1: L'applicazione StringItemDemo in azione in
un emulatore.
054-059:032-035 16-07-2008 9:36 Pagina 58
http://www.ioprogrammo.it
G public String getAltText()
Restituisce il testo alternativo associato all'im-
magine.
G public int getAppearanceMode()
Restituisce il modo di apparire dell'elemento
(Item.PLAIN, Item.HYPERLINK o Item.BUTTON).
Disponibile a partire da MIDP 2.0.
Esempio 2
Dimostriamo lutilizzo degli oggetti ImageItem
attraverso un esempio pratico. Per prima cosa
avremo bisogno di un'immagine PNG. Tra i codi-
ci allegati allarticolo trovate unimmagine gi
pronta. In alternativa potete realizzarla da voi,
come meglio vi piace. In caso chiamatela test.png,
fate in modo che le sue dimensioni siano adatte
al display di un dispositivo portatile e andate a
posizionarla nella cartella res di un progetto
appositamente creato con il WTK o con
EclipseME. La MIDlet di esempio mypack-
age.ImageItemDemoMIDlet:
package mypackage;
import java.io.IOException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.ImageItem;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemCommandListener;
import javax.microedition.midlet.MIDlet;
public class ImageItemDemoMIDlet extends MIDlet
implements CommandListener,
ItemCommandListener {
private Display display;
private Command exit;
private Command layout1;
private Command layout2;
private Command layout3;
private ImageItem imageItem;
private Form form;
public ImageItemDemoMIDlet() throws
IOException {
display = Display.getDisplay(this);
exit = new Command("Esci",
Command.EXIT, 1);
layout1 = new Command("A
sinistra", Command.ITEM, 1);
layout2 = new Command("Al
centro", Command.ITEM, 1);
layout3 = new Command("A
destra", Command.ITEM, 1);
Image img =
Image.createImage("/test.png");
imageItem = new ImageItem("Immagine", img,
Item.LAYOUT_DEFAULT, "Test");
imageItem.addCommand(layout1);
imageItem.addCommand(layout2);
imageItem.addCommand(layout3);
imageItem.setItemCommandListener(this);
form = new Form("ImageItemDemo");
form.addCommand(exit);
form.append(imageItem);
form.setCommandListener(this); }
protected void startApp() {
display.setCurrent(form); }
protected void pauseApp() {}
protected void destroyApp(boolean
unconditional) {}
public void commandAction(Command c,
Displayable d) {
if (c == exit) { destroyApp(true);
notifyDestroyed();
}
}
public void commandAction(Command c,
Item item) {
if (c == layout1) {
imageItem.setLayout(Item.LAYOUT_LEFT);
} else if (c == layout2) {
imageItem.setLayout(Item.LAYOUT_CENTER);
} else if (c == layout3) {
imageItem.setLayout(Item.LAYOUT_RIGHT);
}
}
}
Avviando la MIDlet ed utilizzando i comandi del-
lemulatore o del cellulare in uso possibile
modificare lallineamento lungo lo schermo del-
limmagine caricata.
CONCLUSIONI
Come dimostrato oggi, le interfacce di alto livello
di MIDP sono semplici e piacevoli da maneggia-
re. Costruire applicazioni per cellulari non poi
cos complicato, vero? In questa lezione, dopo
aver introdotto i concetti di base, ci siamo limita-
ti allanalisi di etichette, bottoni ed immagini.
Nel prossimo incontro proseguiremo la trattazio-
ne, esaminando alcuni componenti lievemente
pi complessi, come i campi per limmissione
del testo e delle date, i bottoni di selezione, le
barre di progresso e cos via. Nulla di troppo
complicato, ad ogni modo. A quel punto saremo
veramente pronti per immergerci ancora di pi
in Java ME, per imparare come manipolare la
grafica ad un pi basso livello. Non mancate!
Carlo Pelliccia
M
MOBILE
Settembre 2008/
59
G
Interfacce grafiche di alto livello
054-059:032-035 16-07-2008 9:36 Pagina 59
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
60
/Settembre 2008
Lutilizzo di Crystal Reports in VB.NET
M
icrosoft fornisce, allinterno di Visual
Studio.NET, un tool di grande qualit
per la reportistica. Si tratta di Crystal Re-
ports che, come viene illustrato nellarticolo, per-
fettamente integrato in Visual Basic.NET, consen-
tendo di gestire con facilit le stampe allinterno
delle applicazioni che sviluppate.
Una degli aspetti pi interessanti di Visual Ba-
sic.NET , infatti, la possibilit di costruire report
con semplicit, utilizzando uno strumento che dal-
la versione 6.0 fa parte dellambiente di sviluppo.
Crystal Reports un prodotto di facile utilizzo che
consente di creare report personalizzati, elenchi e
prospetti di stampa di vario tipo utilizzando le
informazioni contenute allinterno di un databa-
se. Il funzionamento si basa sulla creazione di con-
nessioni con uno o pi database e sullutilizzo di que-
sti link per ricavare valori dai campi dei database
selezionati, che possono poi essere inseriti nei re-
port.
Lobiettivo principale di questo articolo quello
di illustrare lutilizzo di Crystal Reports in ambiente
Visual Basic. Esistono, infatti, degli appositi ActiveX
che consentono di attivare da unapplicazione VB
uno o pi report.
DESTINATARI
DEL REPORT
I report sono strumenti di supporto alle decisioni
e destinati a chiunque debba gestire qualcosa.
Il loro principale obiettivo consiste nel permette-
re agli utenti di apprendere rapidamente gli ele-
menti e le relazioni fondamentali esistenti tra i da-
ti, in modo che sia possibile prendere decisioni ap-
propriate. La validit del report dipende dalla pre-
sentazione logica di dati corretti, proprio perch
un report che contiene informazioni presentate in
maniera non chiara o, addirittura, errate non solo
pu rallentare il processo decisionale, ma pu con-
durre a conclusioni sbagliate. Se, ad esempio, il di-
rettore commerciale di unazienda desume, da uno
o pi report errati, che il volume delle vendite ha un
trend crescente pu ritenere necessaria una poli-
tica dinvestimenti e di costi ben differente se aves-
se ricevuto dati veritieri sullattuale realt azien-
dale.
Prima di creare un report consigliabile identificarne
brevemente per iscritto gli obiettivi, in maniera ta-
le da poter realizzare uno strumento che persegua
proprio quanto definito in fase di analisi. In questa
fase sar necessario spendere un po di tempo con
chi ci ha commissionato il lavoro per evitare di
prendere cantonate. Ad esempio lobiettivo del re-
port pu essere:
1. La visualizzazione delle vendite mensili ed annuali
per agente di vendita, paragonare le cifre del-
lanno corrente con quelle dellanno preceden-
te e contrassegnare gli agenti con valori delle
vendite che non corrispondono agli standard
societari.
2. La visualizzazione delle attivit di vendita per
ogni voce dellinventario e la definizione del pun-
to di riordino delle quantit in base a tale atti-
vit.
3. Il calcolo e la successiva visualizzazione delle
ammonizioni e delle espulsioni per ogni squa-
dra che partecipa al campionato di calcio di se-
rie A e B.
Dopo la definizione dellobiettivo importante ca-
pire chi sono gli effettivi destinatari del nostro la-
voro. Un singolo report viene solitamente utiliz-
zato da pi persone. Tornando al caso delle ven-
dite, un report dettagliato sulle vendite potrebbe es-
sere utile agli agenti di vendita, ai responsabili di area
e magari anche al direttore generale, anche se ognu-
no potrebbe essere interessato ad aspetti diversi.
KICK OFF
DEL PROGETTO
La prima operazione da effettuare durante la fase
di creazione di un report quella di attivare VB.NET,
per poi fare clic sul menu File-New-Project, sele-
CREARE REPORT CON
VISUAL BASIC.NET
IN QUESTO ARTICOLO SPIEGHEREMO COME UTILIZZARE IL TOOL DEDICATO ALLA
REPORTISTICA FORNITO CON VISUAL STUDIO: CRYSTAL REPORTS. VEDREMO LA STRUTTURA
DI UN REPORT E COME INTEGRARE LO STESSO ALLINTERNO DI UNA NOSTRA APPLICAZIONE
J CD J WEB
vbreport.zip
cdrom.ioprogrammo.it
Conoscenze richieste
Visual Studio e VB.NET
Software
Windows XP Service
Pack 2, Windows
Server 2003 o
Windows Vista e
Visual Studio 2005
versione Standard o
Professional
Impegno

Tempo di realizzazione
REQUISITI
060-066:072-080 16-07-2008 9:44 Pagina 60
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
61
G
Lutilizzo di Crystal Reports in VB.NET
zionare Windows Application nella sezione Tem-
plates, digitare il nome dellapplicazione in Name
e, poi, fate sul pulsante OK. Successivamente, facendo
clic destro nella finestra 7sul nome del progetto,
scegliere Add, poi New Iteme, nella finestra Add
New Item, scegliete Crystal Reports. A questo pun-
to compare automaticamente il wizardCrystal Re-
ports Gallery dove si possono scegliere le seguen-
ti opzioni:
G Using the Report Wizard, per creare un report in
maniera guidata ed ex-novo.
G As a Blank Report, per generare un report vuo-
to, senza alcun campo, n connessioni a data-
base.
G From an Existing Report, per effettuare una co-
pia di un report gi creato in precedenza.
In questa esemplificazione utilizzerete la prima
opzione. Il Report Wizard permette di procedere
in maniera guidata partendo dalla conessione al
database. Nella sezione Data selezionate Create
New Connection e fare clic su OLE DB (ADO) per
connettervi immediatamente ad un database ser-
ver come Microsoft SQL Server o Oracle, sceglien-
do, poi, nella finestra di dialogo che appare Mi-
crosoft OLE DB Provider for SQL Server. Quindi in-
dicate il nome del computer su cui risiede il data-
base, se la macchina corrente basta digitare lo-
calhost, utente e password e infine il nome della
fonte dati, ossia del database. A questo punto
lorigine dei dati disponibile ed necessario in-
dicare gli oggetti da inserire nel report, che posso-
no essere tabelle, viste o stored procedure.
La successiva sezione Link rappresenta grafica-
mente i collegamenti tra gli oggetti selezionati in ba-
se alle varie chiavi primarie e straniere presenti
sulle tabelle. Qui necessario eliminare i link sba-
gliati o che non sono necessari per la costruzione
del report finale. Inoltre anche possibile verifi-
care quali indici sono presenti grazie alla legenda
attivabile con il pulsante Index Legend.
Nella successiva sezione Fields si indicano i cam-
pi da includere nel report, che solitamente sono
solo una parte di quelli presenti nelle tabelle sele-
zionate.
In seguito, nella sezione Grouping, individuare le
cosiddette Group By per raggruppare i dati secon-
do determinati campi. Facendo clic sul pulsante
Next si passa alla sezione Summaries, in cui ven-
gono individuati i campi di riepilogo e cio quelli
che vengono sommati in base ai criteri di rag-
gruppamento. Nella sezione Group Sorting i grup-
pi sono ordinati in base ai totali di riepilogo.
Avete, poi, la possibilit dinserire un grafico che
pu essere a barre verticali, a linee orizzontali o a
torta.
Nella successiva schermata, Record Selection, po-
tete filtrare le informazioni, selezionando un sot-
toinsieme dei campi presenti nel database, grazie
alla combo box posta a sinistra in basso; l si pu,
ad esempio, specificare che devono essere visualizzati
solo i computer con scadenza inferiore o uguale
al 31 dicembre 2008 (data digitata sulla seconda
combo box, che appare in seguito).
Infine, la sezione conclusiva Report Style permet-
te di scegliere il modello da utilizzare per visualiz-
zare il report tra dieci differenti alternative. A destra
il wizard Crystal Reports visualizza ogni volta
lanteprima di ci che state scegliendo.
NOTA
UNA VERA
E PROPRIA
JOINT VENTURE
Crystal Reports un
prodotto con copyright
Crystal Decisions ed dal
1992 che diventato lo
strumento per la creazione
di report pi utilizzato su
sistemi operativi Microsoft
Windows. Questa
collaborazione tra
Microsoft e Crystal
Decisions continuata fino
ai nostri giorni, anche
dopo lacquisizione da
parte di Business Objects
di Crystal Decisions.
Fig. 1: Selezione del componente Crystal Reports da
aggiungere al nostro progetto.
Fig. 2: Il wizard consente di selezionare il database di
riferimento.
Fig. 3: Le relazioni tra le tabelle utili al vostro report pos-
sono essere modificate.
060-066:072-080 16-07-2008 9:44 Pagina 61
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
62
/Settembre 2008
Lutilizzo di Crystal Reports in VB.NET
OGGETTI
DI CRYSTAL REPORTS
La finestra di progettazione di ciascun report, de-
nominata per default CrystalReport1.rpt, simile a
una form di Visual Basic, include una finestra di
progettazione nella quale viene creato il layout del
report. Essa, inoltre, composta dagli oggetti ri-
portati di seguito:
Section. Ciascuna sezione della finestra di proget-
tazione Crystal Reports rappresentata da un og-
getto Section. In fase di progettazione, ogni sezio-
ne rappresentata da unintestazione, su cui potete
fare clic per selezionare la sezione, e da un riqua-
dro in cui possibile inserire e posizionare con-
trolli. Tramite questo oggetto, e le relative propriet,
possibile riconfigurare un report in modo dina-
mico prima delleffettiva creazione.
Controlli di Crystal Reports. Si tratta di controlli spe-
ciali che funzionano soltanto nella finestra di pro-
gettazione Crystal Reports. In questultima fine-
stra non possibile utilizzare i controlli intrinseci
di Visual Basic o anche controlli ActiveX. I controlli
specifici di Crystal Reports sono inclusi nella ca-
sella degli strumenti di Visual Basic nella scheda
Crystal Reports. In particolare, quando in un pro-
getto si aggiunge una finestra di progettazione di un
report, nella nuova scheda Crystal Reports della
casella degli strumenti vengono aggiunti automa-
ticamente i seguenti controlli:
G Text Object, che consente di formattare testo.
G Line Object. Consente di disegnare righe nel re-
port per contraddistinguere in modo pi chiaro
le varie sezioni.
G Box Object. Consente di inserire nel report ret-
tangoli, cerchi e ovali.
I DATI DA INCLUDERE
Lintestazione non deve venire trascurata, in quan-
to contiene le informazioni necessarie allidenti-
ficazione del report stesso. In particolare dovreste
sempre includere i seguenti elementi: nome del-
lente responsabile del report, titolo ed eventualmente
anche gli obiettivi del report.
Il numero di pagina, invece, dovrebbe sempre fa-
re parte del pi di pagina come anche il termine
confidenziale se necessario e la data e lora del
report.
I tipi di dati che si possono includere in un report
prodotto con Crystal Reports sono i seguenti:
1. Provenienti da campi di un oggetto (tabella, vi-
sta, ecc) di un database e sono quelli pi diffusi.
2. Calcolati ricavandoli in parte da campi di data-
base.
3. Digitati direttamente dallautore in caselle di te-
sto (intestazioni, etichette, note e cos via).
Un altro concetto da tenere presente il raggrup-
pamento delle informazioni. Non una novit, in
quanto presente nel linguaggio SQL ed un mo-
do molto potente che potete utilizzare per creare dei
gruppi di record in base al cliente, alla data o a qual-
siasi altro criterio. A rottura del gruppo potrete in-
serire dati calcolati, tipicamente percentuali, to-
tali parziali/generali o medie.
LE SEZIONI
DI CIASCUN REPORT
Osservando un report possibile distinguere al-
meno sette sezioni che potete utilizzare in fase di
progettazione. Si tratta di aree di default che sono
destinate a contenere i dati e le intestazioni del re-
port. Tutte le aree possono contenere controlli per-
sonalizzati prelevati dalla toolbox e, quindi, de-
scrizioni statiche, dati estratti dai database collegati
e immagini grafiche.
Report Header. E una sezione che pu contenere il
titolo del report e magari unimmagine grafica che
rende pi piacevole il prospetto di stampa.
Page Header. Contiene le intestazioni che vengo-
no ripetute ogni volta che avviene un salto pagi-
na.
Group Header Section1. Qui si deve indicare il cam-
po (o i campi) che fa parte della tabella master.
Details. Nella sezione corrente vengono specifica-
ti i campi che sono presenti nella tabella detail. Ad
esempio si possono considerare le due tabelle Pub-
lishers e Titles, che sono relazionate tra loro tra-
mite il campo PubID. Infatti le tabelle sono legate
con una relazione uno a molti. Ci significa che
per ogni record della tabella master Publishers so-
no presenti uno o pi record sulla tabella detail Ti-
tles.
Group Footer Section1. Qui vengono specificati
eventuali campi che devono essere riportati alla
NOTA
REPORT
NON CORRELATI
Crystal Reports consente
anche di stampare due o
pi report non correlati tra
loro, luno di seguito
allaltro. Per ottenere ci
necessario creare il report
che sintende stampare
per primo ed inserirlo nella
sezione Details.
Successivamente
importare un report gi
esistente o creare un
subreport e posizionarlo
nella sezione Report
Footer. Gli altri, eventuali
subreport, dovranno
essere inseriti in ulteriori
Report Footer creati con il
Section Expert (tasto
destro del mouse, opzione
di menu Insert Section).
Fig. 4: La finestra di progettazione di Crystal Reports.
060-066:072-080 16-07-2008 9:44 Pagina 62
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
63
G
Lutilizzo di Crystal Reports in VB.NET
fine della visualizzazione degli elementi di ciascun
gruppo.
Report Footer. il cosiddetto pi di pagina del re-
port, ossia lultima sezione del report che viene vi-
sualizzata sullultima pagina dello stesso. In que-
sta area possono venire riportati i totali generali
del report. Se, ad esempio, le tabelle master e detail
fossero rispettivamente banche e conti correnti,
evidente che in questa sezione sarebbe possibile
indicare la formula che effettua la sommatoria de-
gli importi dei saldi relativi a tutte le banche con-
siderate.
Page Footer. Si tratta dellarea del report che viene
ripetuta nella parte inferiore di ogni pagina. Soli-
tamente qui si indica la data e il progressivo della
pagina corrente.
UN REPORT DI SINTESI
Nellesempio presentato con questo articolo vie-
ne incluso il database Access che contiene i dati
caricati dal report. Prodotti.mdb composto da 5
tabelle: 1.OrdineProdotto, che la traduzione del-
la relazione con molteplicit N x M che mette in
collegamento le entit ordine e prodotto. Lunico cam-
po non chiave la quantit di prodotto venduta
per ogni ordine. 2.Ordine, che contiene tutti gli at-
tributi propri (come data dellordine e data di con-
segna) e le chiavi straniere (foreign keys) che la col-
legano alle tabelle Cliente e Venditore. 3.Prodotto,
che contiene la descrizione del prodotto e il costo
unitario. 4.Cliente, che contiene attributi come no-
me di riferimento, fax, indirizzo, ed altri ancora.
5.Venditore, che la tabella relativa alla forza ven-
dita.
Lobiettivo del report che si vuole creare quello
di mettere a confronto le vendite effettuate da cia-
scun agente di vendita, evidenziando una serie di
campi di dettaglio tra cui i prodotti venduti, le
quantit vendute, il prezzo unitario e quello tota-
le (prezzo per quantit). Inoltre si vogliono evi-
denziare anche i seguenti campi calcolati: fattura-
to totale realizzato da ciascun agente di vendita e
totale fatturato realizzato da tutta la forza vendi-
ta.
I destinatari possono essere i responsabili di area,
il direttore commerciale e qualsiasi manager che si
occupa della politica delle vendite aziendale, ma
anche della gestione del personale.
Prima di tutto si deve creare un nuovo progetto di
tipo Windows Application ed inserire sulla form il
controllo CrystalReportViewer. Bisogna, poi, ri-
cordarsi dimpostare a Fill la propriet Dock per
ancorare il controllo a tutti i lati della form cor-
rente e, successivamente, in ReportSource ne-
cessario specificare percorso e nome del report da
visualizzare.
Qualora vogliate utilizzare lo stesso CrystalRe-
portViewer per pi report dovrete impostare la pro-
priet ReportSource dinamicamente da menu o
tramite un pulsante di comando. Il codice che se-
gue serve proprio a fare lo switch tra due report:
Private Sub Cambia_Click(...) Handles
Cambia.Click
Static flgCR As Boolean = False
flgCR = Not flgCR
If Not flgCR Then
CrystalReportViewer1.DisplayGroupTree =
True
Me.Text = "Comparazione delle vendite per
agente"
CrystalReportViewer1.ReportSource =
myCrystalReport1
Else
CrystalReportViewer1.DisplayGroupTree =
False
Me.Text = "Ordini evasi per ogni cliente"
CrystalReportViewer1.ReportSource =
CRcliente
End If
End Sub
Al fine di evitare errori, si ricorda anche che deve es-
sere anche incluso il codice che segue (nellappli-
cazione desempio presente nella sezione gene-
rata automaticamente da Progettazione Windows
Form):
Friend WithEvents myCrystalReport1 As
WindowsApplication2.CrystalReport1
Friend WithEvents CRcliente As
WindowsApplication2.CRcliente
Me.myCrystalReport1 = New
WindowsApplication2.CrystalReport1
Me.CRcliente = New
WindowsApplication2.CRcliente
NOTA
VERIFICARE
IL DATABASE
Eseguendo lapplicazione
allinterno dellambiente di
sviluppo pu accadere che
il report non venga
visualizzato a causa di una
richiesta di login. Per evitare
ci dovete effettuare la
verifica del database su tutti
i report, facendo clic destro
sul report stesso e
scegliendo Database-Verify
database. Nella finestra che
appare fate clic sul piccolo
pulsante corrispondente al
campo Database Name,
selezionate il database di
riferimento, fate clic su
Open e, infine, su Finish.
Al termine dovr comparire
il messaggio The database
is up to date.
Fig. 5: Le sezioni di un report a design time consentono
di definire la logica di elaborazione: intestazioni, raggrup-
pamenti, dati calcolati e non etc.
060-066:072-080 16-07-2008 9:44 Pagina 63
ht t p: / / www. i opr ogr ammo. i t
Aggiungere un componente Crystal Report come
spiegato in precedenza e procedete allutilizzo del
wizard individuando passo dopo passo tutte le op-
zioni che interessano. In particolare si deve sce-
gliere un report standard e identificare il database
Prodotti.mdb come quello di riferimento dopo ave-
re fatto clic su File di database. In questo modo si
rendono disponibili tutti gli oggetti del file Access
allapplicazione.
IL WIZARD EXPERT
Nella sezione Links sono ora disponibili i collega-
menti che evidenziano le tabelle master e di dettaglio
ed in generale i vincoli dintegrit referenziale im-
postati sul database. Se volete aggiungere o ri-
muovere collegamenti questa la sede giusta per
farlo. In effetti in questo caso il Report Wizard po-
trebbe aver definito un link tra il campo Region
della tabella Venditore e il campo Region della ta-
bella Cliente che non interessando bene rimuo-
vere. Aggiungete, poi, manualmente un link tra il cam-
po SalesINI della tabella Venditore e il campo SalesI-
NI della tabella Ordine, necessario per collegare la
forza vendita alle altre tabelle del database. Suc-
cessivamente individuate i seguenti campi da vi-
sualizzare: Venditore.Lastname, Venditore.Region,
Ordine.Shipping Date, Cliente.Contact Name,
Cliente.City, Cliente.Contract Date, Prodotto.Product
Description, Prodotto.Unit Price e OrdineProdot-
to.Quantity. Seguendo il wizard potrete impostare
raggruppamenti, ad esempio in questo report nel-
la sezione Group By scegliete Venditore.Lastname
per raggruppare le righe in base al cognome degli
agenti di vendita.
La sezione successiva consente di definire il grafi-
co da visualizzare nel report. Fate clic sullopzio-
ne Bar Chart.
Nella sezione Details aggiungete un campo calco-
lato ottenuto dalla moltiplicazione di Prodotto.Unit
Price per OrdineProdotto.Quantity, al fine di iden-
tificare il fatturato totale di ogni prodotto di una
certa categoria agente per agente. Per inserire cam-
pi calcolati fate clic su Formula Fields nel Field Ex-
plorer, scegliete Newe dopo avere inserito il nome
Prezzo x QTA viene visualizzata la finestra di dia-
logo Formula Editor. Qui necessario scegliere
Prodotto.Unit Price poi tra gli operatori aritmetici
Multiply ed infine OrdineProdotto.Quantity.
Dopo avere salvato le modifiche il nuovo campo
pu essere inserito tra i campi da visualizzare nel
report.
In seguito, facendo clic destro sul grafico, e sce-
gliendo Chart Expert, potete personalizzare il gra-
fico creato con il wizard. In Type scegliete Hori-
zontal mentre in Data impostate Once per report
nel campo Place Chart e a destra lopzione Head-
er. In On change of scegliete Venditore.Lastname e
in Showimpostate Sum of @Prezzo x QTA. In que-
sto modo il grafico in grado di visualizzare un
confronto tra il fatturato realizzato da ogni agente.
Nella sezione Text digitate, Venditore nel campo
Group title e Guadagno realizzato nel campo Da-
ta title.
Nella sezione Group Footer dovete fare clic con il
pulsante destro del mouse e selezionare Insert-
Summary. Nella finestra di dialogo che appare ope-
rate come segue: nella prima casella selezionate
Prezzo x QTA, nella seconda Sume, poi, sceglie-
te OK. In questo modo il campo Prezzo x QTA
verr sommato per dare il fatturato totale della-
gente di vendita. Fate la stessa cosa nella sezione Re-
port Footer per calcolare il fatturato globale della
forza vendita.
A questo punto potete eseguire il report (ricordar-
si della propriet ReportSource) e visualizzare le
informazioni selezionate e presenti nel database
Prodotti.mdb.
Probabilmente sar opportuno procedere ad al-
cune rifiniture, come dimensionare manualmen-
te alcuni campi che risultano troppo piccoli, o po-
sizionarli meglio, inserire le intestazioni e i pi di pa-
gina, e altro ancora.
SISTEMA M
G
64
/Settembre 2008
Lutilizzo di Crystal Reports in VB.NET
Fig. 6: I dati vengono raggruppati in base al campo
Lastname della tabella Venditore.
Fig. 7: Creazione di un campo calcolato con lo strumento
Formula Editor.
SUL WEB
possibile reperire utili
informazioni, consigli e
suggerimenti su Crystal
Reports visitando i
seguenti siti:
www.developers.net
(esempi da scaricare nella
sezione Crystal Reports in
basso a sinistra)
www.businessobjects.co
m/products/reporting/crys
talreports
www.crystalreports.com
www.codeguru.com
(cercare Crystal Reports)
msdn.microsoft.com/
library
(sezione Development
Tools and Languages)
msdn2.microsoft.com/en-
us/vbasic
060-066:072-080 22-07-2008 15:28 Pagina 64
http://www.ioprogrammo.it
IL CONTRIBUTO DI OLE
Per rendere pi significativo il report possibile
inserire oggetti elaborati allinterno di altre appli-
cazioni, quali Microsoft Access o Microsoft Excel.
In particolare la tecnologia OLE consente di otte-
nere molto semplicemente questo risultato.
La prima versione di Object Linking and Embedding
(OLE1) nata da una collaborazione tra Microsoft,
Aldus, Lotus, WordPerfect ed altri produttori di
software, con lobiettivo di rendere disponibile un
meccanismo standard per consentire la gestione
di Documenti Composti (Compound Documents)
in ambiente Windows; le prime realizzazioni di
OLE1 sono apparse gi agli inizi del 1991. Lidea
base di questa tecnologia era quella di consentire
ad unapplicazione (applicazione Client) dincludere
un oggetto generato da unaltra applicazione (ap-
plicazione Server) tramite un particolare riferi-
mento alloggetto da gestire (Object Linking) o in-
corporando loggetto nel formato richiesto dal-
lapplicazione Server allinterno del documento
gestito dallapplicazione Client (Object Embed-
ding).
In questo modo , per esempio possibile, incor-
porare (Embedding) in un prospetto di stampa di
Crystal Reports un foglio elettronico di Excel o con-
nettersi (Linking) ad unapplicazione Server, ad
esempio realizzata con Access. Nel primo caso
loggetto incorporato, essendo solo una copia del-
loriginale, non influenzato dalle modifiche che,
dopo loperazione di embedding, vengono effet-
tuate nellapplicazione Server, mentre nel secon-
do caso le modifiche apportate allinterno del Ser-
ver saranno comunque riflesse anche allinterno
del Client.
Con la successiva introduzione di OLE versione 2
(OLE2) si raffinata la capacit di gestire oggetti
composti e si sono poste le premesse per consen-
tire la realizzazione di un Windows Object Orien-
ted Environment.
Nel caso dellesempio stato incorporato un gra-
fico Excel che, affiancato a quello ottenuto con il
Wizard di Crystal Reports, d una visione anche
delle commissioni che ciascun fornitore ottiene
sui prodotti venduti. Se in sede di stampa non si
pu assolutamente percepire la differenza tra i due
grafici, tuttavia dovrebbe essere chiaro che il se-
condo frutto dellelaborazione effettuata allinterno
di unapplicazione esterna a Crystal Reports, ap-
punto Excel. Procedendo in questo modo ovvia-
mente possibile rendere sempre pi chiari i dati
contenuti nel report.
Ovviamente un oggetto pu essere inserito in Cry-
stal Reports in due modi, ovvero incorporandolo
o collegandolo. In entrambi casi si crea un documento
composto secondo OLE.
Se si utilizza lincorporamento, nel report viene
memorizzata una copia delloggetto originale.
Gli oggetti incorporati non hanno alcun collega-
mento con i relativi oggetti di origine e pertanto
esistono solo nel documento contenitore. Se
sincorpora lo stesso oggetto in report diversi,
loggetto in ogni report non ha alcuna relazione
con gli altri oggetti. Le modifiche apportate ad un
oggetto incorporato non verranno applicate agli
altri oggetti.
Le modifiche apportate ad un oggetto nellappli-
cazione di origine non vengono applicate allog-
getto nellapplicazione contenitore.
Sar quindi necessario aggiornare manualmente
loggetto nellapplicazione contenitore. Ricordate
che tutte le volte che ricorrete a OLE appesantite no-
tevolmente il report, perch un oggetto incorpo-
rato parte integrante del report e pertanto au-
menta in modo considerevole le dimensioni del
filedi riferimento.
Al contrario, se si utilizza il collegamento, nel re-
port viene memorizzata unimmagine dellogget-
to con le informazioni di riferimento, mentre
loggetto vero e proprio rimane memorizzato nel do-
cumento server.
M SISTEMA
Settembre 2008/
65
G
Lutilizzo di Crystal Reports in VB.NET
Fig. 8: Il report a runtime evidenzia il grafico a barre
e i dati cos come selezionati durante la fase di disegno.
Fig. 9: Il secondo grafico presente nel report un ogget-
to OLE.
060-066:072-080 22-07-2008 15:28 Pagina 65
ht t p: / / www. i opr ogr ammo. i t
UTILIZZARE I SUBREPORT
Un subreport un report inserito allinterno di un
report principale e per crearlo bisogna proce-
dere come nel caso di un normale report. Un su-
breport si differenzia dal report principale in
quanto inserito al suo interno come oggetto e
non esiste da solo; pu essere posizionato in
qualsiasi sezione del report e, allinterno di tale
sezione, viene stampato per intero; non pu con-
tenere a sua volta un subreport.
Tipicamente un subreport viene creato per com-
binare report non correlati in un unico prospet-
to di stampa oppure per presentare diverse vi-
sualizzazioni degli stessi dati in un unico report.
Per inserire un subreport basta visualizzare la
form che ospita il report e fare clic destro con il
mouse scegliendo, poi, lopzione di menu Insert-
Subreport. Dopo aver posizionato il subreport
nella sezione opportuna del report principale,
necessario decidere se scegliere un report gi
esistente oppure se crearne uno nuovo con il Re-
port Wizard.
I subreport possono essere collegati oppure no al
report principale. Quelli non collegati sono au-
tonomi: i dati non sono collegati ai dati del re-
port primario in alcun modo.
Tra laltro subreport di questo tipo possono an-
che utilizzare origini di dati completamente di-
verse da quelle del report principale. Al contra-
rio, i subreport collegati son esattamente lopposto,
in quanto i dati sono coordinati tra loro e il pro-
gramma fa corrispondere i record del subreport
a quelli del report principale. Per esemplificare
se si crea un report principale con informazio-
ni sui clienti e un subreport con informazioni
sugli ordini e li si collega, il programma crea un
subreport per ciascun cliente e include anche
tutti gli ordini ad essi relativi.
Nellesempio che vi presentiamo stato creato un
report principale che contiene nome e dati re-
lativi a ciascun venditore, per ciascuno dei qua-
li, grazie ad un subreport, vengono specificati i da-
ti di vendita.
Al fine di collegare report principale e subreport
dovete specificare un campo in entrambi i re-
port in maniera tale che contengano dati comu-
ni. Crystal Reports utilizza tali campi per coordinare
i dati e permette di definirli selezionando Change
Subreport Links nel menu che compare facendo
clic destro sul subreport stesso. A questo punto
necessario evidenziare il campo che si deside-
ra utilizzare come campo di collegamento nel
report principale che lo contiene; fate, poi, clic sul
pulsante con la freccia rivolta verso destra. Il
campo verr aggiunto alla casella di riepilogo
Field(s) to link to e selezionato come campo di
collegamento. Successivamente dovete fare la
stessa cosa per il subreport individuando lo stes-
so campo scelto per il report principale in Sub-
report parameter field to use e i dati da visualiz-
zare nel subreport Select data in subreport based
on field. Queste operazioni devono essere ese-
guite per ciascun collegamento aggiuntivo che
si vuole creare. Al temine scegliere OK.
UNOCCHIATA
AL REPORTVIEWER
Ai pi attenti utilizzatori di Visual Basic.NET non pu
essere sfuggito il controllo ReportViewer. Si tratta
di un ulteriore strumento che Microsoft fornisce
agli sviluppatori per creare report.
Per utilizzare il ReportViewer necessario creare,
al solito, un progetto di tipo Windows Application,
inserire il controllo di riferimento e, infine, creare
una fonte di dati, aggiungendo un nuovo DataSet.
Ricordatevi, poi, di definire la query SQL che co-
stituir il riferimento sorgente per il report finale.
Linterfaccia del ReportViewer simile a quella
delle prime versioni di Crystal Reports. Il maggio-
re punto debole la mancanza di un wizard per la
creazione veloce del prospetto di stampa.
Enrico Bottari
SISTEMA M
G
66
/Settembre 2008
Lutilizzo di Crystal Reports in VB.NET
Fig. 10: Creazione di un report che contiene un subre-
port.
Fig. 11: Il controllo ReportViewer fornisce uno strumento
alternativo a Crystal Reports.
LAUTORE
Enrico Bottari lavora da 18
anni nel mondo ICT.
Ha avuto esperienze
significative nel campo
dello sviluppo software su
piattaforme Microsoft,
dellamministrazione di
database Oracle e della
gestione di sistemi UNIX
Solaris System V.
Attualmente
responsabile delle attivit
operazionali (LAN, Office
Automation e servizi
Desktop) presso la sede
italiana di unimportante
organizzazione
internazionale.
060-066:072-080 16-07-2008 9:44 Pagina 66
ht t p: / / www. i opr ogr ammo. i t
BIBLIOTECA M I migliori testi scelti dalla redazione
Settembre 2008/
67
G
VISUAL C# SPIEGATO A MIA NONNA
U
na guida base alla pro-
grammazione, e in partico-
lare alla programmazione in
Visual C#.NET ormai introdotto
da qualche anno. Un manuale
non per programmatori, bens
per persone curiose che
vogliono entrare nel favoloso
mondo della programmazione
Windows e non dispongono non
solo delle conoscenze tecnologi-
che, ma nemmeno degli stru-
menti teorici. Domande come Cos la programmazione e
a cosa serve o cos una variabile e qual loggetto o il
concetto della vita quotidiana che pi si avvicina a spiegar-
lo, sono tuttaltro che scontate per una persona che non ha
mai frequentato questo mondo. Questo lassunto di base a
cui corrisponde loriginalissima impostazione didattica del
testo. Anche lo stile con il quale il volume stato scritto non
quello pesante dei soliti libri che insegnano un linguag-
gio di programmazione; la narrazione infatti divertente, e
accompagna il lettore nellapprendimento di C#, quasi
come se fosse un libro di narrativa leggera. Lapproccio ci
sembra adatto per chi ha sempre avuto voglia di imparare a
programmare ma allo stesso tempo temeva di avvicinarsi a
materie spiegate con gergo da ingegneri.
Il voluto e ammiccante contrasto tra forma apparentemen-
te elementare e contenuti altamente tecnici invoglia alla let-
tura, e coinvolge, pagina dopo pagina, quasi come se si trat-
tasse di un racconto o un romanzo. In breve, un manuale
entry-level, ideale per studenti di qualsiasi ordine e grado
(dalle scuole secondarie a indirizzo tecnico-scientifico, fino
alle facolt universitarie pertinenti), ma anche per chi si sta
avvicinando alla programmazione per ragioni professionali.
Il libro include anche molti esercizi, che non sono per alle-
gati, ma disponibili solo sul web allindirizzo http://www.
fag.it/booksite/694-3.htm
Autori: Mario De Ghetto Casa Editrice: FAG
ISBN: 978882336948 Pagine: 550 Prezzo: 39,00 Euro
MATLAB GUIDA ALLUSO
L
a parola MATLAB deriva
dalla contrazione di MATrix
LABoratory, fa riferimento al
codice di calcolo sviluppato
verso la fine degli anni '70 pres-
so l'universit americana di
Stanford. Nel corso degli anni
questo pacchetto software si
sempre pi diffuso e perfeziona-
to, fino a diventare, attualmente,
un sistema completo per lo stu-
dio di una grandissima variet
di problemi scientifici. Matlab
deve la sua potenza e diffusione anche ai numerosi toolbox,
ovvero moduli aggiuntivi che ne estendono le funzionalit a
settori specifici, creati nel tempo da utilizzatori e sviluppa-
tori e che consentono anche di effettuare calcoli simbolici.
Questo libro una completa guida alluso del software, pen-
sata per gli utenti inesperti che si avvicinano per la volta al
suo utilizzo, ma si rivela utile anche a chi gi pratico, come
ausilio allo sviluppo delle sue competenze. Il libro struttu-
rato in modo tale che il lettore possa apprendere gradual-
mente le nozioni di base per il corretto utilizzo di MatLab e,
in seguito, tramite la soluzione dei pi diffusi problemi di
calcolo numerico, acquisire padronanza nella gestione della
simulazione numerica di modelli matematici. Il testo vali-
do per qualsiasi versione di MATLAB: gli esempi sono basa-
ti sulla versione 7.x, ma sono compatibili anche con le ver-
sioni precedenti.
Autore: Giuseppe Ciaburro Casa Editrice: FAG
ISBN: 9788882336424 Pagine: 251 Prezzo: 18,90 Euro
COSTRUIRE SITI DINAMICI CON JOOMLA! 1.5
U
na guida semplice e detta-
gliata su Joomla! 1.5, la
nuova release del potente
software Open Source per lo svi-
luppo di siti dinamici che con-
sente di uscire definitivamente
dagli schemi statici dei siti basa-
ti sul semplice HTML. La nuova
versione 1.5 rappresenta una
grande evoluzione rispetto al
passato, perch migliora ulte-
riormente le prestazioni otti-
mizzando lergonomia di lavoro di chi progetta siti web a
vario livello. Lautore accompagna per mano il lettore in
tutte le fasi, in modo da consentire anche ai principianti,
senza alcuna conoscenza di programmazione, di ottenere
risultati immediati e professionali.
Per chi gi utilizza Joomla! 1.0.x, questo libro invece una
valida scorciatoia per conoscere la caratteristiche della
nuova versione partendo da unanalisi chiara e concisa delle
differenze. I sorgenti degli esempi contenuti nel libro sono
disponibili online, allindirizzo:
http://www.hoepli.it/hoeplinformatica
Autori: Roberto Chimenti Casa Editrice: HOEPLI
ISBN: 9788820337131 Pagine: 320 Prezzo: 24,90 Euro
067:014-015 16-07-2008 9:45 Pagina 67
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
72
/Settembre 2008
Utilizzare lAPI ICDBURN di Microsoft Windows
M
asterizzare documenti e file su CD-Rom.
Chiss quante volte abbiamo effettuato
questa operazione. Molti di noi utilizza-
no software appositi, come, ad esempio, il famoso
Nero, in questo articolo vedremo, passo passo, co-
me creare unapplicazione che ci permetter di
masterizzare CD attraverso uninterfaccia total-
mente personalizzata utilizzando un componen-
te di sistema dedicato allo scopo.
Al termine della lettura avremo conosciuto i com-
ponenti software principali che vanno utilizzati
per accedere alle periferiche di masterizzazione
per masterizzare i pi comuni supporti ottici di-
sponibili oggi e, cosa pi importante, avremo im-
parato ad utilizzare componenti esterni al .NET
Framework come gli oggetti COM forniti dal siste-
ma operativo.
LINTERFACCIA ICDBURN
Tutto ruota attorno a un nome: ICDBurn, ovve-
ro cos che si chiama linterfaccia che deve es-
sere implementata per poter utilizzare da codi-
ce le funzionalit di masterizzazione offerteci da
Windows XP. ICDBurn infatti non una inter-
faccia inclusa nel .NET Framework ma, forni-
ta dalle API di Windows XP e, in combinazione
con le IMAPI, permette di gestire la copia di da-
ti su supporti ottici. Tramite .NET possibile im-
portare e utilizzare ICDBurn e la sua shell grafi-
ca per i nostri scopi specifici. Fondamentalmente
linterfaccia ICDBurn fornisce tre funzionalit
principali:
G Individuazione nel sistema dellhardware ne-
cessario per scrivere su supporti ottici
G Determinazione della lettera di unit della pe-
riferica di masterizzazione
G Avvio di una sessione di masterizzazione con
lunit individuata
Per ognuna di queste funzionalit vi un metodo
dedicato allo scopo:
G Burn, per avviare la sessione di masterizzazio-
ne e copiare i file dalla staging area al supporto
ottico scelto
G GetRecorderDriveLetter, fornisce la lettera di unit
della periferica di masterizzazione sulla quale
impostato il flag Enable cd writing on this drive
(Abilita registrazione di CD su questa unit) il
quale non pu essere impostato su pi di una
unit contemporaneamente.
G HasRecordableDrive, cerca nel sistema ununit
di masterizzazione restituendo True se viene tro-
vata
Vediamo pi nel dettaglio il metodo principale
Burn. Questo metodo necessita, per funzionare,
soltanto di un handle alla window principale del-
lapplicazione in modo tale da potersi legare ad es-
sa. Il funzionamento molto semplice e prevede la
copia di tutti i file da masterizzare dalla loro posi-
zione originale alla staging area affinch da qui
possano essere scritti sul supporto. La staging area
non altro che una folder speciale in cui vengono
copiati temporaneamente tutti i file da masterizzare
prima di avviare la copia vera e propria sul sup-
porto. Tipicamente la staging area viene posizio-
nata in:
%userprofile%\Local Settings\Application
Data\Microsoft\CD Burning
ovvero un percorso simile a:
C:\Documents and Settings\<username>\Local
Settings\Application Data\Microsoft\CD Burning
oppure se il sistema operativo in italiano:
C:\Documents and
Settings\<username>\Impostazioni locali\Dati
applicazioni\Microsoft\Masterizzazione CD
Per determinare precisamente qual questa cartella
che, varia in funzione di diversi fattori, quali l'utente
corrente e la lingua di sistema, vanno utilizzati i
MASTERIZZAZIONE
FACILE CON C#
LA VERSATILIT DEL .NET FRAMEWORK PERMETTE, TRA LE ALTRE COSE, ANCHE DI SCRIVERE
DATI SU SUPPORTI OTTICI. VEDIAMO PRATICAMENTE COME REALIZZARE UNAPPLICAZIONE
DI MASTERIZZAZIONE SFRUTTANDO UN COMPONENTE COM INTEGRATO NEL SISTEMA
J CD J WEB
CDBurn.zip
cdrom.ioprogrammo.it
Conoscenze richieste
Conoscenze base di C#
Software
Windows XP Home o
Professional Visual
Studio 2005 o Express
.NET Framework 2.0.
Impegno

Tempo di realizzazione
REQUISITI
072-076:072-080 16-07-2008 9:48 Pagina 72
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
73
G
Utilizzare lAPI ICDBURN di Microsoft Windows
seguenti metodi:
G SHGetSpecialFolderPath, Ritorna il path di una
cartella speciale di Windows dato il suo CSIDL
G SHGetSpecialFolderLocation, Ritorna un pun-
tatore alla struttura ITEMIDLIST della cartella
speciale
G SHGetFolderPathAndSubDir, Dato il CSIDL di
una cartella, ritorna il path della cartella, con-
catenato con il path di una sottodirectory spe-
cificata dallutente.
Dopo questa breve introduzione teorica agli ele-
menti in gioco, passiamo quindi allo sviluppo del-
la nostra applicazione di masterizzazione.
IMPLEMENTAZIONE
Quella che stiamo per creare unapplicazione
Windows Forms. Avviamo Visual Studio 2005 o Vi-
sual Studio Express e creiamo un nuovo progetto di
tipo Windows Application. Chiamiamo il nostro
nuovo progetto MyCDBurn. A questo punto pro-
cediamo con la creazione dellinterfaccia, preci-
sando che, naturalmente, tutto quello che attiene
laspetto grafico dellapplicazione assolutamen-
te soggettivo, scegliete quindi i colori e le forme
che pi vi aggradano. Al termine della creazione
della UI dovreste ottenere un risultato simile a quel-
lo in Fig. 1.
L'interfaccia dell'applicazione molto semplice e
consiste in una TextBox impostata in modalit
Readonly, in cui verr visualizzato il percorso del-
la folder della staging area. Subito sotto troviamo una
ListBox nella quale elencheremo i file e le cartelle
selezionate per la scrittura su CD-Rom. Sulla sini-
stra in basso troviamo una Label che ci mostra la let-
tera dell'unit di scrittura rilevata sulla macchina
e in fondo troviamo i quattro tasti di comando che
rispettivamente partendo da sinistra, permettono
di aggiungere dei file, aggiungere delle cartelle, av-
viare la masterizzazione e chiudere l'applicazione.
Dopo aver impostato linterfaccia grafica passia-
mo alla scrittura del codice. Dobbiamo creare ora
una interfaccia facendo clic con il tasto destro del
mouse sul nome del progetto, scegliendo Add New
Itemdal menu contestuale. Nella finestra di dialo-
go che appare scegliamo il template Interface e as-
sociamo come nome ICDBurn.cs. Siamo quindi
giunti alla parte pi importante di tutta lapplicazione,
ovvero al momento in cui dobbiamo referenziare
linterfaccia di sistema ICDBurn
Per fare questo, il linguaggio C# ci viene in aiuto
grazie alla possibilit di specificare un semplice
attributo per referenziare il componente COM.
Innanzi tutto aggiungiamo internal davanti la di-
chiarazione dellinterfaccia:
internal interface ICDBurn
{
E poi assicuriamoci che siano presenti le seguen-
ti using:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
Quindi aggiungiamo il seguente codice:
[ComImport]
[Guid("3d73a659-e5d0-4d42-afc0-5121ba425c8d")]
[InterfaceType(ComInterfaceType.InterfaceIsIUn
known)]
internal interface ICDBurn
{
Non facciamoci intimidire,, in realt con questi tre
attributi non abbiamo fatto altro che dichiarare
che la nostra interfaccia far uso di un componente
COM di sistema, il cui identificativo univoco
(CLSID) quello specificato nellattributo Guid.
Con l'attributo InterfaceType indichiamo inoltre
l'interfaccia da cui deriva a sua volta ICDBurn, che
nella maggior parte dei casi per i componenti COM
IUnknown. A questo punto non ci resta che in-
serire la dichiarazione fisica dellinterfaccia:
internal interface ICDBurn
{
uint GetRecorderDriveLetter(
[MarshalAs(UnmanagedType.LPWStr,SizeParamIndex
=1)]
string pszDrive,
uint cch);
int Burn(IntPtr hWnd);
int RecordableDrivePresent(ref int iHasRecorder);
}
Qui ritroviamo esattamente quei tre metodi che
abbiamo citato poco prima, ovvero il metodo per
recuperare la lettera di unit del dispositivo, il me-
todo per avviare la masterizzazione e il metodo
Fig. 1: Interfaccia dellapplicazione MyCDBurn
NOTA
COS LA CSIDL?
Questa sigla che sta per
Constant Special Item ID
List una lista di valori
che identificano le cartelle
speciali di Windows XP
frequentemente utilizzate
dalle applicazioni per
diversi scopi. Queste
costanti permettono di
puntare a delle cartelle
che per loro natura
possono variare da
sistema a sistema o da
utente ad utente e quindi
non possibile definire a
priori nelle applicazioni. In
questa lista troviamo valori
come: CSIDL_DESKTOP,
CSIDL_MYDOCUMENTS,
CSIDL_PROGRAM_FILES,
CSIDL_WINDOWS etc.
072-076:072-080 16-07-2008 9:48 Pagina 73
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
74
/Settembre 2008
Utilizzare lAPI ICDBURN di Microsoft Windows
SUL WEB
Per ulteriori dettagli
sullinterfaccia ICDBurn
possibile consultare la
documentazione ufficiale
dellinterfaccia su MSDN:
http://msdn.microsoft.
com/en-us/library/
bb776155(VS.85).aspx
Per maggiori informazioni
invece sulla struttura
ITEMIDLIST che permette
di accedere a diverse
propriet relative ad una
cartella, possibile
consultare la seguente
sezione della MSDN
Library:
http://msdn.microsoft.
com/en-us/library/
bb773321(VS.85).aspx
che ci informa se sulla macchina presente unu-
nit di masterizzazione utilizzabile. Essendo ICD-
Burnuna interfaccia, al fine di poterla importare nel
nostro progetto dobbiamo necessariamente di-
chiarare tutti i suoi metodi..In alcuni casi, ad esem-
pio per il parametro pszDrive di GetRecorderDriv-
eLetter, sar necessario specificare una diversa
mappatura dei tipi tra COM e .NET attraverso
lutilizzo dellattributo MarshalAs che ci permet-
te, appunto, di specificare una diversa corrispon-
denza tra un tipo .NET, string nel nostro caso, e un
tipo Unmanaged, in questo caso LPWStr.
A questo punto passiamo alla creazione della clas-
se che racchiuder tutto il codice necessario alla
nostra applicazione.
LA CLASSE BURN
Creiamo una nuova classe e chiamiamola Burn.
Assicuriamoci che siano presenti almeno i seguenti
namespace:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;
Implementiamo l'interfaccia IDisposable affinch
la classe possa essere eliminata correttamente dal-
la memoria:
public class Burn : IDisposable
{
Dichiariamo i metodi che ci serviranno per rica-
vare il percorso della staging area:
[DllImport("Shell32.dll")]
public static extern bool SHGetPathFromIDList(IntPtr
ilPtr, string sPath);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern uint
SHGetSpecialFolderLocation(IntPtr hWnd, CSIDL
nFolder, out IntPtr Pidl);
Quindi la variabile globale in cui memorizzare
l'oggetto ICDBurne lenumerato che definisce tut-
ti i CSIDL delle cartelle speciali di Windows (vede-
re codice allegato al Cd-Rom per lenum comple-
to):
private ICDBurn ICDBurn;
public enum CSIDL
{
Desktop = 0x0000, // Desktop
Internet = 0x0001, // Internet Explorer
Programs = 0x0002, // Cartella programmi
Controls = 0x0003, // Pannello di
controllo
Printers = 0x0004, // Cartella stampanti
Personal = 0x0005, // Cartella personale
Favorites = 0x0006, // Cartella preferiti di
Internet Explorer
Startup = 0x0007, // Cartella
esecuzione automatica
Recent = 0x0008, // Cartella file recenti
SendTo = 0x0009, // Cartella Invia A
StartMenu = 0x000b, // Cartella Avvio
MyDocuments = 0x000c, // Cartella Documenti
..
..
Passiamo ora alla gestione degli errori. Sappiamo
infatti che non infrequente incappare in diversi
tipi di problemi quando ci accingiamo a maste-
rizzare un supporto ottico. Le problematiche pos-
sono essere di varia natura, ad esempio il disco da
masterizzare potrebbe non contenere sufficiente spa-
zio libero, oppure il supporto potrebbe essere dan-
neggiato o, ancora, durante la copia dei dati possono
insorgere problemi come il famoso buffer underrun.
Per far fronte a queste eventualit, esistono delle API
che permettono di identificare e gestire tali errori.
Il primo passo quello di definire un enumerato
che, come per i CSIDL, ci permetta di elencare tut-
ti i possibili errori che possono verificarsi durante
il processo di masterizzazione:
public enum ImapiErrorValues : uint
{
Ok = 0, // Nessun errore
PropertiesIgnored = 2147746304, // Propriet
sconosciuta
BufferTooSmall = 2147746305, // Buffer troppo
piccolo
.
.
DiskFull = 2147746332, // Disco pieno
.
.
Dopo aver definito questi valori di errore potremo
quindi di volta in volta convertire i codici di erro-
re eventualmente restituiti dai vari metodi utilizzati,
per interpretare l'errore e comunicarlo all'utente.
Dopo queste definizioni possiamo ora passare al
costruttore della classe, che crea materialmente
loggetto ICDBurn e ne inizializza i parametri:
public Burn()
{
if (!CreateInterface())
{
072-076:072-080 16-07-2008 9:48 Pagina 74
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
75
G
Utilizzare lAPI ICDBURN di Microsoft Windows
throw new Exception("Impossibile creare
linterfaccia ICDBurn");
}
RecordableDrive = RecorderAvailable();
if (RecordableDrive)
{
DriveLetter = GetDriveLetter();
}
StageFolder = GetBurnStagingAreaFolder();
}
Il metodo CreateInterface si preoccupa di creare
linterfaccia e di memorizzarla nella variabile glo-
bale , restituendo eventualmente un errore nel ca-
so non riuscisse ad istanziare il componente COM:
private bool CreateInterface()
{
// Oggetto della shell
Guid shellCDBurnStr = new Guid("FBEB8A05-
BEEE-4442-804e-409d6c4515e9");
Type comType =
Type.GetTypeFromCLSID(shellCDBurnStr);
if (comType == null)
{
throw new Exception("Sistema operativo
non supportato");
}
ICDBurn = (ICDBurn)
Activator.CreateInstance(comType);
if (ICDBurn != null)
{
return true;
}
else
{
MessageBox.Show("Impossibile creare
l'interfaccia ICDBurn");
return false;
}
}
Subito dopo viene verificata la presenza di una
unit di masterizzazione e, se presente, ne viene
ricavata la lettera di unit. Infine, viene ricavato il
percorso della cartella che sar utilizzata come
staging area dal processo di masterizzazione.
Tutte queste operazioni vengono svolte da tre me-
todi:
private bool RecorderAvailable();
private string GetDriveLetter();
public static string GetBurnStagingAreaFolder();
Questi tre metodi richiamano i corrispondenti me-
todi delloggetto ICDBurnper ricavare le tre infor-
mazioni necessarie per avviare la masterizzazio-
ne. Vediamo in particolare GetBurnStagingAreaFolder:
public static string GetBurnStagingAreaFolder()
{
IntPtr pidl = Marshal.AllocHGlobal(1024);
uint retVal = SHGetSpecialFolderLocation(pidl,
CSIDL.CdBurnArea, out pidl);
StringBuilder path = new StringBuilder(260,260);
bool result = SHGetPathFromIDList(pidl, path);
if (result == false)
{
throw new Exception("Nessuna staging area
specificata");
}
Marshal.FreeHGlobal(pidl);
return path.ToString();
}
Per ricavare la cartella della staging area utilizzia-
mo il metodo SHGetSpecialFolderLocation il qua-
le richiede in input un puntatore ad uno spazio di
memoria da poter utilizzare per le sue operazioni
ed il valore CSIDL relativo alla cartella speciale da
recuperare. Ottenuto il riferimento alla cartella
speciale della staging area, attraverso il metodo
SHGetPathFromIDList ci ricaviamo il path della
cartella verificando il valore di ritorno per ricono-
scere uneventuale situazione di errore che ci im-
pedisce di ottenere il percorso desiderato.
In ultimo, possiamo liberare la memoria allocata per
questa operazione con il metodo FreeHGlobal e ri-
torniamo il valore trovato.
Possiamo ora definire il metodo principale che av-
via materialmente la scrittura sul supporto CD:
public ImapiErrorValues BurnCD(IntPtr h)
{
return (ImapiErrorValues)ICDBurn.Burn(h);
}
Come accennato, il metodo Burn dellinterfaccia
richiede solo lhandle alla finestra padre che avvia
la dialog del processo di masterizzazione. Il meto-
do BurnCD ci restituisce inoltre anche un valore
di ritorno di tipo numerico che possiamo tradur-
re grazie allenumerato ImapiErrorValues per per-
metterci di verificare la presenza di eventuali er-
NOTA
LE ALTRE SHELL
INTERFACE
Oltre ad ICDBurn che
utilizziamo in questo
esempio, vi sono numerose
altre interfacce che ci
vengono messe a
disposizione per gli scopi
pi disparati. Trovate un
elenco di queste interfacce
allindirizzo:
http://msdn.microsoft.co
m/en-
us/library/bb774328.aspx
NOTA
COS UN CLSID
Un CLSID un
identificativo univoco
rappresentato in forma di
numero esadecimale a
128 bit (es. 373f04b0-
3c50-11dd-ae16-
0800200c9a66), che
identifica univocamente un
oggetto COM,
unapplicazione o un
generico componente
software, allinterno del
sistema. Tutti i CLSID
utilizzati da Windows sono
memorizzati nel registro di
sistema in
HKEY_CLASSES_ROOT\CL
SID.
072-076:072-080 16-07-2008 9:48 Pagina 75
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
76
/Settembre 2008
Utilizzare lAPI ICDBURN di Microsoft Windows
rori. Infine scriviamo anche del codice per gestire
correttamente la Dispose delloggetto dalla me-
moria, affinch liberi le risorse e possa essere avviata
una nuova masterizzazione:
protected void Dispose(bool disposing)
{
if (!this.DisposedVal)
{
if (disposing)
{
if (ICDBurn != null)
{
Marshal.FinalReleaseComObject(ICDBurn);
ICDBurn = null;
}
}
}
this.DisposedVal = true;
}
Questo metodo viene richiamato dal metodo Dis-
pose che abbiamo implementato per l'interfaccia
IDisposable:
public void Dispose()
{
Dispose(true);
}
La nostra classe Burn completa.
Ora non dobbiamo far altro che collegare linterfaccia
grafica che abbiamo creato ai metodi della classe,
e permettere, in tal modo, di visualizzare le infor-
mazioni relative al processo di masterizzazione,
nonch avviare la scrittura su CD. Nel codice del
nostro form creiamo una variabile globale che con-
tiene loggetto ICDBurn:
private Burn Burner;
Quindi nel costruttore del form istanziamo loggetto
ICDBurn e visualizziamo in UI il percorso della
staging area e la lettera di unit del masterizzato-
re:
Burner = new Burn();
txtStagingArea.Text = Burner.StageAreaFolderPath;
lblDriveLetter.Text = Burner.RecorderDrivePath;
I metodi AddFolder e DeleteFolder si occupano ri-
spettivamente di aggiungere file o cartelle alla stag-
ing area o di rimuoverli da essa. Per questioni di
spazio non riportiamo qui il codice di questi metodi
il cui contenuto disponibile nel codice allegato.
Il tasto Burndella nostra applicazione non fa altro
che eseguire il seguente codice:
Burn.ImapiErrorValues result =
Burner.BurnCD(this.Handle);
Burner.Dispose();
DeleteFolder(new DirectoryInfo(txtStagingArea.Text));
lbSelectedFiles.Items.Clear();
lbSelectedFiles.Refresh();
if (result == Burn.ImapiErrorValues.Ok)
{
MessageBox.Show("Masterizzazione eseguita con
successo!");
}
else
{
MessageBox.Show(result.ToString());
}
Viene richiamato il metodo BurnCD della classe
Burn passandogli lhandle della finestra corrente.
Eseguiamo, quindi, il metodo Dispose per scarica-
re la classe Burn dalla memoria e, al termine della
masterizzazione, rimuovere tutti i file e le cartelle
dalla staging area, ripulendo lelenco dei file dal-
linterfaccia. In caso di errore, la variabile result in-
glober la tipologia di errore verificatosi.
SIAMO PRONTI PER
UTILIZZARE LA NOSTRA
APPLICAZIONE
Completata la nostra applicazione, possiamo
procedere con il test di masterizzazione.
Procuriamoci quindi un CD vergine ed avviamo
lapplicazione. Il primo passo sar quello di
verificare che il percorso della staging area sia
corretto o comunque che punti ad una cartella
esistente e dedicata allo scopo.
E molto importante verificare che la cartella della
staging area sia quella corretta in quanto se questa
corrisponde ad una cartella utilizzata per altri scopi
potremmo perderne tutto il contenuto nel momen-
to in cui lapplicazione canceller i file dalla staging
area. Verificato quindi il percorso, selezioniamo i fi-
le e le cartelle che vogliamo copiare su CD-Rom.
Selezionati i file, premiamo su Masterizza, si avvier
il wizard di masterizzazione di Windows.
Il primo step ci chieder il nome da dare al nuovo
supporto che stiamo per creare.
Specifichiamo un nome e proseguiamo con Avanti.
A questo punto, se tutto stato impostato corret-
tamente, e se nellunit di scrittura presente un
disco vuoto, la copia avr inizio.
Gianni Malanga
LAUTORE
Gianni Malanga
lavora da pi di 10 anni
con tecnologie Microsoft in
particolare nel campo
dello sviluppo Web.
Sviluppa in .NET da diversi
anni e dopo aver lavorato
alle dipendenze di
importanti realt locali ha
intrapreso la libera
professione costituendo la
ditta individuale Kaone
Consulting che si occupa
di consulenza informatica
per PMI su tutto il territorio
nazionale. Lo si pu
contattare allindirizzo
kaone@email.it. Il suo
blog personale :
http://thekaone.blogspot.
com
NOTA
DLLIMPORT
Lattributo DllImport
permette di esportare una
funzione da una DLL
unmanaged allinterno del
nostro codice managed
per poterla utilizzare.
Lattributo viene apposto a
un metodo che deve avere
lo stesso nome e firma del
metodo che si vuole
importare dalla DLL e deve
essere marcato con extern
proprio per indicare che
definito fuori
dallapplicazione .NET ed
in particolare nella DLL
specificata allinterno
dellattributo DllImport.
Se per qualche ragione al
metodo che esportiamo
desideriamo cambiargli il
nome, sar sufficiente
specificare in DllImport un
secondo parametro,
EntryPoint che definir il
nome originario del
metodo allinterno della
DLL.
072-076:072-080 16-07-2008 9:48 Pagina 76
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
78
/Settembre 2008
Il nuovo linguaggio di casa SUN: JavaFX Script
J
avaFX Script una nuova tecnologia che sta-
ta presentata dalla SUN qualche mese fa.
Lobiettivo quello di diventare lo strumento idea-
le per lo sviluppo di interfacce grafiche, RIA (Rich
Internet Applications). Un linguaggio di scripting
che permette di sviluppare in poco tempo e con
relativa facilit uninterfaccia grafica che pu es-
sere adoperata per lo sviluppo di programmi Deskop
e, in futuro, utilizzando quello che viene definito Ja-
vaFX Mobile, anche sui dispositivi mobili.
Oltre alla visione futuristica di SUN nel proporre
un linguaggio che possa definire interfacce grafiche
con estrema facilit su diverse piattaforme, c da
dire che JavaFX pu essere molto utile nello pro-
totipazione di interfacce grafiche, realizzando pri-
ma qualcosa di basilare per poi entrare nel detta-
glio di ogni componente. Anche lo sviluppo MVC
(Model View Controller) si sposa perfettamente
con questa tecnologia, visto che, utilizzandola, po-
tremmo demandare completamente la parte di
View alle componenti JavaFX e realizzare le altre
parti in Java. Il linguaggio in oggetto, infatti, offre
unottima interoperabilit con altri sorgenti Java, per-
mettendo quindi di associare allinterfaccia grafi-
ca un Model gestito con Hibernate e la parte di
Controller realizzata completamente da noi.
Lestrema utilit di linguaggi di scripting nello svi-
luppo di applicazioni stata ribadita in diversi con-
testi: Groovy e la JSR-234 (http://jcp.org/en/jsr/detail?id=223)
sono due esempi lampanti del fatto che utilizzare
un linguaggio di scripting allinterno di applica-
zioni Java pu essere spesso una marcia in pi per
lo sviluppo. In questo articolo vedremo le basi di que-
sto linguaggio di scripting, realizzando diversi pro-
grammi desempio per capirne le nozioni fonda-
mentali.
PRONTI
PER IL CONSUETO
HELLO WORLD?
Come in ogni buon articolo che tratti di un nuovo
linguaggio, non possiamo esimerci dallo scrivere il
buon vecchio Hello World, vedendo subito un esem-
pio funzionante di JavaFX Script per poi andare
nel dettaglio.
package testjavafx;
import javafx.ui.*;
import javafx.ui.canvas.*;
Frame {
title: "JavaFX Script example"
height: 150
width: 300
content:
Canvas {
content:
Text {
font:
Font {
faceName: "Arial"
style: BOLD
size: 20
}
x: 10
y: 10
content: "Hello World!"
}
}
PRIMI PASSI
CON JAVAFX SCRIPT
VEDIAMO COME SUN RISPONDE AGLI ALTRI LINGUAGGI PER LO SVILUPPO DI RICH INTERNET
APPLICATION, PROPONENDO UN NUOVO LINGUAGGIO CHE INTRODUCE SIGNIFICATIVI
MIGLIORAMETI NELLA COSTRUZIONE DINTERFACCE GRAFICHE
J CD J WEB
JavaFX_Script.zip
cdrom.ioprogrammo.it
Conoscenze richieste
J2SE
Software
JavaFXPad, Java 6 SE
Impegno

Tempo di realizzazione
REQUISITI
Fig. 1: La piattaforma JavaFX introdotta da SUN
078-082:072-080 16-07-2008 10:25 Pagina 78
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
79
G
Il nuovo linguaggio di casa SUN: JavaFX Script
visible: true
}
Una cosa di cui il buon programmatore Java si ren-
de subito conto lassenza del main.
Nessun problema stiamo parlando di JavaFX Script
non di un semplice programma Java. Dovremo
quindi abituarci a una sintassi e a un modo leg-
germente diverso per realizzarele nostre applica-
zioni. La differenza che comunque balza subito
agli occhi del lettore, oltre alla mancanza del main,
il diverso modo in cui questo programma sta-
to scritto. Infatti, non c da nessuna parte
linizializzazione di un nuovo oggetto, un punto e
virgola, una qualsiasi istruzione che abbiamo gi vi-
sto. Questo perch con JavaFX Script cambia pro-
prio il paradigma di sviluppo. Se con i classici pro-
grammi siamo abituati ad avere un paradigma pro-
cedurale, ora dobbiamo abituarci ad un tipo di svi-
luppo dichiarativo, dove vengono appunti dichia-
rati i vari componenti che devono essere utilizza-
ti. Nellesempio, infatti, potete vedere come venga
fatta una vera e propria descrizione del compo-
nente Frame, settando i vari attributi.
Questa non lunico paradigma supportato da Ja-
vaFX Script, infatti, possibile avere anche fun-
zioni e altro legato al mondo procedurale, per ci
non toglie che sarebbe pi opportuno definire le
nostre interfacce in maniera dichiarativa, per au-
mentare di molto la leggibilit e la comprensione
del nostro codice (oltre ad essere, comunque, un mo-
do molto intuitivo per definire le interfacce grafi-
che, descrivendole).
AMBIENTI DI SVILUPPO
Prima di procedere alla stesura di una prima ap-
plicazione, strettamente necessario conoscere
gli strumenti necessari.
JavaFX Script costruito sulle fondamenta di Java
6 Standard Edition, quindi, prima di tutto, sar ne-
cessario aver installata tale software sul nostro
computer. Possono anche ritornarci utili strumenti
come JavaFxPad, unapplicazione che ci permet-
te di visualizzare in tempo reale qual il risultato
del nostro codice JavaFX Script. possibile scari-
care questa applicazione dal seguente url:
http://www.javafxpad.com/. Oltre a questo interessante
tool, esistono i classici plugin per gli IDE di svi-
luppo, che ci permettono di lavorare ad un pro-
getto JavaFX utilizzando tutte le comodit a cui
siamo normalmente abituati. Per trovare i plugin adat-
ti a NetBeans ed Eclipse visitare il sito https://openjfx.
dev.java.net/downloads.html, Allinterno presente
anche il compilatore JavaFX che pu essere utiliz-
zato da riga di comando, nel caso in cui non si vo-
glia ricorrere agli IDE proposti.
LE BASI DEL
LINGUAGGIO
Come in ogni linguaggio, abbiamo a disposizione
dei costrutti per inglobare un po di logica e pro-
grammazione. Nel caso di JavaFX si hanno due di-
versi tipi di costrutti, che nel linguaggio Java an-
drebbero assumerebbero il nome di metodi, fun-
zioni e operazioni. Le funzioni sono dei semplici
costrutti allinterno dei quali possiamo racchiu-
dere dichiarazioni di variabili (quindi operazioni
su di esse) e ritornare il risultato, il minimo indi-
spensabile quando stiamo realizzando qualcosa
che molto legato a uninterfaccia grafica.
Nel seguente esempio associamo un bottone a
unoperazione:
package testjavafx;
import javafx.ui.*;
import javafx.ui.canvas.*;
var textField1 = TextField {
value: ""
horizontalAlignment: TRAILING
onChange: operation(s:String) {
}
};
var textField2 = TextField {
value: ""
horizontalAlignment: TRAILING
onChange: operation(s:String) {
}
};
var textField3 = TextField {
editable: false
horizontalAlignment: TRAILING
onChange: operation(s:String) {
}
};
Frame {
title: "JavaFX Script example"
height: 150
width: 300
content:
GridBagPanel {
border: EmptyBorder {
top: 5
left: 5
bottom: 5
right: 5
}
x: 0
y: 0
height: 150
width: 300
cells:
078-082:072-080 16-07-2008 10:25 Pagina 79
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
80
/Settembre 2008
Il nuovo linguaggio di casa SUN: JavaFX Script
[GridCell {
anchor: WEST
fill: HORIZONTAL
gridx: 0
gridy: 0
gridwidth: 80
content: textField1
},GridCell {
anchor: WEST
fill: HORIZONTAL
gridx: 0
gridy: 1
gridwidth: 80
content: textField2
},GridCell {
anchor: WEST
fill: HORIZONTAL
gridx: 0
gridy: 2
gridwidth: 80
content: textField3
},GridCell {
anchor: WEST
fill: HORIZONTAL
gridx: 0
gridy: 3
gridwidth: 80
content: Button {
text: "Costruisci"
action: operation() {
textField3.value="{textField1.value}{textField2.value
}";
textField1.value="";
textField2.value="";
}
}
}]
}
visible: true
}
Il codice proposto, rispetto al semplice Hello World,
ha in s una serie di nozioni da approfondire.
Prima di tutto potete vedere come allinizio del no-
stro script ci sia la definizione di tre vere e proprie
variabili. JavaFX permette la definizione delle va-
riabili utilizzando listruzione var, senza specifi-
care direttamente di che tipo siano questultime.
Essendo comunque un linguaggio staticamente
tipizzato, non ci troveremo in situazioni simili a
linguaggi come PHP, in cui inizialmente la variabile
pu assumera un valore stringa e successivamen-
te, nel corso dello script, diventare di un altro ti-
po. Abbiamo quindi definito queste tre variabili di
tipo TextField; saranno utilizzate nel nostro pro-
gramma, specificando alcune loro propriet.
Successivamente presente la definizione del fra-
me in cui andremo a disegnare la nostra interfac-
cia grafica. Allinterno del frame scegliamo di uti-
lizzare un GridBagPanel, ovvero un pannello che ci
permette di integrare alsuo interno diversi com-
ponenti (coloro i quali hanno dimestichezza con
Swing troveranno con questo componente diver-
se similitudini). Nel pannello abbiamo posizio-
nato quattro diversi componenti: tre TextField e
un Button. A questultimo stato associato un ope-
ration, che si aziona nel momento in cui viene pre-
muto il bottone. Questa operazione inserisce nel
terzo TextField il testo dei primi due, poi li resetta.
In questo caso abbiamo utilizzato unoperazione de-
finendola inline, senza dichiarazioni e quantal-
tro. Vediamo ora, invece, una classe nella quale ab-
biamo definito diverse strutture caratteristiche di
JavaFX
package testjavafx;
import javafx.ui.*;
import javafx.ui.canvas.*;
import java.util.Date;
import java.lang.Math;
import java.lang.System;
public class TestClass {
private attribute primo: String;
public attribute secondo: Number;
protected attribute terzo: Number;
attribute quarto: Number;
public attribute quinto: Boolean;
}
var unaVariabile = "Hello world";
var test = TestClass {
primo : "ciao"
quarto: 34
quinto: true
secondo: MIN_INT
terzo: 33
};
saluta(test);
saluta(unaVariabile);
saluta(somma(1,2));
operation saluta(test) {
foreach( i in [1..10] )
System.out.println("Ciao {i}");
System.out.println(test);
Fig. 2: Esempio di operation
078-082:072-080 16-07-2008 10:25 Pagina 80
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
81
G
Il nuovo linguaggio di casa SUN: JavaFX Script
}
function somma(a,b) {
var c = a + b;
return c;
}
Nella nostra classe abbiamo incluso delle variabi-
li, definendole con la keyword attribute. I tipi associati
agli attributi sono quelli primitivi di JavaFX, che
hanno chiaramente una corrispondenza con quel-
li Java, cos come si potr meglio vedere in seguito
String java.lang.String
Boolean java.lang.Boolean
Number java.lang.Number
Integer int, long, byte, short, java.math.BitInteger
Come in Java, possiamo associare agli attributi i
diversi livelli di visibilit: private, public, protect-
ed e default. A seguire la definizione della classe,
troviamo la definizione di quelle che vengono chia-
mate variabili, presenti al di fuori della classe e che
vengono dichiarate tramite la keyword var.
In questo caso abbiamo definito una variabile co-
me String, implicitamente perch abbiamo pas-
sato direttamente il suo valore.
La seconda definizione di variabile riguarda, in-
vece, un oggetto di tipo TestClass, i cui attributi so-
no valorizzati nella maniera dichiarativa, cos co-
me gi visto precedentemente. Loperazione salu-
ta() effettua diversi task, un foreach in cui viene
mostrato su console una stringa e successivamente
anche loggetto che viene passato come argomento
alloperation. La funzione, invece, ci permette di
definire al suo interno nuove variabili (var) e resti-
tuire i valori tramite il return (magari dopo une-
laborazione aritmetica). In questo caso, infatti, per
mostrarne il funzionamento, abbiamo definito la
functionsomma(), che accetta due parametri e re-
stituisce la somma aritmetica degli stessi.
BINDING CON UN MODEL
Uno degli aspetti molto interessanti di JavaFX, spe-
cialmente per la costruzione delle interfacce gra-
fiche, la possibilit di creare un collegamento tra
diverse variabili, il cosddetto binding.
Praticamente, immaginiamo di avere, allinterno
del nostro progetto, una tipica classe model:
package testjavafx;
import javafx.ui.*;
import javafx.ui.canvas.*;
import java.util.Date;
import java.lang.Math;
import java.lang.System;
public class Persona {
public attribute nome: String;
public attribute cognome: String;
public attribute codiceFiscale: String;
public attribute indirizzo: String;
public attribute email: String;
}
var persona = Persona {
nome: "Federico"
cognome: "Paparoni"
codiceFiscale: "ABCDEFGHILMNOPQRSTUVZ"
indirizzo: "Via via"
email: "doc@javastaff.com"
};
Non abbiamo fatto niente di nuovo rispetto ai pre-
cedenti esempi. Aggiungiamo un Frame in cui vi-
sualizzare le informazioni precedentemente defi-
nite:
Frame {
title: "Visualizza persona"
height: 150
width: 300
content:
Canvas {
content:
Text {
font:
Font {
faceName: "Arial"
style: PLAIN
size: 15
}
x: 10
y: 10
content: bind persona.nome
} visible: true }
Testando il programma appena riportato potremo
vedere come i valori definiti precedentemente nel-
la variabile persona siano inseriti nel frame.
Tale link tra interfaccia grafica e model rimane
in piedi anche quando il model subisce dei cam-
biamenti. In soldoni, viene fatto il refresh dei com-
ponenti grafici allorch ve ne siano alcuni colle-
gati tramite la keyword bind con una variabile.
Se avete programmato almeno un po con Swing
e AWT riuscirete a capire quanto pu essere mi-
gliore una gestione automatizzata in questo mo-
do.
FUNZIONAMENTO
DEI TRIGGER
I trigger in SQL sono degli allarmi che noi pos-
siamo far scattare nel momento in cui verifica una
determinata condizione, contestualmente possibile
078-082:072-080 16-07-2008 10:25 Pagina 81
ht t p: / / www. i opr ogr ammo. i t
quindi eseguire specifiche operazioni.
Anche JavaFX possiede una caratteristica simile,
conosciuta proprio come trigger. Tale strumento
pu ritornare particolarmente utile ad esempio
per avere delle notifiche nel momento in cui viene
modificata una classe model. Proviamo a utilizza-
re i trigger in funzione della risposta a una do-
manda posta allutente:
import javafx.ui.*;
import javafx.ui.canvas.*;
class Domanda {
attribute selectedIndex: Number;
attribute quote: String;
attribute preferenza: String*;
attribute actions: String*;
}
var model = Domanda {
var: self
selectedIndex: 0
quote: self.actions[self.selectedIndex]
preferenza: ["JavaME", "JavaSE", "JavaEE"]
quotes: ["Quindi sei un programmatore mobile
eh?!", "Plain old Java :)", "Enterprise di Kirk?"]
};
Oltre a definire il nostro model, abbiamo anche
inizializzato una sua istanza con alcuni valori.
A questo punto definiamo un trigger, che viene ri-
chiamato nel momento in cui lattributo selecte-
dIndex del nostro model viene cambiato con un
nuovo valore:
trigger on Domanda.selectedIndex = newValue {
this.quote = this.quotes[newValue];
}
Il trigger definoto praticamente un listener atti-
vato sul nostro model. Nel nostro caso viene ri-
chiamato quando un determinato attributo cam-
bia. Di conseguenza vine mostrata a video una op-
portuna frase.:
Frame {
title: "WYGIWYS"
width: 300
height: 200
visible: true
content:
Panel {
content: [
Canvas {
x: 0
y: 0
width: 300
height: 120
content:
[Text {
font:
Font {
faceName: "Arial"
style: PLAIN
size: 15
}
x: 10
y: 10
content: bind model.quote
}]
}, ComboBox {
x: 120
y: 140
selection: bind model.selectedIndex
border: EtchedBorder
cells: foreach (pref in model.preferenza)
ComboBoxCell {
text: pref
}
}]
}
}
Il risultato che avremo un semplice frame con
una Combobox. In questa vengono riportate le di-
verse opzioni di scelta. Allatto della selezione di
una di queste, sar nel contempo visualizzata una
frase nel frame, frase che ovviamente si modifica in
funzione della scelta optata dallutente.
UN ESEMPIO GRAFICO
Sicuramente, arrivati a questo punto, avrete gi in-
tuito le potenzialit di JavaFX, quindi ora andre-
mo a vedere un esempio leggermente pi com-
plesso che racchiude diverse feature di questo lin-
guaggio.Il codice sorgente di questo esempio sta-
to rilasciato da Christopher Oliver nella mailing li-
st di openjfx (https://openjfx.dev.java.net/servlets/ReadMsg?l
ist=dev&msgNo=43) e successivamente modificato e
disponibile su http://jfx.wikia.com/wiki/Main_Page, ri-
guarda limplementazione di un semplice orolo-
gio analogico. Analizziamo, quindi, un primo esem-
pio in cui facciamo uso di un timer:
SISTEMA M
G
82
/Settembre 2008
Il nuovo linguaggio di casa SUN: JavaFX Script
Fig. 3: Un timer che muove la nostra interfaccia
078-082:072-080 16-07-2008 10:25 Pagina 82
ht t p: / / www. i opr ogr ammo. i t
import javafx.ui.*;
import javafx.ui.canvas.*;
import java.util.Date;
import java.lang.Math;
import java.lang.System;
public class Timer {
private attribute elapsed: Number;
public attribute minutes: Number;
public attribute seconds: Number;
public attribute hours: Number;
public attribute running: Boolean; }
attribute Timer.elapsed = bind if running
then [1..20] dur 1000 linear
while running
continue if true
else 0;
trigger on Timer.elapsed = value {
var now = new Date();
minutes = now.getMinutes();
seconds = now.getSeconds() + (now.getTime() %
1000)/1000;
hours = now.getHours(); }
public class Clock extends CompositeNode {
public attribute ticking: Boolean; }
operation Clock.composeNode() {
var t = Timer {running: bind ticking};
return Group {
var font = new Font("Dialog", "PLAIN", 15)
var secs = bind t.seconds
var mins = bind t.minutes + secs/60
var hrs = bind t.hours + mins/60
content:
[Rect {
height: 200
width: 5000
fill: white },
Circle {cx: 100, cy: 100, radius: 80, fill:
white, stroke: black, strokeWidth: 1
},
Group {
transform: translate( 100, 100 )
content: foreach( i in [1..12] )
Text{ var radians = Math.toRadians( 30 * i -90)
transform: [translate( 70*Math.cos(
radians ), 70*Math.sin( radians ) )]
content: "{i}" valign: MIDDLE, halign: CENTER
}
},
Group {
transform: translate(100, 100)
var hourHand =
Line {x1: 0, y1: 0, x2: 0, y2: -35,
strokeWidth: 4, stroke: black
transform: bind rotate(hrs*30, 0, 0)
}
var minuteHand =
Line {x1: 0, y1: 0, x2: 0, y2: -55,
strokeWidth: 2, stroke: black,
transform: bind rotate(mins * 6, 0, 0)
}
var secondHand =
Line {x1: 0, y1: 0, x2: 0, y2: -75,
strokeWidth: 1, stroke: red,
transform: bind rotate(t.seconds * 6, 0, 0)
}
content: [hourHand, minuteHand,
secondHand]
},Circle {cx: 100, cy: 100, radius: 3, fill: black,
stroke: black }]
};
}
Clock {ticking: true}
Lesempio racchiude tutti i costrutti di cui abbiamo
avuto gi modo di parlare. Viene altres utilizzato un
componente Timer con gli attributi minuti, sec-
ondi e ora. Il model viene collegato alla nostra in-
terfaccia, in cui vengono disegnate le lancette
(line). Con Group, invece, vengono posizionati i
numeri, ciclando semplicemente da 1 a 12:
Group {
transform: translate( 100, 100 )
content: foreach( i in [1..12] )
Text {
var radians = Math.toRadians( 30 * i - 90)
transform: [translate( 70*Math.cos(
radians ), 70*Math.sin( radians ) )]
content: "{i}"
valign: MIDDLE, halign: CENTER
}
}
Il timer strettamente legato allinterfaccia.
In questo modo riusciamo a realizzare una sem-
plice animazione, settando a true il ticking di Clock
e avviando il timer associato.
CONCLUSIONI
JavaFX Script introduce molte novit nello svilup-
po di interfacce grafiche, ed essendo un prodotto
molto giovane ha sicuramente tanta strada avan-
ti a s per migliorare e per arricchirsi di funziona-
lit.
Oltre a essere impiegato nella costruzione e pro-
totipazione di interfacce grafiche, JavaFX Script
pu essere agevolmente impiegato per realizzare Ap-
plet e applicazioni GUI di un certo rilievo adope-
rando anche Java Web Start.
Insomma, tante possibilit di utilizzo per questo
nuovo e promettente linguaggio.
Federico Paparoni
M SISTEMA
Settembre 2008/
83
G
Il nuovo linguaggio di casa SUN: JavaFX Script
LAUTORE
L'autore, Federico
Paparoni, pu essere
contattato per
suggerimenti o
delucidazioni allindirizzo
email
federico.paparoni@javast
aff.com
078-082:072-080 16-07-2008 10:25 Pagina 83
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
84
/Settembre 2008
Utilizzo di Windows Management Instrumentation
N
essuno comincia a leggere la documenta-
zione ufficiale di una qualsiasi tecnologia
se non spinto da un interesse specifico.
Evidentemente chi scrive tale documentazione de-
ve saperlo bene, perch in effetti se avessimo co-
minciato a leggere la documentazione ufficiale sul
WMI avremmo letto: Windows Management In-
strumentation (WMI) linfrastruttura per la ges-
tione dei dati e delle operazioni sui sistemi operativi
basati su Windows.
E qui, i pi, senza un reale bisogno o interesse, sa-
rebbero passati a leggere altro. Bisogna rendere at-
to ai ragazzi di Redmond, infatti, di avere una par-
ticolare predisposizione allermetismo informati-
co. Personalmente mi capitato in pi occasioni di
scoprire o apprezzare tecnologie Microsoft so-
lo dopo aver scavato parecchio in profondit e sem-
pre spinto da bisogni contingenti, come la realiz-
zazione di una particolare procedura non realiz-
zabile in alcun altro modo. Il WMI una di quelle
cose, appunto, di cui abbiamo sentito parlare ma
che non si apprezza finch non si da uno sguardo
pi in profondit, arrivando cos a comprendere
le enormi potenzialit di questa tecnologia.
COS IL WMI
Posto in modo semplice, il WMI una grossa novit
nel modo in cui unapplicazione pu interagire con
il sistema operativo sottostante, ovviamente parliamo
della famiglia Windows. Per interazione intendia-
mo la raccolta di informazioni o il settaggio di par-
ticolari stati o componenti del sistema. In passato
per poter ottenere gli stessi risultati gli sviluppa-
tori dovevano scrivere parecchio codice anche
complicato, e non di rado succedeva che anche i
programmatori pi skilled trovavano non poche
difficolt.
Il WMI uno strato software che gira come servizio
allinterno del sistema operativo. Questo servizio
paragonabile a quello di un DBMS (Database Man-
agement System), infatti esso pu essere letteral-
mente interrogato con delle query di forma molto
simile allSQL (il linguaggio prende il nome di WQL
infatti), al fine di recuperare le informazioni che ci
interessano.
Tali query fanno riferimento ad oggetti astratti e
relazioni tra di essi che rappresentano entit hardwa-
re del sistema, come i servizi installati, i processi
in esecuzione o la configurazione hardware.
Questa organizzazione ad oggetti e relazioni chia-
mata CIM (Common Information Model), uno
standard aperto che permette di far riferimento
agli elementi fisici di un computer indipendente-
mente dallo specifico costruttore tramite dei
Providers. Il CIM, grazie alla sua struttura aperta
permette linserimento di nuovi Providers, ossia
entit che forniscono nuovi oggetti che ad esempio
facciano riferimento anche ad elementi non fisi-
ci, come il registro di Windows od i protocolli di
rete.
Il WMI molto importante per gli amministratori
di rete ad esempio, infatti tramite questa tecnolo-
gia possibile interrogare qualsiasi computer del-
MONITORARE LE
PERIFERICHE DEL PC
UTILIZZIAMO WMI PER RILEVARE I CAMBIAMENTI DI STATO DEI DISPOSITIVI REMOVIBILI.
INSERIMENTO, MODIFICA E RIMOZIONE DI SUPPORTI CD-ROM/DVD-ROM, USB MASS
STORAGE, MEMORY CARD E VIA DISCORRENDO
J CD J WEB
wmiremovable.zip
cdrom.ioprogrammo.it
Conoscenze richieste
Conoscenze buone di C#
Software
Visual Studio 2005,
.NET Framework 2.0
Impegno

Tempo di realizzazione
REQUISITI
Fig. 1: Schema di relazione per il WMI
084-089:072-080 16-07-2008 9:55 Pagina 84
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
85
G
Utilizzo di Windows Management Instrumentation
la rete per ottenere le informazioni su ogni aspet-
to del sistema (quanto spazio libero rimasto sui
dischi, quale sia lattuale utilizzo di CPU, a quale da-
tabase una certa applicazione connessa, e mol-
to altro ancora).
MONITOR DI
DISPOSITIVI REMOVIBILI
Realizzeremo unapplicazione per vedere allope-
ra le potenzialit della tecnologia di cui stiamo trat-
tando. In questo caso avremmo potuto utilizzare
varie strade. Infatti, proprio come un database,
WMI pu essere utilizzato sia programmatica-
mente, sia con linea di comando tramite WMIC,
sia con interfacce grafiche scritte ad hoc, come ad
esempio Microsoft Operations Manager (MOM)
oppure Systems Management Server (SMS) che usa-
no il WMI per gestire i sistemi da un punto centra-
le. Lapplicazione che andiamo a scrivere sar in
C# e realizzer un monitor per linserimento o
lespulsione di dispositivi removibili. In altre pa-
role la nostra applicazione si accorger quando
inseriremo una memory card oppure quando ri-
muoveremo una pendrive, o altri dispositivi re-
movibili.
Il task in s non complicato, ma ci permetter di
sporcarci le mani con questa nuova tecnologia e
cominciare a padroneggiare alcuni strumenti.
Come vedremo, lintera applicazione si basa sul-
lutilizzo di una classe che noi andremo a realiz-
zare. Per utilizzare il WMI, il framework .Net met-
te a disposizione il namespace System.Management.
Tale namespace contiene oggetti e strutture per
poter gestire e operare sul WMI, per il nostro sco-
po saranno sufficienti solo poche classi.
Cominciamo dalla classe ManagementScope: es-
sa serve ad indirizzare tutte le richieste che il pro-
gramma successivamente far ad un specifico na-
mespace (o scope appunto). Infatti nellistanzia-
re tale classe dovremo fornire al costruttore il path
del computer a cui vogliamo fare riferimento. Il
formato del path il seguente:
\\NumeComputer\\root\cimv2
In cui, ovviamente, NomeComputer rappresenta il
nome o lindirizzo ip del computer su cui vogliamo
operare. Teniamo presente che tramite la classe
ConnectionOptions possibile, settandola in ma-
niera adeguata, connetterci anche a computer che
sono in domini diversi e che hanno una coppia no-
me utente e password differente da quella in uso sul
computer da dove partono le richieste. Loggetto
ConnectionOptions opportunamente settato verr
fornito al costruttore della classe ManagementScope
assieme al path.
Il resto del path \\root\cimv2 fa riferimento al-
le classi esportate dai Providers che ci interessano.
In questo le classi cosiddette Win32 che rappre-
sentano gli aspetti di configurazione del sistema
operativo Windows sottostante.
Una volta definito lo scope delle nostre operazio-
ni, avremo bisogno della classe WqlEventQuery per
interrogare il WMI a riguardo di ci di cui abbia-
mo bisogno. Luso di tale classe molto semplice,
essa infatti un builder per la query WQL che restituir
le informazioni che vogliamo richiedere.
Per capire allora il funzionamento di tale classe do-
veroso introdurre almeno le basi del WQL
IL WQL, OVVERO
LSQL DEL WMI
Incredibile come gli acronimi si moltiplichino lun-
go la stesura di questo articolo, ma inevitabile.
Per non bisogna farsi impressionare, molto pi
semplice di quanto non appaia in realt.
Secondo la documentazione ufficiale Microsoft,
infatti, il WQL un sottoinsieme dellANSI Sql con
alcune piccole modifiche semantiche.
In effetti chi gi mastica di Sql non trover nessu-
na difficolt a padroneggiare il Wql fin da subito,
mentre chi dovesse cominciare direttamente con
questultimo trover una curva di apprendimen-
to leggermente pi alta se comparata allSql stan-
dard. A questo punto possiamo tirare le fila di quan-
to detto finora e dare una rappresentazione orga-
nica del WMI tramite quel parallelo che fin da su-
bito abbiamo fatto con i normali DBMS.
Il WMI il DBMS installato nel nostro sistema, i
vari Providers rappresentano i singoli database sul
quale operare mentre le classi WMI forniti dai
Providers rappresentano le tabelle del nostro da-
tabase. Il WMI supporta tre tipi di query WQL, dia-
mo una veloce occhiata a tutte tre:
Fig. 2: La nostra applicazione demo terminata
084-089:072-080 16-07-2008 9:55 Pagina 85
ht t p: / / www. i opr ogr ammo. i t
SISTEMA M
G
86
/Settembre 2008
Utilizzo di Windows Management Instrumentation
G Data Query. Queste query sono le pi semplici e
si presentano in questa forma: SELECT [Campi]
FROM [Classe] WHERE [Campo] =/LIKE [Valore]
AND/OR . Sostanzialmente identica alle query di
selezione dellSQL.
G Event Query. Queste query sono molto pi po-
tenti se usate correttamente. Le Event Query crea-
no una temporanea richiesta di notifica su un
evento che viene notificata, appunto, ogniqual-
volta listanza di una classe viene creata, modifi-
cata o eliminata. La forma di questa query la se-
guente: SELECT [Campi] FROM [Evento] WHERE
TargetInstance ISA [Classe] AND Tar-
getInstance.[Campo] =/LIKE [Valore] AND/OR .
La sintassi si complica un po ma alla fine ab-
bastanza chiaro il senso. Levento che vogliamo
monitorare potrebbe essere la creazione di una
classe, e allora al posto di [Evento] scriveremo
__InstanceCreationEvent, ma potremmo voler es-
sere notificati anche per la distruzione o la mo-
difica. Notiamo luso della keyword TargetInstance
che rappresenta listanza delloggetto dei cui cam-
pi siamo interessati. In questo modo possiamo
riferirci ad esso nella query anche se tale oggetto
non ancora stato istanziato. Allo stesso modo,
la keyword ISApermette di riferire la query solo ad
uno specifico tipo di oggetto, selezionando la clas-
se di appartenenza.
G Schema Query. Semplicisticamente parlando
queste query permettono di conoscere quali
informazioni sono disponibili per le nostre query
di tipo Data o Event. Proprio come in ogni DBMS
che si rispetti, si pu far riferimento ai metada-
ti per conoscere a runtime specifiche informazioni
non note in fase di progettazione, anche il WMI
permette una cosa simile. Lutilizzo di tali query
va al di l dello scopo di questo articolo.
Ovviamente il discorso pi articolato e complesso
di quanto fin qui riassunto, ma credo che siamo
comunque riusciti a dare un quadro dinsieme suf-
ficiente per cominciare a impratichirsi con questa
tecnologia.
LEVENT QUERY
PER IL MONITORAGGIO
Come si visto nel precedente paragrafo, lEvent
Query che presenta delle differenze sostanziali ri-
spetto ad una query Sql standard. Ed per questo
che abbiamo voluto costruire lesempio di utilizzo
del WMI intorno a questo tipo di query.
Torniamo alla classe WqlEventQuery allora e ve-
diamo come usarla per costruire la nostra query
Wql. Come gi detto, questa classe rappresenta un
builder, quindi basta settare opportunamente al-
cune delle sue propriet per realizzare la query ne-
cessaria. Nella fattispecie il codice che andremo
ad usare il seguente:
WqlEventQuery q = new WqlEventQuery();
q.EventClassName = "__InstanceOperationEvent";
q.WithinInterval = new TimeSpan(0, 0, 3);
q.Condition = "TargetInstance ISA
'Win32_DiskDrive'";
che produce semplicemente la seguente query Wql:
SELECT * FROM __InstanceOperationEvent WITHIN
3 WHERE TargetInstance ISA 'Win32_DiskDrive'
Lo so gi cosa state pensando: da dove uscita la
keyword WITHIN?
Nel paragrafo precedente non ne ho accennato per-
ch stavamo presentando i vari tipi di query in mo-
do molto superficiale, mentre il trattamento di que-
sta keyword merita un po pi di spazio.
Ma leggiamo prima la query nella sua interezza. In
pratica abbiamo richiesto tutti i campi delle classi di
tipo Win32_DiskDrive che per siano interessate dal-
levento __InstanceOperationEvent.
Questo evento levento padre da cui derivano i tre
eventi: __InstanceCreationEvent, __InstanceDele-
tionEvent e __InstanceModificationEvent. In pratica
levento __InstanceOperationEvent non verr mai
notificato come tale, ma sempre sotto forma di uno
dei tre altri eventi appena introdotti. Vedremo che
tale distinzione importante per capire poi cosa suc-
cede realmente allinterno del filesystem del siste-
ma operativo, in conseguenza di aggiunte o rimo-
zioni o modifiche di dischi e lettori removibili. La
classe Win32_DiskDrive una delle innumerevoli
classi interrogabili tramite WMI e che si trova nel na-
mespace che abbiamo selezionato, essa rappresen-
ta un disk drive esattamente come viene visto dal si-
stema operativo. Si volutamente parlato di disk dri-
ve perch la classe WMI fa riferimento al disco fisi-
co, al dispositivo, e non alle partizioni in esso contenute
. Tramite la query appena scritta, allora, abbiamo ri-
chiesto al WMI di notificarci ogni volta che le istan-
ze della classe Win32_DiskDrive presenti nel name-
space selezionato, si modificano o cambiano di nu-
mero (creazione o eliminazione di istanze). E venia-
mo alla keyword WITHIN. Quando richiediamo al
WMI la notifica di un evento, se questultimo sprov-
visto di un Event Provider che richiami il WMI in
modo asincrono, bisogna specificare lintervallo di
polling con il quale controllare levento stesso.
Nel caso specifico, gli eventi che vogliamo monito-
rare sono sprovvisti di un Event Provider asincrono e
bisogna quindi interrogare lo stato dei dischi ad in-
tervalli regolari. Per fare ci bisogna specificare
lintervallo di tempo allinterno della query. Nel no-
stro esempio abbiamo usato 4 secondi. Questo si-
gnifica, ad esempio, che se un drive viene inserito e
084-089:072-080 16-07-2008 9:55 Pagina 86
ht t p: / / www. i opr ogr ammo. i t
M SISTEMA
Settembre 2008/
87
G
Utilizzo di Windows Management Instrumentation
poi rimosso durante il periodo in cui non stiamo in-
terrogando, ossia in quei 4 secondi di intervallo tra
una richiesta e la successiva, noi non verremo mai
notificati di tali eventi. Ovviamente possiamo ab-
bassare il timing del polling per rendere la grana mol-
to pi fine e per intercettare anche i cambiamenti
pi repentini. Inutile dire che ci va a caricare il si-
stema e quindi a pregiudicare le prestazioni. Abbia-
mo quindi trovato che 4 secondi siano un intervallo
accettabile.
LA CLASSE WMIDISK
Siamo pronti a creare la nostra classe a cui affidare il
compito di notificarci quando un dispositivo remo-
vibile stato inserito o rimosso. Apriamo il nostro fi-
do Visual Studio, e creiamo un nuovo progetto C#.
In particolare una semplice applicazione Windows
Forms, chiamiamola WMIRemovable. Come al soli-
to Visual Studio configurer il progetto aggiungen-
do in automatico una form. Noi prima, per. creiamo
una nuova classe e chiamiamola WMIDisk.
Tale classe ben si presta ad essere un Singleton, sia
perch le informazioni in essa contenuta non di-
pendono dalla singola istanza della stessa, sia per-
ch la notifica degli eventi che questa classe forni-
sce un lavoro che, come abbiamo visto, consuma ri-
sorse di CPU e quindi avere pi di unistanza di tale
classe in giro per lapplicazione sarebbe contropro-
ducente oltrech inutile.
Di seguito il codice che definisce la classe mondata
dellimplementazione dei singoli metodi:
public delegate void MediaInsertedDelegate(object
sender, Object o);
public delegate void MediaRemovedDelegate(object
sender, Object o);
class WMIDisk:IDisposable
{
private static WMIDisk _instance;
private ManagementEventWatcher watcher;
private void EventArrived(Object sender,
EventArrivedEventArgs e);
private WMIDisk();
public event MediaInsertedDelegate MediaInserted;
public event MediaRemovedDelegate MediaRemoved;
public static WMIDisk getInstance()
public void Dispose()
}
Come si vede la classe, nella sua struttura, vera-
mente semplice. Poich un Singleton, il costrut-
tore privato ed stato inserito il metodo pubbli-
co getInstance() per recuperare listanza e utiliz-
zare loggetto. La presenza dei due delegati di fun-
zione serve a permettere alla nostra classe di rea-
lizzare i due eventi MediaInsertede MediaRemoved
ai quali si possono sottoscrivere gli utilizzatori di ta-
le classe. Tutto il lavoro diviso tra il costruttore
e il metodo/handler EventArrived. Il costruttore
realizzato in questo modo:
private WMIDisk()
{
ManagementScope scope = new
ManagementScope("root\\CIMV2");
try
{
WqlEventQuery q = new WqlEventQuery();
q.EventClassName =
"__InstanceOperationEvent";
q.WithinInterval = new TimeSpan(0, 0, 4);
q.Condition = "TargetInstance ISA
'Win32_DiskDrive'";
watcher = new
ManagementEventWatcher(scope, q);
watcher.EventArrived += new
EventArrivedEventHandler(EventArrived);
watcher.Start();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Sappiamo gi cosa lo scope ed il significato del
path che passiamo al costruttore. Abbiamo gi an-
che introdotto il codice che costruisce la nostra
query WQL. La parte nuova solo quella relativa
alla classe ManagementEventWatcher.
Listanza di tale classe viene memorizzata nella va-
riabile membro watcher perch poi, successiva-
mente, tale variabile verr utilizzata dal metodo
Dispose() per liberare le risorse. Essa inizializza-
ta passando al costruttore della classe listanza del-
la classe ManagementScope e listanza della classe
WqlEventQuery. A questo punto non resta che re-
gistrare il nostro handler per levento EventArrived,
messo a disposizione dal ManagementEventWatcher,
per far si che al verificarsi dellevento che abbia-
mo selezionato in query venga richiamato il no-
stro handler. Dopodich facciamo partire la ri-
chiesta con il metodo Start().
Il nostro handler per la gestione dellevento an-
chesso molto semplice, vediamone il codice:
private void EventArrived(Object sender,
EventArrivedEventArgs e)
{
ManagementBaseObject mobj =
(ManagementBaseObject)e.NewEvent.Properties["Tar
getInstance"].Value;
NOTA
TECNICA
DI POLLING
Il polling una tecnica di
verifica ciclica orientata al
monitoraggio dei dispositivi
di input/output presenti in
un sistema. In pratica il
sistema interroga il
complesso di periferiche ad
intervalli regolari e ne
registra i cambiamenti.
Chiaramente questa tecnica
comporta degli svantaggi, il
maggiore dei quali lo
spreco di cicli CPU a vuoto
nel caso nessun
cambiamento si sia
verificato. Non solo, la
scelta dellintervallo con cui
fare questi controlli
spesso un compromesso
tra esigenze contrapposte
quali la precisione del
controllo avverso il carico
del processore.
084-089:072-080 16-07-2008 9:55 Pagina 87
ht t p: / / www. i opr ogr ammo. i t
//siamo interessati ai dischi rimovibili e ai cdrom
if ((String)mobj.Properties["InterfaceType"].Value
== "USB")
{
//Dobbiamo risalire al path Logico del DiskDrive
ManagementObject mbj = new
ManagementObject("Win32_DiskDrive.DeviceID='" +
mobj.Properties["DeviceID"].Value + "'");
String DevicePath="";
foreach (ManagementObject o in
mbj.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject oo in
o.GetRelated("Win32_LogicalDisk"))
{
DevicePath = (String)
oo.Properties["Name"].Value;
break;
}
break;
}
switch (e.NewEvent.ClassPath.RelativePath)
{
case "__InstanceModificationEvent":
if (mobj.Properties["Size"].Value
!= null)
{
if (this.MediaInserted != null)
this.MediaInserted(this,
(Object)DevicePath);
}
else
if (this.MediaRemoved != null)
this.MediaRemoved(this, null);
break;
case "__InstanceCreationEvent":
if (this.MediaInserted != null)
this.MediaInserted(this,
(Object)DevicePath);
break;
case "__InstanceDeletionEvent":
if (this.MediaRemoved != null)
this.MediaRemoved(this, null);
break;
}
}
}
La prima cosa da fare recuperare listanza dellog-
getto che ha generato levento. Tale istanza memo-
rizzata nella variabile di tipo EventArrivedEventArgs
passata dal generatore di eventi al nostro handler. Il
namespace System.Management mette a disposi-
zione la classe ManagementBaseObject e la sua de-
rivata ManagementObject per gestire gli oggetti WMI.
Una volta recuperata la classe WMI, possibile poi
accedere alle sue propriet. In questo modo possia-
mo verificare, come nel nostro caso, se listanza del-
loggetto che ha generato levento sia relativa ad un
disk drive che abbia linterfaccia USB. Cos facendo
abbiamo ristretto il nostro campo di azione ai dischi
rimovibili tipo pendrive, hard disk esterni e memory
card. Non che questa scrematura sia necessaria, an-
zi potrebbe essere superflua se si volesse estendere la
gestione di questi eventi anche allinserimento o al-
la rimozione di CD e DVD, ma indubbio che la fa-
cilit con la quale otteniamo certe informazioni di
notevole interesse.
Prima di gestire levento in s, dobbiamo recupera-
re uninformazione che non memorizzata nella
classe che ha generato levento. Dalla documenta-
zione ufficiale infatti, si evince che in nessuna delle
propriet della classe Win32_DiskDrive memoriz-
zato il path del dispositivo (E:, F: o altra lettera..) e in
effetti non potrebbe essere altrimenti visto che, come
detto, la classe si riferisce ad un dispositivo fisico e
non alle unit logiche in esso contenute. Il nostro
scopo, invece, quello dicomunicare la lettera del
path del dispositivo che si connette. questo ci far
addentrare un altro pochino nella gestione degli og-
getti WMI. Quello che ci serve lutilizzo del metodo
GetRelated() della classe ManagementObject. Tale
metodo restituisce una collezione di altri oggetti di ti-
po ManagementObject che risultano essere in qual-
che modo correlati alloggetto chiamante. Nel no-
stro caso noi vogliamo risalire alloggetto di tipo
Win32_LogicalDisk correlato alloggetto Win32_
DiskDriveche ha generato levento. Per prima cosa per
dobbiamo recuperare listanza delloggetto di tipo
ManagementObject relativo alla classe WMI che ha
generato levento. Come abbiamo visto infatti dagli
argomenti passati allevent handler siamo risaliti al-
loggetto relativo che per di tipo Management-
BaseObject. Tale oggetto manca del metodo di cui
abbiamo bisogno e quindi ci costringe al recupero
della classe derivata. Questo viene fatto dalla por-
zione di codice che riportiamo sotto per chiarezza:
//Dobbiamo risalire al path Logico del DiskDrive
ManagementObject mbj = new
ManagementObject("Win32_DiskDrive.DeviceID='" +
mobj.Properties["DeviceID"].Value + "'");
In pratica istanziamo un oggetto di tipo Manage-
mentObject passando al costruttore una stringa che
rappresenta sia il tipo di oggetto che vogliamo recuperare
(Win32_DiskDrive) sia lid di tale oggetto, che cono-
sciamo, in modo da recuperare proprio listanza del-
loggetto che ci interessa. A questo punto possiamo
utilizzare il metodo GetRelated() al quale passiamo
come argomento il tipo di classe correlata che voglia-
mo recuperare. In pratica per recuperare listanza del-
la classe Win32_LogicalDisk correlata al nostro og-
getto padre dobbiamo passare per unaltra classe cor-
SISTEMA M
G
88
/Settembre 2008
Utilizzo di Windows Management Instrumentation
084-089:072-080 16-07-2008 9:55 Pagina 88
ht t p: / / www. i opr ogr ammo. i t
relata che la Win32_DiskPartition. Ultima nota a
margine di questo processo che, poich per ogni
classe Win32_DiskDrive pu essere associata a pi
Win32_DiskPartition e per ognuna di queste posso-
no essere associate pi Win32_LogicalDisk, abbiamo
strutturato il doppio ciclo foreach in modo da recu-
perare le informazioni relative alle prime occorrenze.
Ovviamente, se si vogliono gestire casi particolari co-
me la rimozione o linserimento di dispositivi che pre-
sentano pi partizioni o pi associazioni di lettere,
questa la parte di codice da affinare per gestire tut-
te le possibilit.
A questo punto non ci resta che capire quale tipo di
evento abbia chiamato levent handler, e regolarci di
conseguenza.
Come gi detto, non abbiamo sottoscritto levento
__InstanceOperationEvent che, per, verr notificato
come uno dei tre eventi figli: __InstanceCreationEvent,
__InstanceDeletionEvent e __InstanceModification-
Event.
Quello che fa il resto del codice proprio questo: re-
cuperare il tipo di evento che ha richiamato lhandler
e notificare a propria volta levento corrispondente
della nostra classe. Restano da illustrare solo gli ultimi
due metodi che, come si vede, sono veramente sem-
plici:
public static WMIDisk getInstance()
{
if (_instance == null)
{
_instance = new WMIDisk();
}
return _instance;
}
public void Dispose()
{
watcher.Stop();
}
Il metodo getInstance() restituisce lunica istanza del-
la classe WMIDisk se c, altrimenti ne istanzia una,
il metodo Dispose(), invece, ferma lesecuzione del
watcher liberando cos le risorse del sistema.
ESEMPIO DI UTILIZZO
La nostra classe completata. Adesso possiamo
utilizzarla per monitorare i dispositivi removibili.
Rinominiamo la form e chiamiamola WMIDetect,
il codice dellintera classe sar il seguente:
public partial class WMIDetect : Form
{
private WMIDisk p;
public WMIDetect()
{
InitializeComponent();
p = WMIDisk.getInstance();
p.MediaInserted += new
MediaInsertedDelegate(p_MediaInserted);
p.MediaRemoved += new
MediaRemovedDelegate(p_MediaRemoved);
}
private void p_MediaInserted(Object sender,
Object o)
{
MessageBox.Show("Rilevato nuova unit
logica: " + (String)o, "Informazione");
}
private void p_MediaRemoved(Object sender,
Object o)
{
MessageBox.Show("Unit logica rimossa",
"Informazione");
}
protected override void
OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
p.Dispose();
}
}
Come si vede, lattivazione del monitor avviene al-
linterno del proprio costruttore.
Richiamiamo listanza e aggiungiamo agli eventi i no-
stri handler, che nella fattispecie non faranno niental-
tro che mostrare a video una MessageBox relativa al-
linserimento o alla rimozione.
Inoltre intercettiamo levento OnClosing della from
in modo da poter chiamare il metodo Dispose della
classe WMIDisk che libera le risorse utilizzate dal wat-
cher. Abbiamo utilizzato la strategia del BOXINGe UN-
BOXINGper il parametro degli event handler perch
in questo modo ci siamo dati libert per eventuali
espansioni future. Ad esempio si potrebbe fare in mo-
do che, anzich passare la stringa contenente il path
del drive appena inserito, sia fornita una struttura o
un oggetto che contenga anche altre informazioni,
come lo spazio disponibile e quello totale.
CONCLUSIONI
Le classi WMI sono talmente tante e le applicazio-
ni possibili cos varie da poter dire, senza ombra
di dubbio, che ci che abbiamo mostrato in questo
articolo non graffia nemmeno un po la superficie
di questo vastissimo argomento. Per speriamo di
aver contribuito ad indicare la strada e a fare un
po di chiarezza su di un argomento ancora poco co-
nosciuto e decisamente molto affascinante.
Giovanni Ascione
M SISTEMA
Settembre 2008/
89
G
Utilizzo di Windows Management Instrumentation
LAUTORE
Giovanni, Paolo Ascione,
ingegnere informatico
Software Architect presso
la Soft4Minds s.r.l. di Torre
del Greco (NA), societ che
si occupa di consulenza e
sviluppo software in
ambito controllo accessi e
sistemi embedded
(www.soft4minds.com).
Ama la programmazione
ad ogni livello, su ogni
piattaforma e sviluppa da
pi di quindici anni.
Per segnalazioni o
suggerimenti pu essere
contattato via mail
allindirizzo:
gpascione@soft4minds.
com
084-089:072-080 16-07-2008 9:55 Pagina 89
DATABASE COME
ISTANZE DI PYTHON
SQLALCHEMY UN NUOVO OBJECT-RELATIONAL MAPPER CHE OFFRE AGLI SVILUPPATORI,
STANCHI DEI SOLITI APPROCCI ALLE BASIDATI, UN NUOVO MODO DI PENSARE E CONCEPIRE
IL CODICE E L'SQL, SFRUTTAND UN UNICO STRUMENTO INTEGRATO
ht t p: / / www. i opr ogr ammo. i t
M DATABASE
Settembre 2008/
91
G
LObject Relational Model SQLAlchemy
A
vete mai ideato un sistema di template
per costruire automaticamente query in
SQL, oppure vi siete mai imbattuti in pro-
blemi d'inserimento automatico di valori tramite
query SQL? Siete mai incappati in problemi
migrando da un RDBMS a un altro e siete stati
costretti a modificare la sintassi dello schema o
dei valori?
O, ancora peggio, siete fra quelli che preferiscono
non avere niente a che fare con le basidati SQL
perch queste vi fanno penare?
Se trovate riscontri in questi interrogativi signifi-
ca che questo articolo fa per voi perch proprio
in queste pagine che, con l'ausilio di un ORM di
ultima generazione, esporremo molti metodi
veloci, intuitivi, ma sopratutto interattivi, che vi
introdurranno in un'altra dimensione della pro-
grammazione. Ma prima di tutto, che cos'
l'Object-Relational Mapping?
L'Object-Relational Mapping (ORM) una tec-
nica di programmazione per convertire dati tra
RDBMS e linguaggi di programmazione orien-
tati agli oggetti. Associa, in poche parole, a
ogni operazione, o elemento del database,
alcuni oggetti con adeguate propriet e meto-
di, astraendo l'utilizzo del database dal DBMS
specifico e sconfinando nell'autentica meta-
programmazione, ovvero scrivere i nostri pro-
grammi facendo in modo di interagire o mani-
polare altri programmi o altri componenti del
nostro stesso software, cos come se fossero
dati e instanze del nostro stesso codice.
Da qui capiamo che un ORM altro non che
un modello con il quale mappare una basedati
all'interno del nostro codice, e che la metapro-
grammazione rappresenta per noi un approc-
cio con il quale possiamo astrarre e generaliz-
zare operazioni che richiederebbero laggunta
di centinaia di righe di codice, e quindi un
grosso dispendio di tempo.
Ma ora vediamo come grazie a Python possia-
mo testare queste tecniche senza dover compi-
lare, n utilizzare editor monolitici n
quant'altro all'infuori del terminale.
SCOPRIRE SQLACHEMY
La prima cosa da fare installare SQLAlchemy dal
sito http://www.sqlalchemy.org/download.html oppure,
in maniera ancora pi semplice, sicura ed immedia-
ta, tramite SetupTools (http://cheeseshop.python.org/
pypi/setuptools) che automaticamente, con il coman-
do da terminale easy_install NOMEMODULO
installa l'ultima versione direttamente compatibile
con il nostro interprete Python.
Una volta installato sar bene verificare la versione
visto che release differenti implementano metodi e
classi diverse.
Per farlo basta frugare nella directory d'installazione
di Python nella subdirectory site-packages/ sqlalche-
my, oppure impor Python (d'ora lo chiameremo ter-
minale) e controllarne la versione, cos come avre-
mo modo di vedere nel prossimo paragrafo.
Personalmente consiglio vivamente di utilizzare
ipython, al posto dell'interprete classico, perch
consente, tramite lutilizzo del tasto [TAB] l'auto
completamento del codice e altre scorciatoie indi-
spensabili per chi vuole sostituire il terminale agli
editors avanzati (Python IDE) e trarne beneficio.
Di SQLAlchemy possiamo distinguere tre unit:
G engine, determina quale basedati (RDBMS) utiliz-
zare ed eventualmente le opzioni di connessione.
G mapper, consente di mappare una tabella della
basedati con gli oggetti da noi creati per mezzo di
una classe contenente uno schema
G sessione, la componente che ci consente di scri-
vere nella basedati e funziona come un'autentica
cache intelliggente, prima di salvare risolve dipen-
denze, evita scritture concorrenti, consente l'auto
flush ed , a livello prestazionale, altamente per-
sonalizzabile secondo l'esigenze del nostro modo
di trattare i dati all'interno della nostra applicazio-
ne.
Prima di tutto cerchiamo di capire come connetter-
ci alla basedati tramite l'engine, poi, usando un db
esistente, possiamo momentaneamente dimenti-
carci del mapper e della sessione e utilizzare diretta-
mente delle query SQL.
Conoscenze richieste
Basi di Python e SQL
Software
Windows/Linux,
Python 2.5.x,
SQLAlchemy 0.4.x,
eventualmente iPython
0.x
Impegno
Tempo di realizzazione
REQUISITI
091-097:101-105 16-07-2008 9:58 Pagina 91
ht t p: / / www. i opr ogr ammo. i t
DATABASE M
G
92
/Settembre 2008
LObject Relational Model SQLAlchemy
CREAZIONE DELL'ENGINE
Quello che dovremo fare, inanzitutto, eseguire il
terminale di Python o, ancora meglio, di iPython.
Nel terminale potremo utilizzare il codice in manie-
ra interattiva; questo ci consentir di fare funziona-
re la nostra applicazione mentre la scriviamo.
Questo approccio molto utile per confrontarci in
anteprima con eventuali eccezioni e altri problemi
che solitamente vengono affrontati con le procedu-
re di debug. Noi, invece, direttamente dal terminale,
potremo interagire con la base dati; intanto ecco un
modo veloce per ricavare la versione installata utiliz-
zando iPython:
In [8]: import sqlalchemy
In [9]: sqlalchemy.__version__
Out[9]: '0.4.6'
Come si legge dalle righe, le intestazioni In indicano
il codice da noi immesso e l'intestazione Out,
appunto, l'output. Per chi nuovo del linguaggio,
opportuno conoscere una consuetudine pythoni-
ca dei moduli, e cio che ogni metodo organizza-
to, e in rari casi anche descritto, in un grande dizio-
nario. Quindi, ammesso di voler dare un'occhiata
alla quantit di funzionalit di un modulo, o di una
funzione, basta, nel nostro caso, eseguire sqlalche-
my.__dict__ per avere un'anteprima esaudiente del
contenuto del modulo.
Come gi anticipato SQLAlchemy pu comunicare
con diversi RDBMS, nominati engines, all'interno di
una lista troviamo tutti quelli supportati:
In [15]: sqlalchemy.databases.__all__
Out[15]: ['sqlite', 'postgres', 'mysql', 'oracle', 'mssql',
'firebird']
Ovviamente, ogni volta che genereremo un'istanza
per configurare l' RDBMS, sar doveroso avere pre-
cedentemente installato il modulo che lo supporti,
per ogni DB sono necessari i seguenti moduli:
G Postgres: psycopg2
G SQLite: pysqlite
G MySQL: MySQLDB
G Oracle: cx_Oracle
G MS-SQL: pyodbc (recommended) adodbapi
pymssql
G Firebird: kinterbasdb
Informix: informixdb
In [19]: from sqlalchemy import create_engine
In [20]: engine = create_engine('mysql://CupsJobs:,
n!bfgu54h9fs@server.lan:3306/CupsJobs')
da SQLAchemy importiamo soltanto create_engine,
cos da poterlo usare direttamente. Come si intuisce
l'argomento di create_engine una stringa conte-
nente driver://username:password@host:port/database.
Creato l'engine possiamo connetterci:
In [21]: connection = engine.connect()
Una volta connessi, possiamo ricavare il nome dello
schema ed eseguire comandi SQL direttamente
come testo, ecco una lista contenente una tupla dei
nomi delle tabelle presenti:
In [22]: connection.default_schema_name()
Out[22]: 'CupsJobs'
In [23]: connection.execute("SHOW TABLES").
fetchall()
Out[23]: [('CupsJobs', 'Amount', 'Calendar')]
Possiamo quindi alla stessa maniera visualizzare il
contenuto di una singola tabella; soltanto che, inve-
ce di eseguire direttamente il codice, e ottenere il
risultato nello standard output (d'ora in poi stdout-
put), facciamo in modo di attribuire loutput a una
opportuna variabile:
In [24]: cupstbl = connection.execute("desc
CupsJobs")
In [25]: cupstbl.fetchall()
Out[25]:
[('id', 'int(11)', 'NO', 'PRI', None, 'auto_increment'),
('printer_uri', 'varchar(80)', 'YES', '', None, ''),
('job_name', 'varchar(80)', 'YES', '', None, ''),
('job_originating_user_name', 'varchar(12)', 'YES', '',
None, ''),
('job_priority', 'tinyint(3)', 'YES', '', None, ''),
('job_uuid', 'varchar(60)', 'YES', '', None, ''),
('job_originating_host_name', 'varchar(15)', 'YES', '',
None, ''),
COME FACCIO A SCOPRIRE
LE OPZIONI E IL LORO SIGNIFICATO?
La documentazione del codice
solito essere inclusa all'interno
del codice stesso, come
consuetudine di Python. Usando
Ipython possibile leggerla
scrivendo nomefunzione ?
oppure nomefunzione ??. Se
dovesse essere sprovvista
possiamo sempre visualizzarne
il codice aperto con il comando
%psource nomefunzione,
visualizzandolo come in figura,
con formattazione intuitiva,
nonostante sia da terminale.
Con iPython possiamo anche
salvare le nostre instanze su file,
generare macro e richiamarle,
aprire editor di testo, creare dei
veri e propri profili di esecuzione
cos da richiamare direttamente
il lavoro precedentemente fatto
per uno specifico progetto,
ancora supporta il multithread e
consente l'esecuzione di diverse
instanze (pensiamo a form
grafici d'inserimento, o a
produzione di grafici o
statistiche in tempo reale...).
091-097:101-105 16-07-2008 9:58 Pagina 92
ht t p: / / www. i opr ogr ammo. i t
M DATABASE
Settembre 2008/
93
G
LObject Relational Model SQLAlchemy
('time_at_creation', 'int(12)', 'YES', '', None, ''),
('time_at_processing', 'int(12)', 'YES', '', None, ''),
('time_at_completed', 'int(12)', 'YES', '', None, ''),
('job_id', 'int(30)', 'YES', '', None, ''),
('job_state', 'tinyint(4)', 'YES', '', None, ''),
('job_media_sheets_completed', 'tinyint(3)', 'YES', '',
None, ''),
('job_printer_uri', 'varchar(60)', 'YES', '', None, ''),
('job_k_octets', 'int(12)', 'YES', '', None, ''),
('job_hold_until', 'varchar(10)', 'YES', '', None, ''),
('job_sheets', 'varchar(10)', 'YES', '', None, '')]
Come facile notare, questa volta non abbia-
mo appeso subito il metodo .fetchall() al
comando connection.execute(), ma questo
stato eseguito tramite l'attribuizione alla varia-
bile cupstbl; ad alcuni potr sembrare banale
ma per chi inizia con Python, o con la pro-
grammazione in generale, unautentica
manna. Ultimo esempio semplice prima di
proseguire:
In [55]: for V4l0re in connection.execute_text
("SELECT * FROM CupsJobs").fetchone():
....: print V4l0re
1
ipp://server.lan:631/printers/EPSON_Stylus_C48_US
B_2
scheda giardinaggio.ods
slide
50
urn:uuid:0df7c2df-477f-38e6-56d6-b82e7d86c519
192.168.1.99
1193957370
1193957370
1193957668
125
9
1
ipp://server.lan:631/printers/EPSON_Stylus_C48_US B_2
40
no-hold
none
In [55]: connection.close()
Come avrete intuito, la libert nell'utilizzo di Python
estrema, il nome e il tipo della variabile V4l0re non
ha alcun origine n specificazione, la forza di Python
st nel predeterminare le attribuizioni del codice in
base all'utilizzo che si fa di questo. Ma ora giunto il
momento di addentrarci in SQLAlchemy.
CREIAMO E MAPPIAMO
Il pezzo forte di SQLAlchemy l'approccio con il
quale l'intera base dati viene gestita con una map-
patura in codice. Per fare un po' di ordine ed evitar-
vi di rileggere indietro faremo in modo di generare
nuovamente un engine stavolta con SQLite, cos da
stare certi che i prossimi esempi potranno essere
testati in maniera pi immediata.
In [61]: from sqlalchemy import create_engine
In [62]: engine = create_engine
('sqlite:///:memory:', echo=True)
Per quanto riguarda le opzioni della funzione cre-
ate_engine doveroso segnalare che l'opzione echo
valida per ogni tipo di base dati. La stessa attiva la
stampa in stdoutput cos da visualizzare il codice
SQL eseguito di volta in volta, utile a scopo didat-
tico e debug. Molte opzioni sono invece esclusive
per specifici driver, come ad esempio il multithread,
quindi doveroso prendere in considerazione
anche questi aspetti secondo le specificit tecniche
dei singoli RDBMS. Creiamo, quindi, una tabella uti-
lizzando Metadata() di SQLAchemy, questa funzio-
ne consente di rappresentare una collezione di
tabelle e il loro schema per costruirle, su questo
creeremo pi avanti una classe coerente. Ecco la
fase di creazione di una tabella grazie a metadata:
In [71]: from sqlalchemy import Table, Column, Integer,
String, MetaData, ForeignKey
In [72]: metadata = MetaData()
In [73]: db_utenti = Table('utenti', metadata,
....: Column('id', Integer, primary_key=True),
....: Column('nome', String(60)),
....: Column('nick', String(24)),
....: Column('password', String(15)))
Dal modulo importiamo soltanto quello che serve a
parte per ForeignKey che utilizzeremo pi avanti per
dichiarare le relazioni. La funzione Table prende
come argomento il nome della tabella che vogliamo
generare nell'SQL e metadata. Le funzioni Column,
a loro volta, contengono le specifiche per ogni
colonna. Creare ora la tabella pi facile di quanto
si possa pensare:
In [96]: metadata.create_all(engine)
Out [96]: 2008-06-11 16:41:54,545 INFO
sqlalchemy.engine.base.Engine.0x..4c PRAGMA
table_info("utenti")
2008-06-11 16:41:54,545 INFO
sqlalchemy.engine.base.Engine.0x..4c {}
2008-06-11 16:41:54,547 INFO
sqlalchemy.engine.base.Engine.0x..4c
CREATE TABLE utenti (
id INTEGER NOT NULL,
nome VARCHAR(60),
nick VARCHAR(24),
password VARCHAR(15),
PRIMARY KEY (id)
NOTA
LA RAPPRESENTA-
ZIONE DEI DATI
Python utilizza i
namespaces e le variabili
di scopo. Tutti i nomi,
pensiamo a variabili,
instanze, classi e
genericamente tutto ci
che rappresenta un dato,
viene contenuto in un
grande dizionario che, a
sua volta, anchesso un
oggetto. Ricordate che in
Python tutto un oggetto.
Tutto ci che viene
immesso nell'interprete
viene quindi memorizzato
in un dizionario...Provate a
scrivere globals().items()
oppure locals() da
terminale ed ecco tutte le
vostre variabili.
091-097:101-105 16-07-2008 9:58 Pagina 93
ht t p: / / www. i opr ogr ammo. i t
)
2008-06-11 16:41:54,547 INFO
sqlalchemy.engine.base.Engine.0x..4c None
2008-06-11 16:41:54,547 INFO
sqlalchemy.engine.base.Engine.0x..4c COMMIT
Come volevasi dimostrare, l'opzione echo=True si
rivelata estremamente utile, permettendoci di sbir-
ciare utili informazioni di debug. Se, invece, volessi-
mo dare unocchiata nella collezione di metadata
sappiate che metadata.tables un autentico dizio-
nario di Python, quindi spulciarselo per benino
risulta estremamente semplice se si adottano i
metodi appositi per dizionari. Possiamo ora creare
la classe per la tabella SQL utenti:
In [140]: class Utente(object):
def __init__(self, nome, nick, password):
self.nome = nome
self.nick = nick
self.password = password
def __repr__(self):
return "< Utente('%s', '%s', '%s') >" %
(self.nome, self.nick, self.password)
Questa la classe con la quale genereremo istanze
utilizzabili con la nostra tabella, ogni istanza si con-
cretizza come un inserimento di valori nella baseda-
ti. Il metodo __init__ inizializza quindi con i valori
che non possono essere omessi (nome, nick, pas-
sword) mentre il metodo __repr__ ,invece, serve solo
per ottenere una rappresentazione leggibile (human
readable) sotto forma di stringa, cos al richiamo
dell'istanza otteremo un output personalizzato.
Per completare rendendo funzionale questa classe
con i nostri scopi dobbiamo importare il mapper e
caricarci dentro sia la classe per l'inserimento che la
tabella metadata:
In [152]: from sqlalchemy.orm import mapper
In [153]: mapper(Utente, db_utenti)
Out[153]: <sqlalchemy.orm.mapper.Mapper object
at 0x87c664c>
Attivato il mapper sappiamo che ogni oggetto della
classe Utente verr associato alla mappa della
tabella utenti. Un esempio banale delle generazione
dell'oggetto simone:
In [154]: simone = Utente('simone fiorenza', 'boccaccio',
'\ling0tto79!')
In [155]: simone.nome
Out[155]: 'simone fiorenza'
In [156]: simone.nick
Out[156]: 'boccaccio'
In [157]: simone.password
Out[157]: '\\ling0tto79!'
Ora che il mapper pronto possiamo generare la
sessione vera e propria, cos da gestire in cache tutti
gli inserimenti e salvarli nella basedati con ordine,
evitando concorrenze o madornali errori.
LA SESSIONE
COME UNICO OROLOGIO
Il concetto di sessione racchiuso nell' Unit of Work
system; le azioni di creazione, inserimento, update
o rimozione dell'RDBMS in una coda, generando
dipendenze e ordinando le priorit senza che sia il
nostro codice a farlo, in maniera del tutto automati-
ca. Una volta generata tale coda possiamo scarica-
re tutte le nostre azioni nella base dati (.commit()).
Questo si traduce in efficienza, specialmente se i
problemi di concorrenza sorgono nel caso di basida-
ti relazionali molto vaste, con innumerevoli chiavi e
relazioni a cascata:
In [26]: from sqlalchemy.orm import sessionmaker
In [27]: Session = sessionmaker(bind=engine,
autoflush=True, transactional=True)
In [28]: sessione = Session()
L'istanza stata generata con il binding sul nostro
engine e con l'autoflush attivato, coscch nel
momento in cui eseguiamo una query nella baseda-
ti, la sessione eseguir prima il flush (commit()),
quindi memorizzer anche i dati che ancora man-
tiene in coda. Per fare un esempio dell'autoflush
ecco il salvataggio e la seguente query dell'utente
simone nella tabella utenti:
In [30]: sessione.save(simone)
In [32]: sessione.query(Utente).first()
2008-06-11 18:02:10,397 INFO
sqlalchemy.engine.base.Engine.0x..6c BEGIN
2008-06-11 18:02:10,398 INFO
sqlalchemy.engine.base.Engine.0x..6c INSERT INTO
utenti (nome, nick, password) VALUES (?, ?, ?)
2008-06-11 18:02:10,399 INFO
sqlalchemy.engine.base.Engine.0x..6c ['simone fiorenza',
'boccaccio', '\\ling0tto79!']
2008-06-11 18:02:10,401 INFO
sqlalchemy.engine.base.Engine.0x..6c SELECT utenti.id
AS utenti_id, utenti.nome AS utenti_nome, utenti.nick
AS utenti_nick, utenti.password AS utenti_password
FROM utenti ORDER BY utenti.oid
LIMIT 1 OFFSET 0
2008-06-11 18:02:10,401 INFO
sqlalchemy.engine.base.Engine.0x..6c []
Out[32]: < Utente('simone fiorenza', 'boccaccio',
'\ling0tto79!') >
Il salvataggio avvenuto nella basedati soltanto
DATABASE M
G
94
/Settembre 2008
LObject Relational Model SQLAlchemy
091-097:101-105 16-07-2008 9:58 Pagina 94
ht t p: / / www. i opr ogr ammo. i t
quando una query ha fatto specifica richiesta dell'u-
tente simone.
Se la query non avesse avuto luogo, l'utente simone
non sarebbe stato memorizzato nella tabella utenti,
almenoi fino allesecuzione del metodo commit()
della sessione. L'esempio seguente, invece, produce
un nuovo inserimento in utenti e salva manualmen-
te, tramite commit(), nella sessione, di conseguenza
nella tabella dell'RDBMS.
In [35]: myscelino = Utente('michelino', 'miscelino',
'87fgd8fygsfg')
In [37]: sessione.save(myscelino)
In [38]: sessione.commit()
2008-06-11 18:05:48,517 INFO
sqlalchemy.engine.base.Engine.0x..6c INSERT INTO
utenti (nome, nick, password) VALUES (?, ?, ?)
2008-06-11 18:05:48,518 INFO
sqlalchemy.engine.base.Engine.0x..6c ['michelino',
'miscelino', '87fgd8fygsfg']
2008-06-11 18:05:48,519 INFO
sqlalchemy.engine.base.Engine.0x..6c COMMIT
D'ora in poi ometteremo l'echo, cos da rendere
pi ordinati gli esempi (engine.echo = False).
Possiamo anche essere pi sbrigativi scrivendo
sessione.save(User('nome', 'nick', 'passwd')) diver-
se volte ed eseguire sessione.commit() quando
vogliamo scrivere d'un colpo nella tabella.
Un'altra curiosit che se prima di istanziare la
sessione avessimo digitato, ad esempio,
simone.id avremmo avuto un valore di ritorno
simile a questo: 'None', in quanto, non essendo
questi ancora nella basedati, non aveva generato
alcun id.
Provandolo dopo il salvataggio in sessione, inve-
ce, avremo come ritorno l'id autentico.
In[145]: simone.id
Out [145]: 1
Un'altra caratteristica importante di SQL
Alchemy la costruzione di query tramite fun-
zioni. Metodo che consente di includere: espres-
sioni booleane, operatori, alias sulle tabelle, sub-
query, e clausole (come EXISTS e UNION), join
(sia inner che outer) tutt'insieme o separatamen-
te.
Alcuni esempi semplici sulla nostra tabella uten-
ti possono essere cos, applicando filtri sul risul-
tato:
In [251]: for i in sessione.query(Utente).filter_by
(nome='frak', nick='zia'): print unicode(i)
.....:
< Utente('frak', 'zia', 'jhfg807stgfg') >
oppure, ancora, stavolta senza output per questioni
di spazio:
for i in sessione.query(Utente).filter
(Utente.nome=='michelino'): print i
for i in sessione.query(Utente)[1:3]: print i
Per chi nuovo di Python la dicitura [1:3] davanti la
funzione query() indica l'iteratore, e in questo caso il
range dei valori fra il secondo ed il terzo, riportando
quindi solo due utenti (il primo equivale al numero
0, come consuetudine informatica).
Ancora, se volessimo scoprire tutti gli utenti che
hanno settato la password con il loro stesso nome
(!):
In [291]: vulnerabili = sessione.query(Utente).filter
((Utente.password == Utente.nome))
In [292]: vulnerabili.all()
Out[292]: [< Utente('francy', 'francy', 'francy') >]
oppure, se volessimo conoscere quali utenti hanno
fra le loro password nomi o diciture particolari pos-
siamo usare la funzione like() e includere la porzio-
ne di stringa da cercare nel risultati tra gli operatori
%%come nell'esempio:
In[293]: for i in sessione.query(Utente).filter
(Utente.nome.like('%fr%')): print unicode(i)
possibile simulare il comportamento degli opera-
tori SQL and e or tramite codice, utilizzando sempre
e specificatamente la nostra sintassi personalizzata.
Di seguito una query composta da pi funzioni in
cui filtriamo gli utenti con l'id minore di 3 oppure
quelli che hanno i nick contenenti i caratteri cio e
mi:
In [83]: from sqlalchemy import and_, or_
In [84]: sessione.query(Utente).filter(
and_(Utente.id<3, or_(Utente.nick.like('%cio%'),
Utente.nome.like('%mi%')))).all()
Come precedentemente accennato, chi invece pre-
ferisce le query SQL pu usufruirne grazie alla fun-
zione from_statement() e alla funzione params() che
consente di includere parametri secondo la nostra
applicazione. Inutile dire che di params() per chi
volesse usare soltanto gli statements SQL non ce n
alcun bisogno, ma preferiamo illustrare quanti pi
operatori possibile:
In [98]: sessione.query(Utente).from_statement
("SELECT * FROM utenti where
nome=:nome").params(nome='michelino').all()
Oltre alla funzione all(), che riporta tutti i risultati,
possiamo utilizzare anche one() o first().
M DATABASE
Settembre 2008/
95
G
LObject Relational Model SQLAlchemy
091-097:101-105 16-07-2008 9:58 Pagina 95
ht t p: / / www. i opr ogr ammo. i t
COSTRUIRE RELAZIONI
Ora che abbiamo preso dimistichezza, possiamo
proseguire con l'ampliamento della basedati, senza
tralasciare un aspetto molto importante, che riguar-
da le relazioni.
Iniziamo con una relazione da uno a molti, pren-
dendo in considerazione una nuova tabella che con-
tiene le mansioni degli utenti, considerando che
ognuno di questi ne pu svolgere di diverse.
In [98]: from sqlalchemy import ForeignKey
In [99]: db_lavoro = Table('lavoro', metadata,
Column('id', Integer, primary_key=True),
Column('impiego', String(100), nullable=False),
Column('id_utente', Integer, ForeignKey('utenti.id')))
In [100]: metadata.create_all(engine)
CREATE TABLE lavoro (
id INTEGER NOT NULL,
impiego VARCHAR(100) NOT NULL,
id_utente INTEGER,
PRIMARY KEY (id),
FOREIGN KEY(id_utente) REFERENCES utenti (id)
)
ForeignKey nella dichiarazione della nuova tabel-
la (abbiamo riattivato l'Echo per visualizzare
l'output in SQL) configura la relazione tra gli id
della tabella utenti e la colonna id_utente della
tabella lavoro. Non dimentichiamoci che per
visionare la struttura di ogni singola tabella,
basta richiamare dal terminale il nome della
variabile con la quale l'avete dichiarata (nel
nostro caso db_utenti e db_lavoro). Per essere
certi di non fare confusione, approfittiamo della
creazione di una nuova tabella per terminare la
sessione ORM corrente e svuotare il mapper:
In [101]: from sqlalchemy.orm import clear_mappers
In [102]: sessione.close()
In [103]: clear_mappers()
Fatto questo creiamo la classe che configura
l'inserimento nella nuova tabella lavoro e ricarichia-
mo il mapper, questa volta specificando la relazione
fra le due tabelle. Per creare la relazione sar neces-
sario importare relation:
In[110]: from sqlalchemy.orm import relation
In [111]: class Lavoro(object):
def __init__(self,impiego):
self.impiego = impiego
def __repr__(self):
return "< Lavoro('%s')>" % self.impiego
E ora il mapper:
In [117]: mapper(Utente, db_utenti, properties={
'lavoro':relation(Lavoro, backref='utenti')
})
In [118]: mapper(Lavoro, db_lavoro)
Ricordiamo che i nomi delle tabelle SQL, all'in-
terno della basedati, sono 'utenti' e 'lavoro' men-
tre i nomi all'interno del mapper in riferimento
alle nostre classi sono Utente e Lavoro.
Una volta mappata la classe possiamo giocare
con la nuova tabella e con le nuove relazioni,.
Ecco alcuni esempi di come funziona la relazio-
ne uno a molti e dell'utilit, non ancora com-
prensibile, del valore backref dichiarato nel map-
per. Questo genera una relazione bidirezionale,
cos da ottenere allo stesso tempo una relazione
molti a uno in modo automatico, come si intui-
sce dalla riga 54. Creiamo nuovo utente:
In [41]: laura = Utente('laura', 'lauretta',
'jhgdfv9ueytehgh')
L'utente laura non ha lavoro (linea 42), quindi le
diamo ben due lavori:
In [42]: laura.lavoro
Out[42]: []
In [43]:
laura.lavoro.append(Lavoro(impiego='segretaria'))
In [44]: laura.lavoro
Out[44]: [< Lavoro('segretaria')>]
In [46]:
laura.lavoro.append(Lavoro(impiego='operatore'))
In [47]: laura.lavoro
Out[47]: [< Lavoro('segretaria')>, <
Lavoro('operatore')>]
Per comprendere backref possiamo appendere il
metodo utenti. Selezionando con l'iteratore,
come nell'esempio successivo, quale lavoro di
laura ci interessa, se il primo o il secondo fra i
risultati, possiamo scoprire tutti gli utenti ai
quali corrisponde un lavoro uguale. Questo ci
consente di sfruttare le relazioni bidirezionali:
In [54]: laura.lavoro[0].utenti
Out[54]: [< Utente('laura', 'lauretta', 'jhgdfv9ueytehgh')
>, < Utente('marika', 'kika', 'hgh4398fdf!!')>]
Notiamo che con l'utente laura non abbiamo
eseguito alcuna query nella basedati vera e pro-
pria (infatti non abbiamo usato la sessione!),
quindi non ci resta che memorizzare il tutto nella
sessione e quindi nella tabella. Se invece avessi-
mo fatto una query (quindi tramite la sessione)
l'autoflush attivo avrebbe prima inserito i valori
da noi appena dichiarati e poi esposto i risultati
come visto per l'utente simone. A ogni modo,
ricarichiamo la sessione come abbiamo fatto nel
DATABASE M
G
96
/Settembre 2008
LObject Relational Model SQLAlchemy
091-097:101-105 16-07-2008 9:58 Pagina 96
ht t p: / / www. i opr ogr ammo. i t
precedente paragrafo e salviamo nella tabella:
In [55]: sessione.save(laura)
In [56]: sessione.commit()
2008-06-12 13:02:05,513 INFO
sqlalchemy.engine.base.Engine.0x..2c BEGIN
2008-06-12 13:02:05,515 INFO
sqlalchemy.engine.base.Engine.0x..2c INSERT INTO
utenti (nome, nick, password) VALUES (?, ?, ?)
2008-06-12 13:02:05,515 INFO
sqlalchemy.engine.base.Engine.0x..2c ['laura',
'lauretta', 'jhgdfv9ueytehgh']
2008-06-12 13:02:05,517 INFO
sqlalchemy.engine.base.Engine.0x..2c INSERT INTO
lavoro (impiego, id_utente) VALUES (?, ?)
2008-06-12 13:02:05,517 INFO
sqlalchemy.engine.base.Engine.0x..2c ['segretaria', 3]
2008-06-12 13:02:05,518 INFO
sqlalchemy.engine.base.Engine.0x..2c INSERT INTO
lavoro (impiego, id_utente) VALUES (?, ?)
2008-06-12 13:02:05,518 INFO
sqlalchemy.engine.base.Engine.0x..2c ['operatore', 3]
2008-06-12 13:02:05,520 INFO
sqlalchemy.engine.base.Engine.0x..2c COMMIT
QUERY RELAZIONALI
Con le relazioni fra pi tabelle possiamo quindi
effettuare join con una impressionante libert
sintattica grazie alla moltitudine di operatori che
SQLAlchemy mette a disposizione.
Appendendoli a nostro piacimento s'intende:
In[62]:sessione.query(Utente).filter(Utente.id==Lavoro.
id_utente).filter(Lavoro.impiego=='segretaria').all()
Out[62]: [< Utente('laura', 'lauretta', 'jhgdfv9ueytehgh')
>, < Utente('marika', 'kika', 'hgh4398fdf!!')>]
In [84]: sessione.query(Utente).select_from
(db_utenti.join(db_lavoro)).filter(Lavoro.impiego=
='operatore').all()
Out[84]:
[< Utente('laura', 'lauretta', 'jhgdfv9ueytehgh') >,
< Utente('mirko crosia', 'ko', 'jhgdffgufgh') >]
Allo stesso modo delle query precedenti possia-
mo appendere gli operatori che preferiamo,
quindi produrre query generiche e filtrare a
cascata i risultati, oppure eseguire direttamente
statements in SQL allo stesso modo di come
abbiamo fatto nel paragrafo precedente.
CANCELLAZIONI
E OPERAZIONI A CASCATA
Per cancellare un utente dalla tabella dobbiamo
agire tramite la sessione:
In [85]: sessione.delete(ugo)
In [86]:
sessione.query(User).filter_by(name='ugo').count()
Out [87]: 0
Chi ha esperienza in basi dati sa che cancellare
un utente non significa anche togliere di mezzo
tutte le relazioni figlie, a meno che non venga
specificato nel codice. Se nel caso dell'esempio,
volessimo che anche le mansioni dell'utente ugo
fossero cancellate, potremmo farlo per mezzo
del reload sulla sessione (sessione.rollback()) e il
suo clear (sessione.clear()), per evitare incoerenze
fra i dati nella tabella della basedati e i valori che
il mapper ha caricato dovremmo anche effettua-
re clear_map pers(). Ricordiamo che, per come
gestita la sessione, la rimozione di un utente e
dei suoi valori relazionali in altre tabelle avviene
se a questi ultimi non sono relazionati altri uten-
ti, altrimenti cancellando l'utente laura rimuo-
veremmo anche la mansione segretaria.
Se invece volessimo automatizzare la rimozione
a cascata ecco come dichiarare il mapper per
cancellare, come nel nostro esempio, un utente e
sulla base delle relazioni, anche valori in altre
tabelle, in maniera del tuto automatica.
Ipotizziamo, per questioni di spazio, di aver
generato, come abbiamo visto prima dagli esem-
pi precedenti, una tabella degli indirizzi ai quali
corrispondono univocamente i nostri utenti.
La rimozione di questi ultimi deve contemplare
anche la rimozione dei loro indirizzi, quindi il
mapper fra la tabella dei nostri utenti deve inse-
rire nelle sue propriet anche la relazione alla
classe Indirizzi (della tabella indirizzi, dichiarata
tramite la variabile db_indirizzi) con l'opzione
cascade:
mapper(Utente, db_utenti, properties={
'indirizzi':relation(Indirizzi, backref='utenti',
cascade='all, delete, delete-orphan')})
mapper(Indirizzi, db_indirizzi)
sessione.delete(mirko)
sessione.commit()
Cancellando l'utente mirko tramite la sessione
cancelleremo automaticamente tutte le relazioni
evitando problemi di conflitti o concorrenze.
Ora che abbiamo capito il ruolo degli engines,
del mapper e della sessione, con i dovuti meriti
alle relazioni e alle funzionalit a cascata abbia-
mo tutto il necessario per poter sviluppare siti in
web 2.0, template system o programmi gestiona-
li con terminali.
Giuseppe De Marco
M DATABASE
Settembre 2008/
97
G
LObject Relational Model SQLAlchemy
091-097:101-105 16-07-2008 9:58 Pagina 97
STATO PATRIMONIALE ATTIVO 31/12/2007 31/12/2006 31/12/2007 31/12/2006
A) Crediti verso soci per versamenti ancora dovuti 8) Debiti rappresentati da titoli di credito
9) Debiti verso imprese controllate 728.089 744.847
B) Immobilizzazioni 728.089 744.847
10) Debiti verso imprese collegate
11) Debiti verso controllanti
I. Immateriali 12) Debiti tributari
1) Costi di impianto e di ampliamento 408.275 553.891 - entro 12 mesi 84.920 282.081
2) Costi di ricerca, di sviluppo e di pubblicit 3.914.858 3.070.217 - oltre 12 mesi
3) Diritti di brevetto industriale e di utilizzo di opere dell'ingegno 11.697 6.087 84.920 282.081
4) Concessioni, licenze, marchi e diritti simili 35.000 13) Debiti verso istituti di previdenza e di sicurezza sociale
5) Avviamento - entro 12 mesi 141.505 104.436
- oltre 12 mesi
6) Immobilizzazioni in corso e acconti 300.000 141.505 104.436
7) Altre 14) Altri debiti
4.634.830 3.665.195 - entro 12 mesi 578.486 303.728
II. Materiali - oltre 12 mesi
1) Terreni e fabbricati 1.614.355 1.643.602 578.486 303.728
2) Impianti e macchinario 77.153 53.841
3) Attrezzature industriali e commerciali 22.167 24.035 Totale debiti 26.965.775 30.259.004
4) Altri beni 277.892 333.138
5) Immobilizzazioni in corso e acconti
1.991.567 2.054.616 E) Ratei e risconti
III. Finanziarie - aggio sui prestiti
1) Partecipazioni in: - vari 470.637 520.179
- a) imprese controllate 1.095.205 1.835.838 470.637 520.179
- b) imprese collegate Totale passivo 35.141.135 38.106.178
- c) imprese controllanti
- d) altre imprese Conti d'ordine
1.095.205 1.835.838 1) Sistema improprio dei beni altrui presso di noi 19.586 43.334
2) Crediti 2) Sistema improprio degli impegni 2.614.400 2.614.400
3) Altri titoli 231.506 3) Sistema improprio dei rischi
4) Azioni proprie 4) Raccordo tra norme civili e fiscali
1.095.205 2.067.344 Totale conti d'ordine 2.633.986 2.657.734
Totale immobilizzazioni 7.721.602 7.787.155 Conto economico 31/12/2007 31/12/2006
C) Attivo circolante 31/12/2007 31/12/2006 A) Valore della produzione
I. Rimanenze 1) Ricavi delle vendite e delle prestazioni 47.342.528 45.815.105
1) Materie prime, sussidiarie e di consumo 2) Variazione delle rimanenze di prodotti in lavorazione,
2) Prodotti in corso di lavorazione e semilavorati semilavorati e finiti 50.415 259.837
3) Lavori in corso su ordinazione 3) Variazioni dei lavori in corso su ordinazione
4) Prodotti finiti e merci 3.079.505 3.029.090 4) Incrementi di immobilizzazioni per lavori interni 275.898
5) Acconti 5) Altri ricavi e proventi:
3.079.505 3.029.090 - vari 52.070 81.871
II. Crediti - contributi in conto esercizio
1) Verso clienti - contributi in conto capitale (quote esercizio) 31.592 34.884
- entro 12 mesi 12.951.368 13.645.893 83.662 116.755
- oltre 12 mesi
12.951.368 13.645.893 Totale valore della produzione 47.752.503 46.191.697
2) Verso imprese controllate
- entro 12 mesi 1.471.884 1.325.826 B) Costi della produzione
- oltre 12 mesi 6) Per materie prime, sussidiarie, di consumo e di merci 4.355.310 4.224.328
1.471.884 1.325.826 7) Per servizi 34.539.308 33.719.261
3) Verso imprese collegate 8) Per godimento di beni di terzi 67.211 83.873
4) Verso controllanti 9) Per il personale
4-bis) Per crediti tributari a) Salari e stipendi 2.123.285 1.976.269
- entro 12 mesi 3.778.524 4.460.963 b) Oneri sociali 568.949 466.629
- oltre 12 mesi c) Trattamento di fine rapporto 160.931 145.503
3.778.524 4.460.963 d) Trattamento di quiescenza e simili
4-ter) Per imposte anticipate e) Altri costi
- entro 12 mesi 2.853.165 2.588.401
- oltre 12 mesi 1.619.705 1.811.815 10) Ammortamenti e svalutazioni
1.619.705 1.811.815 a) Ammortamento delle immob. Materiali 3.213.357 3.214.250
5) Verso altri b) Ammortamento delle immobiliz. Materiali 179.394 164.592
- entro 12 mesi 1.043.010 138.855 c) Altre svalutazioni delle immobilizzazioni 319.942
- oltre 12 mesi 4.000 4.000 d) Svalutazioni dei crediti compresi nell'attivo
1.047.010 142.855 circolante e delle disponibilit liquide
3.712.693 3.378.842
20.868.491 21.387.352 11) Variazioni delle rimanenze di materie prime,
sussidiarie, di consumo e merci
III. Attivit finanziarie che non costituiscono Immobilizzazioni 12) Accantonamento per rischi 50.000
6) Altri titoli 45.242 44.242 13) Altri accantonamenti
45.242 44.242 14) Oneri diversi di gestione 125.001 73.772
IV. Disponibilit liquide Totale costi della produzione 45.702.688 44.068.477
1) Depositi bancari e postali 1.025.726 3.159.641
2) Assegni 6.296 365.671 Differenza tra valore e costi di produzione (A-B) 2.049.815 2.123.220
3) Denaro e valori in cassa 41.285 27.775
1.073.307 3.553.087 C) Proventi e oneri finanziari
15) Proventi da partecipazioni:
Totale attivo circolante 25.066.545 28.013.771 16) Altri proventi finanziari:
a) da crediti iscritti nelle immobilizzazioni
D) Ratei e risconti b) da titoli iscritti nelle immobilizzazioni 7.871
- disaggio su prestiti c) da titoli iscritti nell'attivo circolante 4.874 1.011
- varie 2.352.988 2.305.252 d) proventi diversi dai precedenti:
2.352.988 2.305.252 - da imprese controllate
Totale attivo 35.141.135 38.106.178 - da imprese collegate
- da controllanti
Stato patrimoniale passivo 31/12/2007 31/12/2006 - altri 55.686 9.444
68.431 10.455
A) Patrimonio netto 68.431 10.455
I. Capitale 634.230 634.230 17) Interessi e altri oneri finanziari:
- da imprese controllate
II. Riserva da sovrapprezzo delle azioni 4.623.770 4.623.770 - da imprese collegate
- da controllanti
III. Riserva di rivalutazione - altri 520.434 400.402
520.434 400.402
IV. Riserva legale 127.912 64.009 17-bis) Utili e Perdite su cambi 235 161
V. Riserve statutarie Totale proventi e oneri finanziari -451.768 -389.786
VI. Riserva per azioni proprie in portafoglio D) Rettifiche di valore di attivit finanziarie
18) Rivalutazioni:
VII. Altre riserve a) di partecipazioni 85.286 18.062
Riserva straordinaria 1.508.578 1.080.920 b) di immobilizzazioni finanziarie 8.947
Versamenti in conto capitale 23.758 23.758 c) di titoli iscritti nell'attivo circolante
1.532.336 1.104.678 85.286 27.009
19) Svalutazioni:
VIII. Utili (perdite) portati a nuovo a) di partecipazioni 8.765 218.423
b) di immobilizzazioni finanziarie
IX. Utile (perdita) d'esercizio 367.210 491.564 c) di titoli iscritti nell'attivo circolante
Totale patrimonio netto di gruppo 7.285.458 6.918.251 8.765 218.423
Totale patrimonio netto conosolidato 7.285.458 6.918.251 Totale rettifiche di valore di attivit finanziarie 76.521 -191.414
B) Fondi per rischi e oneri E) Proventi e oneri straordinari
1) Fondi di trattamento di quiescenza e obblighi simili 20) Proventi:
2) Fondi per imposte, anche differite - plusvalenze da alienazioni 257.846
3) Altri - varie 6.836 188
Totale fondi per rischi e oneri 264.682 188
21) Oneri:
C) Trattamento fine rapporto di lavoro subordinato 419.265 408.744 - minusvalenze da alienazioni
- imposte esercizi precedenti
D) Debiti - varie 466.937 250.631
1) Obbligazioni 466.937 250.631
2) Obbligazioni convertibili
3) Debiti verso soci per finanziamenti Totale delle partite straordinarie -202.255 -250.443
4) Debiti verso banche
- entro 12 mesi 795.116 6.755.357 Risultato prima delle imposte (A-BCDE) 1.472.313 1.291.577
- oltre 12 mesi 2.196.067 2.935.212
2.991.183 9.690.569 22) Imposte sul reddito dell'esercizio, correnti, differite e anticipate
5) Debiti verso altri finanziatori a) Imposte correnti 912.992 1.198.047
- entro 12 mesi b) Imposte differite (anticipate) 192.111 -398.034
- oltre 12 mesi 1.105.103 800.013
6) Acconti 23) Utile (Perdita) dell'esercizio 367.210 491.564
- entro 12 mesi 8.693.944 7.077.853
- oltre 12 mesi
8.693.944 7.077.853 Prospetto di dettaglio delle voci del Bilancio di Esercizio al 31/12/2007
7) Debiti verso fornitori Ricavi dalla vendita di copie 44.461.565
- entro 12 mesi 13.747.648 12.055.490 di cui per abbonamenti e arretrati 994.345
- oltre 12 mesi Ricavi per vendita di spazi pubblicitari 2.810.843
13.747.648 12.055.490 Servizi e lavorazioni effettuate presso terzi 34.539.308
EDIZIONI MASTER S.p.A
Sede in C.da Lecco Zona Industriale, 64 - 87036 RENDE (CS) Capitale Sociale Euro 634.230,00 I.V.
Bilancio al 31/12/2007
L
evoluzione dei software e la loro crescen-
te complessit negli anni, ha portato alla
necessit di avere una maggiore ingegne-
rizzazione degli stessi. LObject-Oriented
Programming si imposto quasi come uno stan-
dard soppiantando progressivamente la pro-
grammazione procedurale.
Contestualmente si sono evolute le basi di dati,
ora in grado di fornire degli strumenti per la riso-
luzione delle nostre problematiche, con un
modello di tipo relazionale. I due mondi, quello
ad oggetti e quello relazionale, entrano spesso in
conflitto proprio per il diverso approccio.
Il modello a oggetti basato sulla creazione di
classi che rispecchiano il mondo reale ma di
certo non ha modo e non deve fornire la stessa
rappresentazione che viene invece fatta dal
modello relazionale, basato appunto su tabelle e
relazioni tra le stesse.
Questo conflitto ha portato alla necessit di crea-
re uno strato di mapping che si propone come
punto di incontro tra i due mondi, una specie di
ponte in grado di reinterpretare il nostro model-
lo a oggetti nel modello relazionale rappresenta-
to nel nostro database. Per facilitare questo lavo-
ro spesso tedioso, sono nati diversi framework
che nel tempo hanno aiutato gli sviluppatori a
creare e gestire i vari mapping. Uno dei pi famo-
si , senza dubbio, NHibernate, ormai punto di
riferimento, sia in ambienti .NET sia in ambienti
Java con Hibernate.
Microsoft, per la prima volta, con luscita di LINQ
e pi in particolare con luscita di LINQ to SQL ha
proposto un primo framework il cui compito
proprio quello di consentire un accesso rapido ai
database SQL Server. Ma LINQ to Sql stretta-
mente legato a SQL Server e questo costituisce
un limite molto forte in molti scenari.
Con lADO.NET Entity Framework e con LINQ to
Entities, invece, Microsoft supera i limiti gi esi-
stenti con un framework decisamente pi evolu-
to e in grado di supportare le numerose esigenze
di chi si appresta a gestire tutte le problematiche
di accesso ai dati.
A differenza di altri OR/M attualmente in circola-
zione, ADO.NET Entity Framework e LINQ to
Entities sono strumenti totalmente integrati in
Visual Studio 2008 e in questo articolo vedremo
come utilizzarli nelle nostre applicazioni affron-
tando scenari di una applicazione reale.
LADO.NET
ENTITY FRAMEWORK
LADO.NET Entity Framework consente di astrar-
re il modello relazionale in un modello concet-
tuale. Lobiettivo quello di limitare, se non eli-
minare del tutto, le differenze esistenti tra il
mondo relazionale e il mondo a oggetti.
Il fulcro di questo scenario costituito dalle
entit, intese come oggetti i cui dati devono esse-
re manipolati. In una qualsiasi applicazione, ad
esempio, Persona una entit i cui dati (nome,
cognome, data di nascita etc) devono essere
gestiti. A sua volta lentit Persona entra in rela-
zione con altre entit, ad esempio, il Comune,
costituendo, poi, una relazione che porta a otte-
nere il Comune di Nascita o il Comune di
Residenza. ADO.NET Entity Framework permette
di progettare le entit e le loro relazioni, nonch
il mapping che lega le entit con lo schema di
database sottostante. Lobiettivo quello di crea-
re uno strato utilizzabile sia dal nostro codice
nelle nostre applicazioni, ma anche da strumen-
ti e prodotti come i sistemi di reportistica. Per
questo motivo stato scelto, inoltre, di sviluppa-
re un modello di query leggermente differente da
SQL, su cui comunque basato, ma soprattutto
indipendente dai vari dialetti (T-SQL, PLSQL
etc..). Linterrogazione della base di dati quindi
possibile sfruttando questo linguaggio interme-
dio che prende il nome Entity SQL.
Lo svantaggio di questo approccio dovuto alla
necessit di imparare un ulteriore nuovo lin-
guaggio, lEntity SQL appunto. Si pu comunque
ovviare a questo utilizzando LINQ to Entities per
laccesso al database.
UTILIZZARE ADO.NET
ENTITY FRAMEWORK
VISUAL STUDIO 2008 INTEGRA UN ORM MOLTO EVOLUTO CHE PERMETTE DI ASTRARRE
IL MODELLO RELAZIONALE IN UN MODELLO A OGGETTI. TALE TECNICA CONSENTE
DI INTERROGARE UN DB SENZA CONOSCERNE STRUTTURA E RELAZIONI
ht t p: / / www. i opr ogr ammo. i t
M DATABASE
Settembre 2008/
99
G
Interrogare un DB senza conoscerne struttura e relazioni
Conoscenze richieste
Conoscenze base di
programmazione in C#
Software
Visual Studio 2008
Service Pack 1, .NET
Framework 3.5 Service
Pack 1
Impegno
Tempo di realizzazione
REQUISITI
099-103:101-105 16-07-2008 10:03 Pagina 99
ht t p: / / www. i opr ogr ammo. i t
DATABASE M
G
100
/Settembre 2008
Interrogare un DB senza conoscerne struttura e relazioni
COS LINQ TO ENTITIES
LINQ to Entities una implementazione di LINQ
che consente di interagire, come gi accennato,
con lADO.NET Entity Framework (EF) utilizzando
la sintassi comune condivisa e gi disponibile con
gli altri LINQ providers. Il rovescio della medaglia,
sempre presente, dato dal mancato controllo
sulle query generate. Infatti, LINQ to Entities astrae
completamente laccesso, generando per noi il
codice necessario al recupero o al salvataggio dei
dati. La scelta delluso di un metodo o dellaltro
dipende, quindi, da quello che si vuole ottenere e
dal tipo di controllo che si vuole realizzare sul codi-
ce generato. In questo articolo faremo una panora-
mica delle due metodologie di accesso.
COSTRUIAMO
IL DOMAIN MODEL
Creiamo un nuovo progetto e chiamiamolo
Bookshelf. Entities. Aggiungiamo un nuovo ele-
mento di tipo ADO.NET Entity Data Model al pro-
getto appena creato:
generato il file, si avvier il wizard di Visual Studio.
Possiamo quindi scegliere se creare un nuovo
modello, partendo da un nostro disegno, oppure
da un database gi esistente.
In linea generale la procedura dovrebbe prevedere,
come primo passo, la creazione del nostro modello
di dominio e, solo successivamente, la creazione
delle tabelle di database. Tuttavia, nel nostro arti-
colo descriveremo la creazione del Domain Model
(DM) partendo dal database perch attualmente
la funzionalit pi completa dellEF. Andando
avanti nel wizard, selezioniamo il database dal
quale vogliamo partire e quindi le tabelle che
vogliamo trasferire nel nostro DM. Ecco che, dopo
aver creato il progetto, il nostro semplice Domain
Model pu essere rappresentato in questo modo
secondo quanto mostrato in Fig.2. Una volta creato
questultimo, Visual Studio consente di navigare nel
modello attraverso il Model Browser che fornisce la
vista sia dei tipi del mio Domain Model, sia delle
tabelle e delle loro relazioni.
LA CREAZIONE DEL
PROGETTO BOOKSHELF
Nel paragrafo precedente abbiamo creato il nostro
Domain Model, integrandolo in un proget-
to/assembly dedicato.
Creiamo ora il nostro strato di accesso ai dati in un
progetto separato e lo chiamiamo Bookshelf.Data.
Nel progetto aggiungiamo una nuova classe Books
DataService che ha il compito di gestire tutte le
informazioni relative allentit Books.
Possiamo utilizzare le entities cos create utilizzan-
do due differenti modalit.
La prima prevede lutilizzo dellObjectQuery, un
modello di accesso ai dati tipizzato e integrato
nellEntity Data Model:
Fig. 1: La prima fase di creazione di un nuovo
progetto ADO.NET Entity Framework.
Fig. 2: Rappresentazione del Domain Model.
Fig. 3: La struttura completa del nostro progetto.
NOTA
GENERAZIONE DEI
FILE DI MAPPING
Per la generazione dei file
di mapping possibile
anche utilizzare il tool da
riga di comando
EDMGEN.EXE.
Il software genera il file
.edmx ma consente di
fornire ulteriori opzioni di
generazioni. Inoltre,
anche possibile generare i
file di mapping utilizzando
le API contenute
nellassembly
System.Data.Entity.Design.
099-103:101-105 16-07-2008 10:03 Pagina 100
ht t p: / / www. i opr ogr ammo. i t
M DATABASE
Settembre 2008/
101
G
Interrogare un DB senza conoscerne struttura e relazioni
NOTA
DOMAIN MODEL
Un Domain Model la
rappresentazione
concettuale di un sistema.
Nel Domain Model vengono
descritte, infatti, le entit e
le loro relazioni come parte
integrante e fondamentale
del sistema che si vuole
rappresentare.
public class BooksDataService
{
public Books[] GetBooks()
{
BookshelfEntities be = new BookshelfEntities();
ObjectQuery<Books> query = be.CreateQuery
<Books>("SELECT VALUE b FROM Books AS b");
return query.ToArray();
}
}
il secondo quello di utilizzare LINQ to Entities:
public class BookshelfDataService
{
public Books[] GetBooks()
{
BookshelfEntities be = new BookshelfEntities();
var query = from b in be.Books select b;
return query.ToArray();
}
}
ovviamente nel nostro articolo tratteremo esclusi-
vamente laccesso ai dati eseguito attraverso LINQ
to Entities, ma importante sapere che esiste
anche unaltra alternativa.
LENTITY DATA MODEL
Prima di procedere con la descrizione delle funzio-
nalit integrate in LINQ to Entities, cerchiamo di
capire cosa ha generato Visual Studio attraverso
lutilizzo del wizard:
attraverso una rapida occhiata al Solution Explorer
vediamo che sono stati creati due file:
G BookshelfModel.edmx
G BookshelfModel.Designer.cs
il primo file contiene la rappresentazione in XML
del mapping che abbiamo generato attraverso il
wizard. Il file composto da tre sezioni principali:
una rappresentante il modello concettuale (CSDL),
una rappresentante il modello di storage (SSDL) e
la terza rappresentante il mapping (MSL) tra i due
modelli. Possiamo dare uno sguardo al file edmx
per vedere le tre sezioni ben distinte.
Contestualmente stato generato il file Bookshelf
Model.Designer.cs che contiene le classi corrispon-
denti alle nostre entit.
Lunico inconveniente presente relativo al fatto
che le nostre entit devono obbligatoriamente ere-
ditare dalla classe astratta System.Data.Objects.
DataClasses.EntityObject. Questo ci costringe a
introdurre aspetti non strettamente legati al nostro
Domain Model. Il motivo sta nella necessit di
gestire comportamenti come la chiave identificati-
va della mia entit o il tracciamento delle modifi-
che al fine di ottimizzare la fase di update sul data-
base. Comportamenti pi che giusti e che, proba-
bilmente, speriamo, possano cambiare fino al rila-
scio della versione finale dellADO.NET Entity
Framework.
Lentit Books, ad esempio, viene rappresentata
con il codice che segue.
Il codice, per problemi di spazio, stato voluta-
mente proposto in forma sintetica:
[EdmEntityTypeAttribute(NamespaceName="BookshelfM
odel", Name="Authors")]
[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class Authors : EntityObject
{
public static Authors CreateAuthors(Guid idAutore)
[EdmScalarPropertyAttribute(EntityKeyProperty=true,
IsNullable=false)]
[DataMemberAttribute()]
public Guid IdAutore { }
private Guid _IdAutore;
partial void OnIdAutoreChanging(Guid value);
partial void OnIdAutoreChanged();
[EdmScalarPropertyAttribute()]
[DataMemberAttribute()]
public string Nome { }
private string _Nome;
partial void OnNomeChanging(string value);
partial void OnNomeChanged();
[EdmRelationshipNavigationPropertyAttribute("Bookshelf
Model", "Books_Authors", "Books")]
[XmlIgnoreAttribute()]
[SoapIgnoreAttribute()]
[DataMemberAttribute()]
[BrowsableAttribute(false)]
public EntityCollection<Books> Books { }
}
Fig. 4: Il wizard ha creato due file: uno contenente
del codice XML, laltro le classi della nostra entit.
099-103:101-105 16-07-2008 10:03 Pagina 101
ht t p: / / www. i opr ogr ammo. i t
DATABASE M
G
102
/Settembre 2008
Interrogare un DB senza conoscerne struttura e relazioni
da notare, nella classe Authors, luso massivo
degli attributi per definire la propriet chiave, ma
soprattutto per mappare la relazione sulla pro-
priet Books di tipo EntityCollection.
Viene definito, infatti, il namespace della relazione
da utilizzare, la relazione e il destinatario della stes-
sa, nel nostro caso lentit Books.
ARRIVATO IL
MOMENTO DI UTILIZZARE
LINQ TO ENTITIES
Finalmente arriviamo a utilizzare LINQ to Entities.
Dopo aver compreso nel dettaglio il funzionamen-
to dellADO.NET Entity Framework e del suo
modello, vediamo come LINQ pu aiutarci nella
gestione di tutta la parte di accesso ai dati.
LINQ un framework che ci consente di astrarre
completamente laccesso ai dati utilizzando una
sintassi comune.
Parliamo di sintassi comune perch LINQ in
grado di interfacciarsi a qualsiasi sorgente dati, non
necessariamente database ma anche collection,
file XML, Web Service etc.
un framework molto importante la cui semplicit
duso un notevole punto di forza.
La sua sintassi, del tutto simile a quella utilizzata
per la creazione di semplici query SQL.
Come abbiamo visto prima, infatti, la semplice let-
tura di tutti i libri nel nostro database si traduce
nella seguente riga di codice:
var query = from b in be.Books select b;
la query restituisce lelenco completo dei libri con-
tenuti nel database.
Se poi volessimo filtrare la query per autore,
dovremmo semplicemente aggiungere quanto
segue:
public Books[] GetBooks(string authorName)
{
BookshelfEntities be = new BookshelfEntities();
var query = from b in be.Books
where b.Authors.Any(a => a.Nome ==
authorName)
select b;
return query.ToArray();
}
in questo modo la funzione Any valuta se almeno
uno degli elementi della collection soddisfa la con-
dizione che abbiamo imposto. Ipotizzando di inse-
rire lautore Isaac Asimov avremo loutput di
Fig.5:
Catturando la query generata dal codice con SQL
Profiler vedremo il codice riproposto in Fig.6.
Il profiler, molto importante, ci consente di capire
immeditamente quali query vengono generate da
LINQ, consentendoci eventualmente di intervenire
per modificarne in modo opportuno il comporta-
mento.
Nella nostra applicazione, ad esempio, non viene
caricata lentit Publisher associata per ogni singo-
la entit Book che stiamo caricando.
Possiamo decidere di caricare anche le entit asso-
ciate utilizzando il metodo Include, questultimo
parte integrante dellObjectQuery:
Fig. 5: Loutput generato inserendo come autore la
stringa Isacc Asimov
Fig. 6 La query con autore Isaac Asimov cattura-
ta utilizzando SQL Profiler.
ACCESSO AI DATI CON ENTITYCLIENT
Unaltra modalit per laccesso ai
dati in ADO.NET Entity Framework
fornita dallEntityClient.
A differenza delle modalit
esposte nellarticolo, lEntityClient
consente di avere un maggior
controllo sia sul codice sviluppato,
sia sulle query generate. Di
contro, per, lavorando con
Command e con DataReader non
possiamo avere codice strongly-
typed e non possiamo avere come
valori di ritorno le entit stesse.
Vediamo come scrivere la stessa
query scritta nellarticolo
utilizzando per lEntityClient:
EntityConnection cn = new
EntityConnection("Name=Bookshelf
Entities")
cn.Open();
EntityCommand cmd =
cn.CreateCommand();
cmd.CommandText = @"SELECT
VALUE b FROM
BookshelfEntities.Books AS b";
DbDataReader rdr =
cmd.ExecuteReader(Command
Behavior.SequentialAccess);
while (rdr.Read())
{
Console.WriteLine(rdr["Titolo"].
ToString());
}
rdr.Close();
cn.Close();
E evidente la differenza nella
gestione del codice e la
somiglianza con il classico codice
ADO.NET
099-103:101-105 16-07-2008 10:03 Pagina 102
ht t p: / / www. i opr ogr ammo. i t
var query = from b in be.Books.Include("Publishers")
where b.Authors.Any(a => a.Nome ==
authorName)
select b;
in SQL otteniamo cos la query che segue:
SELECT
1 AS [C1],
[Extent1].[IdBook] AS [IdBook],
[Extent1].[ISBN] AS [ISBN],
[Extent1].[Titolo] AS [Titolo],
[Extent1].[Sottotitolo] AS [Sottotitolo],
[Extent1].[Formato] AS [Formato],
[Extent1].[NumberOfPages] AS [NumberOfPages],
[Extent1].[PublicationDate] AS [PublicationDate],
[Extent1].[NotaPrivata] AS [NotaPrivata],
[Extent1].[TitoloCommento] AS [TitoloCommento],
[Extent1].[CorpoDelCommento] AS
[CorpoDelCommento],
[Extent1].[Stato] AS [Stato],
[Extent1].[Stelle] AS [Stelle],
[Extent1].[Etichette] AS [Etichette],
[Extent2].[IdPublisher] AS [IdPublisher],
[Extent2].[Nome] AS [Nome]
FROM [dbo].[Books] AS [Extent1]
LEFT OUTER JOIN [dbo].[Publishers] AS [Extent2] ON
[Extent1].[IdPublisher] = [Extent2].[IdPublisher]
WHERE EXISTS (SELECT
cast(1 as bit) AS [C1]
FROM [dbo].[Books_Authors] AS [Extent3]
INNER JOIN [dbo].[Authors] AS [Extent4] ON
[Extent4].[IdAutore] = [Extent3].[IdAuthor]
WHERE ([Extent1].[IdBook] =
[Extent3].[IdBook]) AND ([Extent4].[Nome] =
@p__linq__2)
In cu, in aggiunta a quanto fatto nella prima query,
viene eseguita una left outer join per recuperare il
Publisher associato.
Nella query abbiamo notato come lelenco degli
autori viene caricato semplicemente perch utiliz-
zato nella query LINQ. Se, invece, non utilizziamo
lelenco degli autori nella query, questo non verr
automaticamente caricato da LINQ.
Per caricarlo sar necessario intervenire da s, solo
quando espressamente necessario e quindi
richiesto dal nostro codice.
Attualmente, lunico modo consentito lutilizzo
del lazy load esplicito, tecnica che appunto ci con-
sente di caricare i dati solo quando strettamente
necessario, ma sotto esplicita richiesta. In Entity
Framwork, e quindi anche in Linq to Entities, si tra-
duce nellutilizzo del metodo .Load():
Utilizzando la tecnica del lazy load esplicito invo-
cando il metodo .Load():
BookshelfEntities be = new BookshelfEntities();
var query = from b in be.Books select b;
foreach (var book in query)
{
book.Authors.Load();
foreach (var author in book.Authors)
{
Console.WriteLine(author.Nome);
......
}
}
solo allora lelenco degli autori sar disponibile e
quindi utilizzabile.
Nelle future versioni sar anche possibile utilizzare
la modalit implicita che non ci costringe ad invo-
care il metodo Load(), ma nasconde il meccanismo
sottostante.
CONCLUSIONI
In questo articolo abbiamo fatto una panoramica
dellADO.NET Entity Framework, lORM di casa
Microsoft che fa discutere le community di svilup-
patori fin dalle sue prime versioni.
Ladozione di un modello basato sulle entit , al
giorno doggi, uno degli approcci pi apprezzati
dai team di sviluppo. Tale metodologia consente,
infatti, di concentrarsi sul dominio del problema in
maniera diretta e soprattuto trasversale, permet-
tendoci di affrontare e rispondere tempestivamen-
te ad una classe di problemi e non pi pensando
alla sua implementazione su db.
Fabio Cozzolino
M DATABASE
Settembre 2008/
103
G
Interrogare un DB senza conoscerne struttura e relazioni
MAPPING MOLTI-A-MOLTI
Uno dei limiti di LINQ to SQL
lassoluta impossibilit di
utilizzare relazioni di tipo molti a
molti. LADO.NET Entity
Framework supera questo limite.
Dando uno sguardo al
diagramma utilizzato
nellarticolo, possiamo notare la
relazione di tipo molti-a-molti
tra Books e Authors
implementata attraverso la
tabella Books_Authors. In questo
modo esprimiamo il fatto che un
libro pu essere scritto da pi
autori e un autore pu scrivere
pi libri. La tabella
Books_Authors, per, non ha
nessuna corrispondenza nel
mondo reale. Nessuna entit
del mondo reale in grado di
rappresentarla e la sua unica
ragione desistere quella di
creare la relazione tra i due
soggetti Books e Authors. Per
questo motivo inserire una
classe che rappresenti la
relazione Books_Authors non ha
alcun senso e non esiste nel
nostro Domain Model.
099-103:101-105 16-07-2008 10:03 Pagina 103
STATO PATRIMONIALE ATTIVO 31/12/2007 31/12/2006 31/12/2007 31/12/2006
A) Crediti verso soci per versamenti ancora dovuti
8) Debiti rappresentati da titoli di credito
B) Immobilizzazioni 9) Debiti verso imprese controllate
10) Debiti verso imprese collegate
I. Immateriali 11) Debiti verso controllanti
1) Costi di impianto e di ampliamento 1.045.207 583.717 12) Debiti tributari
2) Costi di ricerca, di sviluppo e di pubblicit 3.874.858 3.070.217 - entro 12 mesi 167.916 373.860
3) Diritti di brevetto industriale e di utilizzo di opere dell'ingegno 20.382 7.708 - oltre 12 mesi
4) Concessioni, licenze, marchi e diritti simili 35.000 167.916 373.860
5) Avviamento 72.401 77.228 13) Debiti verso istituti di previdenza e di sicurezza sociale
-) Differenza di consolidamento 14.364 881.665 - entro 12 mesi 200.379 167.024
6) Immobilizzazioni in corso e acconti 300.000 122.437 - oltre 12 mesi
7) Altre 10.040 200.379 167.024
5.327.212 4.788.012 14) Altri debiti
II. Materiali - entro 12 mesi 751.933 464.798
1) Terreni e fabbricati 2.045.976 2.086.004 - oltre 12 mesi
2) Impianti e macchinario 82.826 106.565 751.933 464.798
3) Attrezzature industriali e commerciali 392.159 580.930
4) Altri beni 394.226 428.717 Totale debiti 27.331.442 30.476.231
5) Immobilizzazioni in corso e acconti 257.804 35.380
3.172.991 3.237.596
III. Finanziarie E) Ratei e risconti
1) Partecipazioni in: - aggio sui prestiti
- a) imprese controllate - vari 772.629 755.663
- b) imprese collegate 7.000 772.629 755.663
- c) imprese controllanti Totale passivo 36.250.698 38.984.948
- d) altre imprese
7.000 Conti d'ordine
2) Crediti 1) Sistema improprio dei beni altrui presso di noi 19.586 43.334
3) Altri titoli 231.506 2) Sistema improprio degli impegni 2.614.400 2.614.400
4) Azioni proprie 3) Sistema improprio dei rischi
238.506 4) Raccordo tra norme civili e fiscali
Totale conti d'ordine 2.633.986 2.657.734
Totale immobilizzazioni 8.500.203 8.264.114
Conto economico 31/12/2007 31/12/2006
C) Attivo circolante 31/12/2007 31/12/2006
I. Rimanenze A) Valore della produzione
1) Materie prime, sussidiarie e di consumo 1) Ricavi delle vendite e delle prestazioni 48.295.379 46.856.322
2) Prodotti in corso di lavorazione e semilavorati 2) Variazione delle rimanenze di prodotti in lavorazione,
3) Lavori in corso su ordinazione semilavorati e finiti 50.415 259.837
4) Prodotti finiti e merci 3.079.505 3.029.090 3) Variazioni dei lavori in corso su ordinazione
5) Acconti 4) Incrementi di immobilizzazioni per lavori interni 741.428
3.079.505 3.029.090 5) Altri ricavi e proventi:
II. Crediti - vari 41.257 38.919
1) Verso clienti - contributi in conto esercizio 165.109
- entro 12 mesi 14.355.222 15.061.897 - contributi in conto capitale (quote esercizio) 83.470 128.571
- oltre 12 mesi 124.727 332.599
14.355.222 15.061.897
2) Verso imprese controllate Totale valore della produzione 49.211.949 47.448.758
3) Verso imprese collegate
4) Verso controllanti B) Costi della produzione
4-bis) Per crediti tributari 6) Per materie prime, sussidiarie, di consumo e di merci 4.371.695 4.230.357
- entro 12 mesi 3.992.382 4.520.282 7) Per servizi 33.627.415 32.915.978
- oltre 12 mesi 8) Per godimento di beni di terzi 160.667 156.161
3.992.382 4.520.282 9) Per il personale
4-ter) Per imposte anticipate a) Salari e stipendi 3.234.909 3.106.721
- entro 12 mesi b) Oneri sociali 860.518 735.150
- oltre 12 mesi 1.632.263 1.811.815 c) Trattamento di fine rapporto 244.398 225.047
1.632.263 1.811.815 d) Trattamento di quiescenza e simili
5) Verso altri e) Altri costi
- entro 12 mesi 1.047.160 140.005 4.339.825 4.066.918
- oltre 12 mesi 4.000 4.000 10) Ammortamenti e svalutazioni
1.051.160 144.005 a) Ammortamento delle immob. Materiali 3.488.408 3.284.807
b) Ammortamento delle immobiliz. Materiali 431.160 705.046
21.031.027 21.537.999 c) Altre svalutazioni delle immobilizzazioni 319.942
d) Svalutazioni dei crediti compresi nell'attivo
III. Attivit finanziarie che non costituiscono Immobilizzazioni circolante e delle disponibilit liquide
6) Altri titoli 85.392 84.392 4.239.510 3.989.853
85.392 84.392 11) Variazioni delle rimanenze di materie prime,
sussidiarie, di consumo e merci
IV. Disponibilit liquide 12) Accantonamento per rischi 50.000
1) Depositi bancari e postali 1.123.211 3.240.256 13) Altri accantonamenti
2) Assegni 6.296 365.671 14) Oneri diversi di gestione 143.860 102.080
3) Denaro e valori in cassa 49.305 43.323
1.178.812 3.649.250 Totale costi della produzione 46.932.972 45.461.347
Totale attivo circolante 25.374.736 28.300.731 Differenza tra valore e costi di produzione (A-B) 2.278.977 1.987.411
D) Ratei e risconti C) Proventi e oneri finanziari
- disaggio su prestiti 15) Proventi da partecipazioni:
- varie 2.375.759 2.420.103 16) Altri proventi finanziari:
2.375.759 2.420.103 a) da crediti iscritti nelle immobilizzazioni
Totale attivo 36.250.698 38.984.948 b) da titoli iscritti nelle immobilizzazioni 7.871
c) da titoli iscritti nell'attivo circolante 16.918 1.011
Stato patrimoniale passivo 31/12/2007 31/12/2006 d) proventi diversi dai precedenti:
- da imprese controllate
A) Patrimonio netto - da imprese collegate
I. Capitale 634.230 634.230 - da controllanti
- altri 155.947 9.645
II. Riserva da sovrapprezzo delle azioni 4.623.770 4.623.770 180.736 10.656
180.736 10.656
III. Riserva di rivalutazione 17) Interessi e altri oneri finanziari:
- da imprese controllate
IV. Riserva legale 127.912 64.009 - da imprese collegate
- da controllanti
V. Riserve statutarie - altri 554.154 427.716
554.154 427.716
VI. Riserva per azioni proprie in portafoglio 17-bis) Utili e Perdite su cambi 236 240
VII. Altre riserve Totale proventi e oneri finanziari -373.182 -416.820
Riserva straordinaria 1.508.578 1.025.816
Versamenti in conto capitale 23.758 23.758 D) Rettifiche di valore di attivit finanziarie
1.532.336 1.049.574 18) Rivalutazioni:
a) di partecipazioni
VIII. Utili (perdite) portati a nuovo b) di immobilizzazioni finanziarie 1.131 10.033
c) di titoli iscritti nell'attivo circolante -
IX. Utile (perdita) d'esercizio 367.210 546.667 1.131 10.033
Totale patrimonio netto di gruppo 7.285.458 6.918.251 19) Svalutazioni:
Totale patrimonio netto di terzi 85.774 61.791 a) di partecipazioni
Totale patrimonio netto conosolidato 7.371.232 6.980.042 b) di immobilizzazioni finanziarie
c) di titoli iscritti nell'attivo circolante
B) Fondi per rischi e oneri
1) Fondi di trattamento di quiescenza e obblighi simili
2) Fondi per imposte, anche differite 71.587 133.853 Totale rettifiche di valore di attivit finanziarie 1.131 10.033
3) Altri
Totale fondi per rischi e oneri 71.587 133.853 E) Proventi e oneri straordinari
20) Proventi:
C) Trattamento fine rapporto di lavoro subordinato 703.808 639.159 - plusvalenze da alienazioni 257.846
- varie 47.998 1.210
D) Debiti 305.844 1.210
1) Obbligazioni 21) Oneri:
2) Obbligazioni convertibili - minusvalenze da alienazioni
3) Debiti verso soci per finanziamenti - imposte esercizi precedenti
4) Debiti verso banche - varie 668.990 197.117
- entro 12 mesi 1.004.845 6.901.680 668.990 197.117
- oltre 12 mesi 2.575.138 3.192.979
3.579.983 10.094.659 Totale delle partite straordinarie -363.146 -195.907
5) Debiti verso altri finanziatori
- entro 12 mesi Risultato prima delle imposte (A-BCDE) 1.543.780 1.384.717
- oltre 12 mesi
22) Imposte sul reddito dell'esercizio, correnti, differite e anticipate
6) Acconti a) Imposte correnti 1.033.818 1.670.819
- entro 12 mesi 8.693.944 7.077.853 b) Imposte differite (anticipate) 111.767 -791.090
- oltre 12 mesi 1.145.585 879.729
8.693.944 7.077.853
7) Debiti verso fornitori 23) Utile (Perdita) dell'esercizio 398.195 504.988
- entro 12 mesi 13.937.287 12.298.037 -) Utile (perdita) dell'esercizio di pertinenza di terzi 30.985 -41.680
- oltre 12 mesi -) Utile (perdita) dell'esercizio di gruppo 367.210 546.668
13.937.287 12.298.037
EDIZIONI MASTER S.p.A
Sede in C.da Lecco Zona Industriale, 64 - 87036 RENDE (CS) Capitale Sociale Euro 634.230,00 I.V.
Bilancio Consolidato al 31/12/2007
ht t p: / / www. i opr ogr ammo. i t
M SOFTWARE SUL CD
Settembre 2008/
105
G
Librerie e Tool di sviluppo
VB 6 ANTIDECOMPI-
LER 2.2.1
UNA UTILITY PER PROTEGGERE
I TUOI PROGRAMMI
Il tool ideale per gli sviluppatori VB che
hanno il timore che qualcuno copi il co-
dice da loro creato con tanto fatica. VB 6
AntiDecompiler, infatti, disabilita la de-
compilazione nativa di Visual Basic.
Operazione che sar quindi possibile so-
lo con appositi tool allavanguardia.
Una volta che VB Antidecompiler in-
tervenuto su un file eseguibile, l'output
dell'eventuale decompilazione produrr
soltanto del confuso assembler, o addi-
rittura non produrr nessun output.
Directory: vb6antidecompiler.exe
UI SUITE
POTENZIA E RENDI UNICHE
LE TUE PAGINE ASP.NET
UI Suite include un set di controlli da uti-
lizzare nei siti realizzati con tecnologia
ASP.NET. I componenti offerti in questa
suite possono rendere pi facile la vita
allo sviluppatore web che intende realiz-
zare siti Internet dall'aspetto professio-
nale, includendo comodi calendari, edi-
tor di testo, pannelli di controllo, stru-
menti per la realizzazione di Sitemap e
per lo spell checking.
Directory: uisuite.zip
HELPCRUISER
2.2.1.511
CREA DA SOLO LA DOCUMENTA-
ZIONE PER IL TUO SOFTWARE
Tutti gli sviluppatori si, trovano prima o poi,
a dover affrontare il problema docu-
mentazione. HelpCruiser un software
che aiuta a creare file di help nei formati
pi diffusi, quali HTML, PDF, RTF e il fa-
moso formato di Microsoft, il CHM.
Proprio per la creazione dei file CHM,
per, Helpcruiser ha bisogno di scarica-
re e installare MS HTML Workshop, il
compilatore per file CHM. Questa ope-
razione avviene in modo del tutto tra-
sparente allutente, tanto che inclusa
nel processo di installazione.
I layout prodotti dal programma sono to-
talmente configurabili e personalizzabi-
li, cos da permettere allo sviluppatore il
massimo della personalizzazione.
Directory: helpcruiser_eng.exe
VIRTUAL BOX 1.6.2
USARE TUTTI I SISTEMI OPERATIVI
INSIEME, GRAZIE ALLA VIRTUALIZ-
ZAZIONE
Chi sviluppa per pi di un sistema operativo
ha spesso lesigenza di testare le proprie
applicazioni, ma pu non avere la possi-
bilit di installare pi di un SO, sulla pro-
pria macchina.
Virtual Box permette di utilizzare molti
SOFTWARE
SUL CD
Speciale Tool
M
olte volte, sviluppando una qualunque applicazio-
ne, ci si trova in situazioni particolari e impreviste
che provocano, almeno per un attimo, la sgradevole sen-
sazione di non sapere cosa fare. Lintegrazione di un par-
ticolare componente che intervenga sui file di Office piut-
tosto che su quelli in formato PDF, la necessit di testare
unespressione regolare prima di inserirla nel programma
o, ancora, la volont di dotare lapplicazione che si sta
creando di unaccattivante interfaccia che distingua il
nostro programma dalla marea di applicazioni in circo-
lo. Sono soltanto alcuni degli esempi di eventualit che
possono accadere programmando, in qualsiasi linguaggio
lo si faccia. E spesso, proprio per far fronte a queste even-
tualit, si perde prezioso tempo cercando la soluzione
adatta al problema di turno. Proprio per questo, nel CD-
Rom allegato a questo numero proponiamo una raccolta
di componenti, tool e programmi che di sicuro agevole-
ranno il lavoro quotidiano di chi ci segue. Gli attrezzi giu-
sti per inserire un motore antivirus nelle proprie appli-
cazioni o per proteggere il proprio codice da impertinenti
decompilatori, e ancora i programmi per conservare le
porzioni riutilizzabili del proprio prezioso codice. Sfo-
gliando il CD-Rom troverete tutti questi tool, e molti al-
tri ancora, pronti da installare ed utilizzare per perfezio-
nare il vostro lavoroe divertimento! Di seguito un estrat-
to dei software presenti nel CD.
105-107:106-108-software 16-07-2008 10:29 Pagina 105
ht t p: / / www. i opr ogr ammo. i t
SOFTWARE SUL CD M
G
106
/Settembre 2008
Librerie e Tool di sviluppo
sistemi operativi sulla stessa macchina,
senza avere il bisogno di partizionare
lhard disk e configurare il sistema in ma-
niera particolare. Buona la gestione del-
le porte USB della macchina Host, cos
come anche quella della rete virtuale, con-
figurabile sia in modalit bridge o NAT.
Directory: VirtualBox-1.6.2-Win_x86.zip
CODESNIP
PER NON PERDERE MAI PI
NEANCHE UN RIGO DI CODICE!
Tutti coloro che programmano produco-
no migliaia di righe di codice. Ma, spesso
e volentieri, quando serve proprio quel
pezzetto di codice utilizzato in un pro-
gramma sviluppato tempo fa, ci quasi im-
possibile trovarlo. CodeSnip un tool
pensato proprio per supplire alla distra-
zione dei programmatori, venendo loro in
aiuto e mettendo a disposizione un'in-
terfaccia per conservare i propri snip di
tutti i linguaggi.
Una volta individuato il pezzo di codice che
si vuole conservare, possibile inserire
una descrizione e un nome per lo snip,
cos da poterlo individuare pi facilmente
in seguito. Directory: codesnip.zip
WAB PROCESSOR
GESTISCI LA RUBRICA
WINDOWS TRAMITE DELPHI
Wab processor un componente per
Delphi che fornisce accesso facile e im-
mediato alla rubrica di Windows (Win-
dows Address Book). Una volta interfac-
ciato il componenente, possibile mo-
dificare, aggiungere e/o eliminare con-
tatti e gruppi. Una delle altre caratteri-
stiche quela che permette di importare
ed esportare i contatti ed editarli in qual-
siasi applicazione Delphi.
Directory: WABProcessor.zip
PHP PROCESSOR
1.5.0.0
PROTEGGI IL TUO CODICE PHP
Chi sviluppa in PHP e deve distribuire il co-
dice dei suoi progetti ha spesso la neces-
sit di proteggere il codice, onde evitarne
la copia da parte di persone non autoriz-
zate. Il programma include un comodo
editor, utile sia per scrivere in PHP che in
linguaggio Javascript o in "semplice"
HTML. ovviamente dotato della fun-
zione di syntax highlighting per una pi
comoda visualizzazione del codice. PHP
processor pu essere utilizzato anche per
la semplice ottimizzazione dei file PHP,
riuscendo a diminuire notevolmente (fi-
no al 30%) il peso dei file stessi. Questo
programma comprende anche un client
FTP e addirittura un sistema per effet-
tuare i backup.
Directory: phppro15.zip
VB DECOMPILER 5.0
RENDI VISIBILE IL CODICE
DEGLI ESEGUIBILI WINDOWS!
VB Decompiler un software che serve, co-
me si evince dal nome stesso, a decompilare
i programmi scritti utilizzando il linguaggio
VB. Siano essi di tipo EXE, OCX o ancora
DLL VB Decompiler riesce quasi sempre
a restituire il codice sorgente. Ottimo per
analizzare il codice anche quando que-
sto non viene totalmente decompilato,
in quanto l'algoritmo utilizzato riesce
ugualmente a riconoscere la struttura del
programma o della libreria da decompi-
lare.
Directory: vb_decompiler_lite.zip
HEX EDITOR NEO
4.51
VISUALIZZA IL CODICE ESADECI-
MALE DEI TUOI ESEGUIBILI
Visualizza, modifica e analizza i tuoi da-
ti esadecimali e file binari di ogni di-
mensione. Ottimo per la manipolazione
dei file EXE, DLL, DAT, AVI, MP3.
Il programma offre la possibilt di creare
delle patch operando molto semplice-
mente, mantenendo la history delle mo-
difiche effettuate sui file, permettendo di
salvare la stessa e ricaricarla in un se-
condo momento.
Directory: free-hex-editor-neo.zip
SCRIPTOMANIA 2.7
UN EDITOR PER TUTTI I LINGUAGGI
WEB
Questo programma lideale per gli svi-
luppatori web oriented che utilizzano
PHP e altri linguaggi per la creazione dei
siti web.
Scriptmania supporta infatti PHP, HTML,
CSS e Javascript, offrendo molti comodi
strumenti. La colorazione della sintas-
si e lautocompletamento del codice fa-
cilitano infatti la redazione degli script,
mentre la possibilit di programmare
macro agevola l'esecuzione di compiti
ripetitivi. possibile, inoltre, creare dei
template da richiamare con comandi ra-
pidi e organizzare i file in una struttura
a progetti.
Directory: scriptomania.zip
INSTALL SIMPLE
1.27
CREA FACILMENTE FILE
DINSTALLAZIONE
Installsimple un programma che per-
mette di creare pacchetti di installazio-
ne per distribuire le proprie applicazioni.
Consente di configurare archivi autoe-
straenti con un ottimo grado di com-
105-107:106-108-software 16-07-2008 10:29 Pagina 106
ht t p: / / www. i opr ogr ammo. i t
M SOFTWARE SUL CD
Settembre 2008/
107
G
Librerie e Tool di sviluppo
pressione, intervenire direttamente sul-
le chiavi di registro, mostrare le informa-
zioni sull'eventuale licenza adoperata
dallo sviluppatore, creare collegamenti
dove desiderato e molto altro ancora.
Gratuito, occupa davvero pochissime ri-
sorse di sistema.
Directory: installsimple.zip
ENTERPRISE ARCHI-
TECT 7.1 BUILD 827
PER PROGETTARE SECONDO LO
STANDARD UML
Questo programma sar certamente gra-
dito a chi utilizza UML durante lo svi-
lupppo delle sue applicazione e progetti.
Enterprise Architect permette, infatti, gra-
zie a un'interfaccia molto semplice da
utilizzare, di modellare, disegnare e co-
struire un software o un progetto busi-
ness. Il programma riesce a generare il
codice in molti linguaggi, tra i quali Ac-
tionscript, Java, C#, C++, Python e DDL.
Grazie a questo software pi semplice pas-
sare agevolmente dalla fase di progetta-
zione a quella di sviluppo, accelerando
notevolmente i tempi di lavorazione del
progetto.
Directory: scriptomania.zip
REGEX TESTBED
1.0.6.1
TESTE LE TUE ESPRESSIONI
REGOLARI IN WYSIWYG!
RegEx TestBed consente di testare le
espressioni regolari utilizzando un me-
todo visuale.
Un comodo highlithing della sintassi
aiuta a rintracciare le occorrenze in real-
time.
Molto utile la funzione cerca e sosti-
tuisci integrata e la possibilit di espor-
tare le espressioni regolari in formato
XML o CSV, cos da poterle utilizzare nei
pi svariati programmi.
Directory: RegExTestBed-Setup.zip
MSI TO EXE SETUP
CONVERTER 2.0.1.5
DISTRIBUISCI I TUOI PROGRAMMI
SU TUTTE LE VERSIONI
DI WINDOWS
I pacchetti di installazione nel nuovo
formato di Windows (MSI) sono ormai
diffusissimi e utilizzati dalla stragran-
de maggioranza degli sviluppatori e pro-
duttori di software. Hanno per il di-
fetto di non essere compatibili con le
vecchie versioni di Windows. MSI to EXE
Converter, come si capisce dal nome
stesso, trasforma i pacchetti di instal-
lazione .MSI in comuni eseguibili di
Windows, senza modificare per il con-
tenuto originale del file di installazio-
ne. In questo modo sar possibile di-
stribuire le proprie applicazioni su tut-
te le versioni del sistema operativo Mi-
crosoft.
Directory: MSItoEXECreatorDemo.zip
CODE WAREHOUSE
2007
RAGGRUPPA E CATALOGA LE TUE
PORZIONI DI CODICE PREFERITE!
Se producete una marea di codice, fun-
zioni e snippet, non potete fare a me-
no di questo semplice e comodissimo
programma.
Code Warehouse serve a conservare e
catalogare porzioni di testo che utiliz-
ziamo spesso nelle nostre applicazio-
ni. L'interfaccia molto intuitiva e per-
mette di creare e modificare categorie e
sottocategorie, organizzare bookmark
e, cosa che pu rivelarsi moto utile, in-
cludere degli allegati per ogni snippet
creato.
Utile anche la possibilit di inserire de-
gli specifici tag che serviranno in mo-
dalit di ricerca e la colorazione della
sintassi per i linguaggti di programma-
zione pi famosi. Per funzionare richiede
linstallazione di Microsoft .NET Fra-
mework 2.0.
Directory: codewarehouse.zip
METADEFENDER
LITE 1.5.62
INTEGRA UN POTENTE ANTIVIRUS
NEI TUOI PROGRAMMI
Per gli sviluppatori che vogliono inclu-
dere un motore antivirus nei loro pro-
grammi, niente di meglio di Metade-
fender.
Questo piccolo tool permette di inclu-
dere il CORE di Clamav, famoso antivi-
rus Open Source. Utilizzando Metade-
fender sar possibile effettuare scan-
sioni al volo direttamente dalle proprie
applicazioni. Questa nuova versione in-
clude molte nuove funzioni, come ad
esempio la possibilit di creare file di
log. Essendo una versione trial, limita
a 10 MB la dimensione dei file scansio-
nabili.
Directory: mdlite1562.zip
105-107:106-108-software 16-07-2008 10:29 Pagina 107
ht t p: / / www. i opr ogr ammo. i t
SOLUZIONI M
G
110
/Settembre 2008
Algoritmi geometrici per la programmazione grafica
Le tecniche di elaborazione grafica sono in conti-
nua evoluzione. Le attuali rappresentazioni sono
davvero sorprendenti per realismo ed efficienza, si
pensi ai nuovi giochi o alle moderne simulazioni.
Alla base di avanzati e complessi metodi vi sono
delle primitive, indispensabili strumenti per chi si
desidera avvicinarsi a tale ambito. In particolare
rivestono un ruolo fondamentale le routine cono-
sciute con il nome di rasterizzazione che hanno il
compito di adattare entit descritte nel continuo e
con strumenti analitici in corrispondenti entit
pronte alla rappresentazione grafica. noto che gli
apparati che si occupano della raffigurazione di
elementi grafici come monitor o stampanti, in
estrema sintesi, si rifanno alla giustapposizione di
insiemi di punti, che per i monitor sono conosciuti
come pixel. Tali punti, che nei casi pi comuni pos-
sono assumere uno tra diversi colori, sono organiz-
zati come una matrice in accordo con la struttura
bidimensionale di monitor o stampanti. Cosicch,
ogni punto sar univocamente individuato da una
coppia di coordinate (x,y). I problemi che nel corso
degli anni si sono via via presentati agli studiosi
sono molteplici. Giusto per citarne qualcuno pos-
siamo ricordare il problema della trasformazione
di oggetti dalla realt tridimensionale a cui appar-
tengono alla rappresentazione delle due dimensio-
ni a cui devono essere riportati; o, ancora, la rap-
presentazione degli oggetti nello spazio in cui sono
presenti fonti di luce che innescano una serie di
questioni come la riproduzione delle forme e delle
ombre, e la non visione delle parti nascoste. In que-
sto appuntamento ci occuperemo di un problema
basilare, ma di estremo interesse, la rasterizzazio-
ne, ossia il procedimento che trasforma una qual-
siasi figura, come un segmento o un poligono,
descritta nel continuo, nella corrispettiva rappre-
sentata come insieme di pixel nello schermo; in
particolare ci concentreremo sulla figura segmen-
to. Cosa si intenda per continuo sar chiarito e
approfondito nel corso della trattazione, per avere
una prima idea basti pensare allo strumento oscil-
loscopio che, al contrario del monitor, traccia fun-
zioni. Simile analogia si pu fare tra i due strumen-
ti di stampa plotter e stampante. Il plotter usa dei
pennini che, mossi da bracci, disegnano.
Ancora, per intenderci, un segmento nel continuo
non altro che una linea che tracciamo a penna
usando un righello. Rispetto a tale problemi, forni-
remo gli algoritmi e i semplici procedimenti mate-
matici e geometrici che li generano e accenneremo
le tecniche correlate alla rasterizzazione come il
flood fill, ossia il riempimento di poligoni o
lantialiasing ossia la riduzione dello scalettamento
nella riproduzione ad esempio di font.
RASTERIZZAZIONE
DI LINEA
Chi si cimentato anche con le pi semplici routi-
ne di rappresentazione grafica avr certo notato
che il banale tracciamento di un segmento inclina-
to tra due punti qualsiasi P1(x1, y1) e P2(x2, y2) pre-
senta un effetto poco piacevole alla vista una sorta
di scaletta. Effetto differente avremmo ottenuto su
un foglio di carta usando gli antiquati strumenti:
penna e righello. Osservando Fig.1 si comprende
meglio di ogni descrizione cosa si intende dire.
stato ingrandito per enfatizzare la differenza, nella
realt non si notano cos evidenti discrepanze tra le
due rappresentazioni.
IL PROCESSO
DI RASTERIZZAZIONE
UN PUNTO CRUCIALE E DI ESTREMO INTERESSE NELLAMBITO DELLA GRAFICA
COMPUTAZIONALE IL PROCESSO CON IL QUALE SI CONVERTONO ENTIT, DESCRITTE
NEL CONTINUO, IN CORRISPONDENTI ENTIT DISCRETE, OSSIA INSIEMI DI PIXEL
Conoscenze richieste
Nozioni di base su:
linguaggi di
programmazione,
geometria e analisi
matematica.
Software
-
Impegno

Tempo di realizzazione
REQUISITI
Fig. 1: Rappresentazione di un segmento nel continuo
(arancio) e nel discreto (turchese)
110-114:110-113-Soluzioni mcd 16-07-2008 10:34 Pagina 110
ht t p: / / www. i opr ogr ammo. i t
M SOLUZIONI
Settembre 2008/
111
G
Algoritmi geometrici per la programmazione grafica
Il procedimento di rasterizzazione anche cono-
sciuto come scan conversion, questa seconda acce-
zione mette in risalto le fasi di osservazione e con-
versione. Prima di procedere con le tecniche di
soluzione bene ribadire che i potenti hardware di
cui oggi disponiamo, in effetti, attenuano e di
molto il problema. La presenza di matrici di pixel
sempre pi dense di punti rendono meno evidenti
gli effetti indesiderati della discretizzazione. La
scelta di un algoritmo che risolva il problema deve
perseguire principalmente due scopi:
1. Descrivere il pi fedelmente possibile la figura
originaria. Dal segmento descritto nel continuo,
ad esempio attraverso strumenti analitici come
lequazione di una retta passante per due punti,
bisogna individuare una sequenza di pixel da
accendere;
2. Essere efficiente. Usare operazioni e tipi di dati
che corrispondano a poche e veloci istruzioni
macchina. questa unesigenza primaria, si
pensi alle complesse rappresentazioni grafiche
costituite da numerosissime raffigurazioni ele-
mentari che devono essere aggiornate molto di
frequente per dare fluidit allazione in movi-
mento; evidente che sul tempo di elaborazione
totale influisce in modo sostanziale la singola
rappresentazione elementare. Anche la riduzio-
ne di poche istruzioni macchina, in considera-
zione del numero elevato di componenti ele-
mentari e del gran quantit di immagini da pro-
durre per i video, abbatte in modo sostanziale il
tempo totale di elaborazione decretando la
bont di un algoritmo piuttosto che di un altro.
In tale contesto sono utili pochi, ma ben circo-
stanziati consigli: opportuno usare tipi di dati
snelli, quindi sono ovviamente preferibili gli
interi a alle virgole mobili. Inoltre, si cercher di
evitare routine particolarmente pesanti, come
vedremo anche larrotondamento round() pro-
duce uno sforzo computazione e la sua elimina-
zione consente incrementi di efficienza. Ancora
preferibile la somma alla moltiplicazione. E
cos via.
Esistono diversi metodi per la rasterizzazione di
una linea ne visioneremo due. Il primo DDA sem-
plice ma poco efficiente. Il secondo, algoritmo di
Bresenham, pi efficiente.
ALGORITMO DDA
DDA acronimo di Digital Differential Analyzer, in
effetti si tratta di un dispositivo meccanico che
risolve equazioni differenziali con metodi numeri-
ci. Come vedremo, la soluzione al nostro problema
di rasterizzazione di linea verr appunto risolta
impostando una semplice equazione differenziale.
Nulla di cui spaventarsi basta ricordare i principi di
descrizione analitica di una retta. Consideriamo,
come fatto in Fig.1, due punti P1(x1, y1) e P2(x2,
y2); per essi passa una ed una sola retta la cui pen-
denza (coefficiente angolare) si esprime come rap-
porto tra gli incrementi delle ordinate indicate con
y e delle ascisse ossia x. Da cui si pu facilmente
calcolare la variazione della y.
In sostanza, lalgoritmo DDA, a ogni iterazione,
incrementa la x di ununit (corrispondente a un
pixel) e calcola il nuovo valore di y. Essendo la y un
valore reale, si procede arrotondando.
Vediamo come si esprime da un punto di vista ana-
litico. Viene considerata una coppia generica di
coordinate xi, yi che esprime il punto Pi al passo i
dellalgoritmo. Si inizia dal calcolo dellultima rela-
zione ottenuta, nota anche agli studenti delle supe-
riori. Si ricorda che nel caso specifico la variazione
della x ad ogni passaggio 1, si passa da ununit
alla successiva. Con pochi passaggi matematici si
ottiene la relazione che si potr usare nellalgorit-
mo:
Lalgoritmo si costruisce in modo naturale.
Sviluppiamolo usando una sintassi vicina al pascal.
Con putpixel(x, y, C) intendiamo laccensione del
pixel del colore C di coordinate x e y. Inoltre, si pre-
suppone che la matrice di pixel segua gli orienta-
menti di unasse cartesiano cos come lo riprodur-
remmo con carta e penna, e cio che riporti
RASTERIZZAZIONE DI UN POLIGONO
Un algoritmo di rasterizzazione di
un poligono ha il compito di
convertire un poligono
rappresentato come un insieme di
vertici in sequenza che indicano
un poligono nella corrispondente
immagine bitmap o raster. Il pi
semplice degli algoritmi prevede il
solo tracciamento del poligono,
come giustapposizione dei vari
lati, vuoto per intenderci. Per
realizzare questo sufficiente
applicare algoritmi di
rasterizzazione di linea ai vari lati
del poligono. Pi complessi sono
invece gli algoritmi che prevedono
il riempimento del poligono anche
conosciuti come flood fill. In tal
caso si hanno diversi livelli di
difficolt a seconda se il poligono
convesso o meno. Per poligoni
convessi la risoluzione risulta pi
semplice. Una qualsiasi figura
piana convessa se comunque
presi due punti interni ad essi il
segmento che li congiunge ricade
interamente nella figura stessa.
Risultano particolarmente
efficienti algoritmi flood fill
ricorsivi.
110-114:110-113-Soluzioni mcd 16-07-2008 10:34 Pagina 111
ht t p: / / www. i opr ogr ammo. i t
SOLUZIONI M
G
112
/Gennaio 2006
Fisica
ht t p: / / www. i opr ogr ammo. i t
G
112
/Settembre 2008
Algoritmi geometrici per la programmazione grafica
lorigine in basso a sinistra. In realt, spesso,
lorigine per i sistemi grafici in alto a destra, ma
sufficiente una piccola conversione per conside-
rarla, senza perdita di generalit, in basso a sinistra.
Supponiamo, qualora tale conversione sia necessa-
ria, che sia contenuta nella routine elementare
indicata con putpixel. Lultima ipotesi, questa di
tipo analitico, riguarda m che deve essere compre-
so tra 0 e 1. Anche in questo caso non si perde di
generalit poich altri valori di m possono essere
trattati in modo simmetrico. Ecco lalgoritmo DDA
..
// Inserimento dei dati
input(x1,y1,x2,y2)
// calcolo dei differenziali (incrementi) e del coefficiente
angolare
dx := x2-x1;
dy := y2-y1;
m := dy/dx;
// Punto di partenza
y := y1;
// Iterazione
for x:=x1 to x2 do
Begin
// applicazione della formula calcolata
y:= y+m;
putpixel(x, round(y), black);
End;
..
Se applichiamo lalgoritmo a pendenze maggiori di
1, in contrasto con lipotesi iniziale, ed esaminiamo
i risultati ottenuti notiamo che si genera un effetto
di sgranamento. Pendenze basse, ossia con m<1,
non evidenziano tale problema per cui la riprodu-
zione accettabile. Le due situazioni sono riporta-
te in Fig.2 rispettivamente nella parte a e b.
Il problema che, per pendenze alte, poich
aumenta maggiormente la y rispetto alla x, si crea-
no inevitabilmente dei vuoti, poich la y salta di un
valore maggiore di 1 di pixel facendo perdere
leffetto di continuit. Un modo semplice, quanto
ingegnoso per risolvere il problema, invertire la x
con la y, qualora che la pendenza sia maggiore di 1.
Ovvero si varia, di uno alla volta, la y, contestual-
mente si calcola la variabile x. Lalgoritmo che tiene
conto di questa modifica riportato di seguito:
..
// Inserimento dei dati
input(x1,y1,x2,y2)
// calcolo dei differenziali (incrementi) e del coefficiente
angolare
dx := x2-x1;
dy := y2-y1;
m := dy/dx;
// Verifica della pendenza
if m<=1 then
Begin
// Punto di partenza primo caso
y := y1;
// Iterazione
for x:=x1 to x2 do
Begin
// applicazione della formula calcolata
y:= y+m;
putpixel(x, round(y), black);
End;
Else
Begin
// Punto di partenza secondo caso
x := x1;
// Iterazione
for y:=y1 to x2 do
Begin
// applicazione della formula calcolata
x:= x+1/m;
putpixel(round(x), y, black);
End;
..
Tale algoritmo non comunque abbastanza effi-
ciente, poich per ogni iterazione sono richieste
operazioni in virgola mobile (somma e arroton-
damento). Per cui, anche se didattico, poich ci
introduce direttamente al cuore del problema e
ci chiarisce lambito di sviluppo, non di fatto
utilizzato.
Un algoritmo pi efficiente riportato di seguito.
ALGORITMO
DI BRESENHAM
Come per il paragrafo precedente, esaminiamo il
metodo; in una prima fase attraverso lanalisi
matematica, poi tramite limplementazione dellal-
goritmo. Si formulano le stesse ipotesi. Si parte
anche in questo caso da un generico punto i per il
quale si suppone che si sia acceso il pixel P(xi,yi).
Fig. 2: Due segmenti costruiti con DDA. a) rappresentazione accettabile. b) rap-
presentazione con m>1, il segmento risulta sgranato
a
b
110-114:110-113-Soluzioni mcd 16-07-2008 10:34 Pagina 112
http://www.ioprogrammo.it
Come mostrato in Fig.3, in considerazioni delle
ipotesi fatte sul coefficiente angolare, il nuovo
punto candidato ad accendersi potr essere A o B.
Lalgoritmo di Bresenham efficiente poich, come
vedremo, propone un modo semplice e rapido da
computare per effettuare questa scelta.
Si rimanda la scelta del punto da accendere tra A e
B al valore che assume un indice o coefficiente, se
maggiore di zero si opter per il punto A, se minore
per il punto B. Vediamo come si pu calcolare tale
coefficiente. In corrispondenza del punto xi+1 la
retta pu trovarsi sopra o sotto il punto medio M,
posto esattamente a met tra le due opzioni A e B.
Se esprimiamo la retta in forma esplicita e sosti-
tuiamo in tale relazione il punto medio, si possono
verificare tre casi: lequazione si annulla e ci indi-
ca che il punto M proprio sulla retta; il risultato
maggiore di zero, quindi M sopra la retta; infine il
risultato minore di zero e quindi M sotto la retta.
Nel primo caso la scelta del punto candidato
indifferente visto che la retta passa esattamente a
met, nel secondo caso, invece bisogner scegliere
il punto A la cui ordinata yi perch la retta pi
vicina a quel punto. Infine nel terzo caso la scelta
ricadr su B con yi+1. La retta si scrive in forma
esplicita come:
con
nella forma implicita, ossia riportando unequa -
zione pari a zero, si ottiene:
Il punto medio Mha coordinate (xi+1, yi + _)
Sostituendo le coordinate del punto medio che
possiamo indicare con xm e ym otteniamo il coef-
ficiente cercato che indichiamo con d.
Se d=0 lequazione degenera nella forma implicita
della retta e quindi il punto si trova sulla retta stes-
sa, cos si pu scegliere indifferentemente il punto
A o B. Se d>0, M al di sopra la retta e quindi opte-
remo per A. Se d<0 opteremo infine per B. Questo
risultato ci potrebbe accontentare da un punto di
vista matematico, per sviluppare lalgoritmo, inve-
ce, Bresenham ha pensato bene di generalizzare e
semplificare il calcolo dei coefficienti d. Per ottene-
re il nuovo d bisogna considerare separatamente il
caso in cui sia stato scelto il punto A o il punto B.
Sviluppiamo i passaggi matematici per le due
situazioni. Se il punto scelto A si riparte da
P(xi+1,yi). Il nuovo punto medio M (xi+2, yi+1/2).
Il nuovo coefficiente d, che indichiamo con dn
sar:
Se al nuovo valore ottenuto sottraiamo quello vec-
chio:
Dalla semplificazione rimane soltanto lincre -
mento della y.
Se il punto iniziale B si parte da P(xi+1,yi+1) e da
un punto medio M(xi+2, yi+1+1/2) ossia M(xi+2,
yi+3/2). Sviluppando lo stesso procedimento prece-
dente per il calcolo prima di dn e successivamente
facendo la differenza dn-d, si ottiene:
Il nuovo valore d si pu quindi sintetizzare tenendo
conto dei due casi esaminati.
Il risultato estremamente positivo a cui siamo arri-
vati che lindividuazione del nuovo punto da
accendere si ottiene soltanto sulla base di somme e
senza alcun arrotondamento. Per poter sviluppare
lalgoritmo ci serve il primo coefficiente d
0
dal
quale estrarre la prima scelta. Si ottiene:
M SOLUZIONI
Settembre 2008/
113
G
Algoritmi geometrici per la programmazione grafica
Fig. 3: Problema della scelta del punto candidato nel-
lalgoritmo di Bresenham
110-114:110-113-Soluzioni mcd 16-07-2008 10:34 Pagina 113
http://www.ioprogrammo.it
La presenza di questa frazione sar superata nella
seconda versione proposta dellalgoritmo di
Bresenham. Un primo modo per implementare il
metodo che fa riferimento fedelmente ai risultati
analitici ottenuti il seguente.
// Inserimento dei dati
input(x1,y1,x2,y2)
// Calcolo degli incrementi e del coefficiente iniziale
dx:=x2-x1;
dy:=y2-y1;
d:=dy-dx/2;
// Inizializzazione coordinate
x:=x1;
y:=y1;
putpixel (x,y,black);
while (x<x2) do
Begin
if (d>=0) then
Begin
d:=d+dy-dx;
y:=y+1;
x:=x+1
End;
Else
Begin
d:=d+dy;
x:=x+1
End;
putpixel (x,y,black)
End;

Come detto, necessario superare la presenza dei


numeri in virgola mobile. Per farlo basta effettuare
una piccola modifica. infatti sufficiente raddop-
piare i valori di d. Ecco come risulta il nuovo e que-
sta volta efficiente algoritmo di Bresenham:
// Inserimento dei dati
input(x1,y1,x2,y2)
// Calcolo degli incrementi e del coefficiente iniziale
(modificato)
dx:=x2-x1;
dy:=y2-y1;
d:=2*dy-dx;
// Inizializzazione coordinate
x:=x1;
y:=y1;
putpixel (x,y,black);
while (x<x2) do
Begin
if (d>=0) then
Begin
d:=d+2*dy-2*dx;
y:=y+1;
x:=x+1
End;
Else
Begin
d:=d+2*dy;
x:=x+1
End;
putpixel (x,y,black)
End;

METODOLOGIE
DI ANTIALIASING
un metodo anche conosciuto con la sigla AA
usato per ridurre leffetto di scalettamento o
appunto aliasing. Lo si pu ritrovare anche nei tool
di manipolazione grafica o fotoritocco. Leffetto
negativo si presenta soprattutto quando una figura
come ad esempio un font o una semplice immagi-
ne (come una foto digitalizzata) a bassa risoluzione
viene mostrata ad alta risoluzione. Linconveniente
ancora pi evidente a fronte di linee oblique che
delimitano due colori contrastanti.
I metodi di antialiasing hanno lo scopo di rendere
meno evidente leffetto scaletta e di riportare le
linee che presentano questo difetto con una rap-
presentazione che sia pi naturale possibile.
Esistono diversi metodi di antialiasing. Il pi cono-
sciuto anche perch usato a livello di hardware,
ossia dalle schede video, il supersampling: un
pixel viene suddiviso in pi pixel detti sub pixel
ognuno dei quali con colori diversi che ovviamente
dipendono dal colore assunto nelle loro vicinanze.
opportuno ricordare che il problema si presenta
soltanto ai bordi.
Una volta che si hanno tutti i colori del nuovo insie-
me si opera una media da cui scaturisce il colore
del pixel. La media pu essere anche ponderata,
quindi dare maggiore rilevanza ai sub pixel centra-
li. Si tratta di una elaborazione non del tutto ele-
mentare, cosicch le schede video che lo adopera-
no devono pagare la migliore qualit delle imma-
gini con un minore frame rate appunto diminuito a
causa delle computazioni di supersampling.
Un secondo metodo poligon filtering con il quale
si lavora sui soli bordi dei poligoni. In particolare si
adotta quando pi poligoni insistono, magari con
diversa forza, su uno stesso pixel, in tal caso si rie-
labora il colore del pixel tenendo conto dei poligo-
ni e della percentuale che ognuno di essi ha sul
pixel. Anche qui in definitiva viene fatta una media
dei colori.
Altre tecniche sono la temporal antialiasing e la
gamma corrected.
Fabio Grimaldi
SOLUZIONI M
G
114
/Settembre 2008
Algoritmi geometrici per la programmazione grafica
NOTA
RIFERIMENTI
Sulla enciclopedia on-line
Wikipedia possibile
trovare nozioni ben
organizzate sugli
argomenti trattati.
Il presente articolo stato
realizzato tenendo come
riferimento principale la
fonte appena citata.
Uninteressante sintesi va
anche segnalata al sito
110-114:110-113-Soluzioni mcd 16-07-2008 10:34 Pagina 114