venerdì 2 dicembre 2011

Create a Drawing App with HTML5 Canvas and JavaScript { William Malone }

Create a Drawing App with HTML5 Canvas and JavaScript { William Malone }: - Inviata con Google Toolbar


Create a Drawing App with HTML5 Canvas and JavaScript

by William Malone
html5 drawing tool example crayon
This tutorial will take you step by step through the development of a simple web drawing application using HTML5 canvas and its partner JavaScript. The aim of this article is to explore the process of creating a simple app along the way learn:
  • How to draw dynamically on HTML5 canvas
  • The future possiblities of HTML5 canvas
  • The current browser compatibility of HTML5 canvas
Each step includes a working demo; if you want to skip ahead:

Define Our Objective


Let's create a web app where the user can dynamically draw on an HTML5 canvas. What will our users use? A coloring book comes to mind; that means crayons. Our first tool is a crayon. Although the real world doesn't agree, I think we should be able to erase crayons. Our second tool will be an eraser (sorry reality). And because I have always have been a Sharpie® fan our final tool will be a marker.
Our tools could use colors (except maybe our eraser). Let's keep it simple, so we give our user 4 different colors to choose from.
Similarly let's also give our user 4 different sizes to draw with, because we can. To recap our app should have the following:
  • 3 tools: crayon, marker, eraser
  • 4 colors to choose from (except eraser)
  • 4 sizes to choose from
Like a coloring book, let's give our user something to "color". I have chosen a favorite of mine: Watermelon Duck by Rachel Cruthirds.

martedì 29 novembre 2011

La legge di Astrazioni deficitarie.

La legge di Astrazioni deficitarie.

da Joel Spolsky
Lunedi, November 11, 2002
C'è un pezzo fondamentale di magia nella progettazione di Internet che si basano su ogni singolo giorno. Succede nel protocollo TCP, uno dei blocchi fondamentali di Internet.
TCP è un modo per trasmettere i dati che sono affidabili . Con questo voglio dire: se si invia un messaggio attraverso la rete utilizzando il protocollo TCP, che arriverà, e non saranno alterati o danneggiati.
Noi usiamo TCP per molte cose, come il recupero pagine web e l'invio di email. L'affidabilità del protocollo TCP è il motivo per ogni e-mail emozionante da appropriazione indebita africani Oriente arriva nella lettera-perfetto stato. O gioia.
In confronto, c'è un altro metodo di trasmissione dati chiamato IP che è inaffidabile . Nessuno promette che i dati arriveranno, e potrebbe avere incasinato prima che arrivi. Se si invia un mucchio di messaggi con IP, non stupitevi se solo la metà di loro arrivano, e alcuni di questi sono in un ordine diverso rispetto all'ordine in cui sono stati inviati, e alcuni di loro sono stati sostituiti da messaggi alternativi , forse contenente le immagini di oranghi bambino adorabile, o più probabilmente solo un sacco di spazzatura illeggibile che sembra l'oggetto di spam Taiwan.
Ecco la parte magica: TCP si basa su IP. In altre parole, il protocollo TCP è obbligato a trasmettere in qualche modo dati in modo affidabile utilizzando solo uno strumento inaffidabile .
Per illustrare perché questo è magia, considerare quanto segue moralmente equivalente, anche se un po 'ridicolo, lo scenario del mondo reale.
Immaginate che abbiamo avuto modo di invio di attori di Broadway a Hollywood che ha coinvolto mettendoli in auto e li guida attraverso il paese. Alcune di queste vetture incidentate, uccidendo gli attori poveri. A volte gli attori si ubriacavano sulla strada e rasata la testa o ha tatuaggi nasale, diventando così troppo brutta per lavorare a Hollywood, e spesso gli attori arrivati ​​in un ordine diverso da quello che avevano indicato, perché tutti preso strade diverse. Immaginate ora un nuovo servizio chiamato Hollywood Express, che ha emesso gli attori a Hollywood, garantendo che avrebbero (a) arrivare (b) in ordine (c) in perfette condizioni. La parte magica è che Hollywood Express non dispone di alcun metodo di consegna degli attori, oltre al metodo inaffidabile di collocarle in auto e li guida attraverso il paese. Hollywood Express funziona controllando che ogni attore arriva in perfette condizioni e, se non lo fa, richiamando l'home office e chiedendo che gemello dell'attore invece l'invio. Se gli attori arrivano nell'ordine sbagliato Hollywood Check li riorganizza. Se un UFO di grandi dimensioni in via di Area 51 va in crash in autostrada in Nevada, rendendolo impraticabile, tutti gli attori che è andato in quel modo sono deviati via Arizona e Hollywood Express non ha nemmeno dire al registi in California quello che è successo. Per loro, sembra proprio come gli attori stanno arrivando un po 'più lentamente del solito, e non hanno mai nemmeno sentito circa l'incidente UFO.
Che è, approssimativamente, la magia del TCP. E 'ciò che gli informatici amano chiamare un astrazione : una semplificazione di qualcosa di molto più complicato che sta succedendo sotto le coperte. Come si è visto, un sacco di programmazione consiste nella costruzione di astrazioni. Che cos'è una libreria stringa? E 'un modo per fingere che i computer possono manipolare le stringhe con la stessa facilità si possono manipolare i numeri. Che cosa è un file system? E 'un modo per fingere che un disco rigido non è davvero un mucchio di filatura piatti magnetici in grado di memorizzare i bit in certi luoghi, ma piuttosto un sistema gerarchico di cartelle-dentro-cartelle contenenti i singoli file che a loro volta costituite da una o più stringhe di byte.
Torna a TCP. In precedenza per ragioni di semplicità ho raccontato una piccola bugia, e alcuni di voi hanno vapore che esce orecchie da adesso perché questa è fib facendo impazzire. Ho detto che il protocollo TCP garantisce che il messaggio arriverà. Non ha, in realtà. Se il serpente domestico ha masticato attraverso il cavo di rete che porta al computer, e non i pacchetti IP possono ottenere attraverso, quindi TCP non può fare nulla al riguardo e il messaggio non arriva. Se tu fossi brusco con gli amministratori di sistema della vostra azienda e vi puniti collegando un hub è in sovraccarico, solo alcuni dei pacchetti IP otterrà attraverso, e TCP funzionerà, ma tutto sarà molto lento.
Questo è ciò che io chiamo un astrazione che perde . TCP tenta di fornire una completa astrazione di una rete sottostante inaffidabile, ma a volte, le perdite di rete attraverso l'astrazione e si sente le cose che l'astrazione non riesco a proteggere l'utente da. Questo è solo un esempio di quello che ho chiamato la Legge di Astrazioni Leaky:
Tutti i non-banale astrazioni, in qualche misura, si perde.

Astrazioni fallire. A volte un po ', a volte molto. Ci sono perdite. Le cose vanno male. Succede dappertutto quando si hanno astrazioni. Ecco alcuni esempi.
  • Qualcosa di semplice come l'iterazione su un grande array bidimensionale può avere prestazioni radicalmente diverso se lo si fa in orizzontale piuttosto che verticale, a seconda del "grano del legno" - una direzione può portare a errori di pagina molto più che nella direzione opposta ed errori di pagina sono lenti. Anche i programmatori di montaggio dovrebbero essere autorizzati a pretendere di avere un grande spazio indirizzo piatto, ma la memoria virtuale significa che è davvero solo una astrazione, che le perdite quando c'è un page fault e la memoria certo recupera prendere nanosecondi modo più memoria altre operazioni di recupero.
  • Il linguaggio SQL è pensato per astrarre i passi procedurali necessari per interrogare un database, che permette invece di definire semplicemente ciò che si desidera e lasciare che la figura del database i passi procedurali per interrogare esso. Ma in alcuni casi, alcune query SQL sono migliaia di volte più lento di altre query logicamente equivalenti. Un famoso esempio di questo è che alcuni server SQL sono notevolmente più veloci se si specifica ", dove a = b e b = c e a = c" che se si specifica solo ", dove a = b e b = c" anche se il set di risultati è lo stesso. Non dovresti avere a cuore l'procedura, solo le specifiche. Ma a volte le fughe di notizie astrazione e le cause delle prestazioni orribili e si deve uscire l'analizzatore di query piano e studiare ciò che ha fatto male, e capire come rendere il vostro eseguire query più rapidamente.
  • Anche se le librerie di rete come NFS e SMB consentono di considerare il file su macchine remote "come se" fossero locali, a volte la connessione diventa molto lento o va giù, e il file si ferma agire come se fosse locale, e come programmatore si deve scrivere il codice per affrontare questo. L'astrazione di "file remoto è lo stesso file locale" fughe . Ecco un esempio concreto per gli amministratori di sistema Unix. Se mettete home directory degli utenti 'su NFS unità montate (una astrazione), e agli utenti di creare file. Avanti per inoltrare tutte le proprie email da qualche altra parte (un'altra astrazione), e il server NFS va giù mentre nuova e-mail è in arrivo, i messaggi non verranno inoltrati in quanto il file. forward non verrà trovato. La perdita nel astrazione effettivamente causato alcuni messaggi per essere caduto sul pavimento.
  • Classi C + + stringa si suppone che consentono di far finta che le stringhe sono di prima classe di dati. Essi cercano di astrarre il fatto che le stringhe sono duri e consentono di agire come se fossero così facile come numeri interi. Quasi tutte le classi C + + stringa di sovraccaricare l'operatore + in modo da poter scrivere s + "bar" per concatenare. Ma sapete una cosa? Non importa quanti sforzi facciano, non c'è C + + stringa di classe sulla Terra che vi permettono di digitare "pippo" + "bar" , perché le stringhe letterali in C + + sono sempre s char * 'mai, stringhe. L'astrazione è aperta una falla che la lingua non consente di spina. (Ironicamente, la storia della evoluzione del C + + nel corso del tempo può essere descritto come una storia di cercare di tappare le falle nella astrazione stringa. Perché non si può semplicemente aggiungere una classe nativa stringa al linguaggio stesso mi sfugge in questo momento. )
  • E non si può guidare il più velocemente quando piove, anche se la vostra auto è tergicristalli e fari e un tetto e una stufa, che vi proteggerà da preoccuparsi del fatto che piove (che astrarre il tempo), ma Ecco, tu devi preoccuparti di aquaplaning (o aquaplaning in Inghilterra) ea volte la pioggia è così forte non si può vedere molto avanti in modo da andare più lento sotto la pioggia, perché il tempo non potrà mai essere completamente astratto lontano, a causa della legge di astrazioni che perde.
Uno dei motivi per la legge di astrazioni che perde è problematico è che significa che in realtà non astrazioni semplificarci la vita tanto quanto avrebbero dovuto. Quando mi sto allenando a qualcuno di essere un programmatore C + +, sarebbe bello se non ho mai dovuto insegnare loro s char * 'e aritmetica dei puntatori. Sarebbe bello se potessi andare direttamente alle stringhe STL. Ma un giorno faranno scrivere il codice "pippo" + "bar" , e le cose veramente bizzarre che accadrà, e poi dovrò smettere e di insegnare loro tutto su char * 's comunque. Oppure un giorno cercherò di chiamare una funzione API di Windows che viene documentato come aventi un argomento OUT LPTSTR e non saranno in grado di capire come chiamarla fino a quando non conoscere s char * ', e puntatori, e Unicode , e wchar_t, ed i file header TCHAR, e tutta quella roba che le perdite su.
Nell'insegnamento qualcuno sulla programmazione COM, sarebbe bello se potessi semplicemente insegnare loro come usare il wizard di Visual Studio e tutte le funzionalità di generazione del codice, ma se qualcosa va storto, non avranno la più vaga idea di quello che è successo o come eseguire il debug e recuperare da esso. Ho intenzione di insegnare loro tutto IUnknown e CLSID e ProgID e ... oh, l'umanità!
Nell'insegnamento qualcuno su ASP.NET programmazione, sarebbe bello se potessi semplicemente insegnare loro che possono fare doppio clic su cose e poi scrivere il codice che viene eseguito sul server quando l'utente fa clic su queste cose. Infatti ASP.NET astrae la differenza tra la scrittura del codice HTML per gestire cliccando su un collegamento ipertestuale ( <a> ) e il codice per gestire cliccando su un pulsante. Problema: i progettisti ASP.NET necessari per nascondere il fatto che in HTML, non c'è modo di inviare un modulo da un collegamento ipertestuale. Lo fanno generando poche righe di JavaScript e allegando un gestore onclick per il collegamento ipertestuale. Le perdite di astrazione, però. Se l'utente finale ha disattivato JavaScript, l'applicazione ASP.NET non funziona correttamente, e se il programmatore non capisce quello che è stato ASP.NET astrarre via, semplicemente non avrà alcuna idea di cosa è sbagliato.
La legge di astrazioni che perde significa che ogni volta che qualcuno esce con un nuovo codice wizzy generazione strumento che dovrebbe renderci tutti sempre in modo efficiente, si sente un sacco di persone dire "imparare a farlo manualmente, quindi utilizzare lo strumento Wizzy per risparmiare tempo. " Strumenti di generazione di codice che pretendono qualcosa di astratto, come tutte le astrazioni, perdite, e l'unico modo per affrontare le perdite è competente per conoscere come funzionano le astrazioni e ciò che sono astrazione. Così le astrazioni ci salvi l'orario di lavoro, ma non ci salvano tempo di apprendimento.
E tutto questo vuol dire che paradossalmente, anche se abbiamo sempre più in alto strumenti di programmazione a livello di astrazioni sempre meglio, diventando un abile programmatore è sempre più difficile.
Durante il mio primo stage di Microsoft, ho scritto le biblioteche stringa per girare su Macintosh. Un compito tipico: scrivere una versione di strcat che restituisce un puntatore alla fine della stringa nuova. Poche righe di codice C. Tutto quello che facevo era giusto da K & R - un libro sottile sul linguaggio di programmazione C.
Oggi, per lavorare su CityDesk, ho bisogno di sapere di Visual Basic, COM, ATL, C + +, InnoSetup, Internet Explorer interni, espressioni regolari, DOM, HTML, CSS e XML. Tutti gli strumenti di alto livello rispetto al vecchio K & R roba, ma devo ancora conoscere il K & R o roba sto pane tostato.
Dieci anni fa, avremmo potuto immaginare che nuovi paradigmi di programmazione avrebbe reso più semplice la programmazione ormai. Infatti, le astrazioni abbiamo creato nel corso degli anni non ci permettono di affrontare nuovi ordini di complessità nello sviluppo di software che non abbiamo a che fare con dieci o quindici anni fa, come la programmazione GUI e programmazione di rete. E mentre questi grandi strumenti, come moderni OO forme linguaggi basati su, cerchiamo di ottenere un sacco di lavoro incredibilmente in fretta, all'improvviso un giorno abbiamo bisogno di capire un problema in cui l'astrazione trapelato, e ci vogliono 2 settimane. E quando avete bisogno di assumere un programmatore di fare la maggior parte di programmazione VB, non è sufficiente per assumere un programmatore VB, perché avranno completamente bloccati nel catrame ogni volta che le fughe di notizie astrazione VB.

lunedì 14 novembre 2011

Id in Rdf e OWL

3.1.1. Classi Semplici con Nome
Class, rdfs:subClassOf

Il concetto fondamentale in un dominio deve corrispondere alle classi che sono alla radice delle varie strutture ad albero che ne rappresentano la tassonomia. Ogni individuo nel mondo di OWL è un membro della classe owl:Thing. Per questo motivo ogni nuova classe definita dall'utente sarà implicitamente una sottoclasse della owl:Thing. Le classi radice di uno specifico dominio, possono essere definite semplicemente dichiarandone il nome. OWL permette anche la definizione della classe vuota, owl:Nothing.
Per il nostro esempio del dominio dei vini, abbiamo creato tre classi radice: Winery(Azienda Vinicola), Region(Regione), e ConsumableThing(Bene consumabile).
<owl:Class rdf:ID="Winery"/> 
<owl:Class rdf:ID="Region"/> 
<owl:Class rdf:ID="ConsumableThing"/> 
Da notare che per ora abbiamo solo detto che esistono classi a cui sono stati dati questi nomi, mediante la sintassi 'rdf:ID='. Formalmente noi non sappiamo niente altro di queste classi se non il fatto che esistono, grazie all'uso di etichette che le definiscono mediante i termini comuni in lingua Inglese. E fino a che le classi esistono solamente, potrebbero non avere nessun membro. Per quello che sappiamo fino a questo punto, le classi potrebbero essere anche state chiamate Thing1, Thing2, e Thing3.
E' importante ricordare che le definizioni possono essere incrementali e distribuite. In particolare avremo molto da dire successivamente riguardo la classe Winery.
La sintassi rdf:ID="Region" è usata per introdurre un nome come parte della sua definizione. Questo è il costrutto rdf:ID attribute ([RDF], 7.2.22) che risulta del tutto simile al più familiare attributo ID definito dall'XML. All'interno di questo documento, potremmo ora riferirci alla classe Region usando il termine #Region, ad esempio scrivendo rdf:resource="#Region". Altre ontologie possono invece riferirvisi usando la sua forma completa, "http://www.w3.org/TR/2004/REC-owl-guide-20040210/wine#Region".

RDF Risorse, Proprietà, e valore della proprietà

RDF Risorse, Proprietà, e valore della proprietà

RDF identifica le cose utilizzando identificatori Web (URI), e descrive le risorse con proprietà e valori di proprietà.
Spiegazione del valore delle risorse, proprietà e di proprietà:
  • Una risorsa è tutto ciò che può avere un URI, come "http://www.w3schools.com/rdf"
  • Una proprietà è una risorsa che ha un nome, come "autore" o "home page"
  • Il valore  è il valore di una proprietà, come ad esempio "Jan Egil Refsnes" o "http://www.w3schools.com" (si noti che un valore di proprietà può essere un'altra risorsa)
Il seguente documento RDF potrebbe descrivere la risorsa "http://www.w3schools.com/rdf":
<? Xml version = "1.0"?>

<RDF>
  <Descrizione About="http://www.w3schools.com/rdf">
    <author> Jan Egil Refsnes </ autore>
    <homepage> http://www.w3schools.com </ homepage>
  </ Descrizione>
</ RDF>
lampadaL'esempio sopra è semplificata. Spazi dei nomi vengono omessi.

Le dichiarazioni RDF

La combinazione di una risorsa, una proprietà e un valore di proprietà forma una dichiarazione (nota come predicato soggetto e oggetto di una dichiarazione).
Diamo un'occhiata ad alcune affermazioni esempio per ottenere una migliore comprensione:
Dichiarazione: "L'autore di http://www.w3schools.com/rdf è Jan Egil Refsnes".
  • L'oggetto della dichiarazione di cui sopra è: http://www.w3schools.com/rdf
  • Il predicato è: autore
  • L'oggetto è: Jan Egil Refsnes
Dichiarazione: "La homepage di http://www.w3schools.com/rdf è http://www.w3schools.com".
  • L'oggetto della dichiarazione di cui sopra è: http://www.w3schools.com/rdf
  • Il predicato è: homepage
  • L'oggetto è: http://www.w3schools.com

web semantico -- Ontologie - owl

La natura delle ontologie
L’OWL, come detto, è una componente delle attività dedicate al Semantic Web. Questi sforzi si pongono l’obiettivo di rendere le risorse presenti sul Web più accessibili e comprensibili per le applicazioni, attraverso l’aggiunta di informazioni supplementari che descrivano i dati sui quali occorre effettuare delle elaborazioni. Poiché il Semantic Web è, per sua natura, una realtà distribuita, l’OWL deve permettere di raccogliere le informazioni tra le più disparate fonti. Questo è in parte realizzato consentendo alle ontologie di collegarsi fra loro, prevedendo meccanismi per l’importazione delle informazioni le une dalle altre. Inoltre il linguaggio non tratta le descrizioni delle risorse come informazioni da confinare in un singolo file o come destinate esclusivamente ad un determinato ambito di validità, ma le considera di valenza globale (open world assumption). Una classe C1, anche se definita originariamente nell’ontologia O1, può essere estesa e/o specializzata in altre ontologie. Questa caratteristica implica che le nuove ontologie non possono ritrattare ciò che è dichiarato in quelle precedenti. Sebbene le nuove informazioni possano essere contraddittorie, i fatti e le implicazioni possono solo essere aggiunti, mai eliminati. L’evenienza di queste contraddizioni è qualcosa che i costruttori di ontologie devono tenere in debita considerazione. Ci si aspetta comunque che saranno tool automatici ad evidenziare queste inconsistenze.
Namespace
Prima di poter utilizzare un insieme di termini, occorre una precisa specifica dei vocabolari che saranno utilizzati. Una prima componente standard di tutte le ontologie include un insieme di dichiarazioni di namespace XML, incluso nel tag di apertura rdf:RDF.
Questa sezione fornisce un metodo per interpretare senza ambiguità gli identificatori e rende il resto dell’ontologia decisamente più leggibile.
Un primo esempio (per la catalogazione dei vini di una cantina), in notazione RDF/XML, è riportato di seguito:
La prima dichiarazione identifica il namespace di default per questa ontologia; dal momento che un qualified name (QName) senza prefisso si riferisce all’ontologia corrente è sempre bene prevedere un’assegnazione di questo tipo. La seconda definisce l’URI base per questo documento che sarà utilizzato per “completare” tutti gli URIref relativi. Il terzo namespace indica che, in questo documento, gli elementi col prefisso owl: devono essere interpretati come riferimenti ai concetti estratti dal namespace associato all’URIref http://www.w3.org/2002/07/owl#. Questa è una dichiarazione convenzionale usata per introdurre il vocabolario OWL. Le restanti dichiarazioni stabiliscono che i prefissi rdf:, rdfs: e xsd: fanno riferimento ai costrutti definiti da RDF e RDF Schema ed ai datatype di XML Schema.
Intestazione e corpo delle ontologie OWL
Una volta definiti i namespace che saranno utilizzati, il secondo passo è includere una collezione di asserzioni che riguardano l’ontologia stessa, raggruppate sotto il tag owl:Ontology (annotation). Queste asserzioni sono definite attraverso tag dedicati e si occupano di specificare commenti, controllo di versione, inclusione di altre ontologie, eccetera.
1<owl:Ontology rdf:about="">
2<rdfs:comment>Un’ontologia OWL di esempio</rdfs:comment>
3<owl:priorVersion rdf:resource="http://example.org/20031215/wine"/>
4<owl:imports rdf:resource="http://example.org/20040210/food"/>
5<rdfs:label>Ontologia dei Vini</rdfs:label>
6...
7</owl:Ontology>
In questa sezione si inseriscono di norma tutti i metadati relativi al documento e spesso sono presenti informazioni non direttamente collegate all’ontologia. Questo accade perché tali documenti non sono sempre utilizzati per descrivere un’ontologia nel significato tradizionale del termine: in alcune applicazioni le ontologie non riguardano gli individual ma solo le classi e le proprietà per descrivere, in generale, il dominio di riferimento. L’attributo rdf:about fornisce un nome o un riferimento per l’ontologia. Quando il valore è una stringa vuota, ossia il caso più comune, il nome dell’ontologia è l’URI base dell’elemento owl:Ontology. Tipicamente questo è l’URI del documento che contiene l’ontologia anche se, con l’uso di xml:base, è possibile sostituire quello predefinito. Specificando il tag owl:imports è possibile importare un’ontologia all’interno di un’altra: questo significa che, per l’ontologia corrente, saranno valide tutte le asserzioni presenti nell’ontologia importata. Per utilizzare al meglio l’ontologia importata è conveniente assegnarle un namespace. È bene precisare che l’importazione può anche fallire, fondamentalmente per la non reperibilità o disponibilità delle risorse, problema molto frequente in un ambiente distribuito come il Web. Si noti che, per utilizzare il vocabolario OWL, non è stato necessario importare il file di ontologia owl.rdf ed anzi questa importazione è sconsigliata. Questa sezione è seguita dalle effettive asserzioni che costituiscono l’ontologia, le quali si concludono col tag di chiusura </rdf:RDF> che segna la fine del documento. Un’ontologia scritta in OWL contiene, essenzialmente, una sequenza di annotazioni, assiomi e fatti. Le annotazioni, alcune delle quali già analizzate in precedenza, sono usate per dare un nome all’ontologia, per registrare informazioni sull’autore e sull’ontologia stessa, per importare altre ontologie, ecc.. La parte centrale invece è composta da assiomi e fatti, che forniscono le informazioni sulle classi, sulle proprietà e sugli individual (istanze di proprietà e classi) ad ognuno dei quali è assegnato un identificatore nella forma di un URIref. Innanzitutto è importante chiarire che le classi denotano insiemi di individual; le proprietà, invece, legano gli individual ad altre informazioni e sono divise in quattro gruppi distinti:
  • data-valued, esplicitano i valori delle proprietà degli individual;
  • individual-valued, mettono in relazione un individual con gli altri;
  • annotation, includono commenti riguardo a individual, classi, proprietà e nomi di ontologie;
  • ontology properties, connettono le ontologie tra loro.
In OWL sono previste due classi predefinite, entrambe appartenenti al namespace owl:. La classe con identificatore owl:Thing è la classe di tutti gli individual, la classe owl:Nothing indica, conseguentemente, la classe vuota: entrambe sono parte di OWL Lite. Per quanto riguarda le annotation, ce ne sono molte predefinite in OWL, alcune delle quali mutuate dall’RDF: owl:versionInfo, rdfs:label, rdfs:comment, rdfs:seeAlso, e rdfs:isDefinedBy. Esistono anche proprietà di default per la descrizione dell’ontologia quali owl:imports, owl:priorVersion, owl:backwardCompatibleWith, e owl:incompatibleWith. Per quanto concerne i fatti, essi sono sostanzialmente di due tipologie. La prima tipologia fornisce informazioni riguardo un particolare individual, specificando le classi cui appartiene, le proprietà possedute ed i relativi valori. Ad un individual può essere assegnato un individualID facoltativo (alcuni individual sono anonimi: blank node) che può essere utilizzato per riferirsi ad esso. La seconda tipologia di fatti è utilizzata principalmente per operare sugli identificatori degli individual (renderli identici o distinti). Gli assiomi sono utilizzati per fornire informazioni relativamente a classi e proprietà. In particolare essi sono usati per associare a queste ultime una parziale o completa specifica delle loro caratteristiche. La definizione degli assiomi presenta delle differenze tra OWL Lite e OWL DL. Ogni assioma di classe nella versione Lite contiene una collezione di classi più generali ed una collezione di restrizioni sulle proprietà locali, nella forma di restriction construct. Questi ultimi stabiliscono il range di una proprietà, quanti valori sono permessi, e l’elenco di quelli obbligatori. La classe così specificata è resa equivalente all’intersezione tra le classi e le restrizioni o ad un suo sottoinsieme. In OWL DL un assioma di classe è costituito da un insieme di descrizioni, le quali possono essere classi più generali, restrizioni, set di individual e combinazioni booleane tra queste. Le classi possono inoltre essere specificate tramite enumerazione, rese equivalenti o disgiunte. Le proprietà possono essere equivalenti ad altre o esserne una specializzazione; possono essere rese funzionali, funzionali inverse, simmetriche o transitive, e vi si possono associare domini e range. Tuttavia molte informazioni che riguardano le proprietà sono più agevolmente espresse mediante restrizioni in cui è possibile specificare range validi localmente e cardinalità. In definitiva le ontologie permettono di rappresentare le risorse in maniera più completa di quanto si possa fare con RDF, disponendo di costrutti decisamente più efficaci ed espressivi. È bene ribadire, comunque, che le caratteristiche aggiuntive di cui dispone l’OWL non sono state implementate direttamente in RDF (nonostante queste fossero effettivamente emerse durante la fase di analisi) al fine di soddisfare i requisiti di modularità e stratificazione previsti in sede di progetto.
Caratteristiche di RDF in OWL
Collegate allo Schema RDF, sono incluse le seguenti caratteristiche OWL.
  • Class: una classe definisce un gruppo di individui che sono legati tra di loro perché condividono le stesse proprietà. Per esempio, Deborah e Frank appartengono ambedue alla classe Persona. Le classi possono essere organizzate in una gerarchia di specializzazione usando subClassOf. Esiste una classe integrata molto più generale chiamata Thing che è la classe di tutti gli individui ed è una superclasse di tutte le classi OWL. Esiste anche una classe integrata specifica chiamata Nothing che è la classe che non ha istanze ed è una sottoclasse di tutte le classi OWL.
  • rdfs:subClassOf: gerarchie di classe possono essere create grazie ad una o più istruzioni secondo cui una classe è una sottoclasse di un’altra classe. Per esempio, si può affermare che la classe Persona è una sottoclasse della classe Mammifero. Un ragionatore può dedurre da ciò che se un individuo è una Persona, allora è anche un Mammifero.
  • rdf:Property: le proprietà possono essere usate per stabilire relazioni tra individui oppure da individui a valori di dati. Esempi di proprietà possono essere haFiglioFiglia, haParente, haFratelloSorella, e haEtà. I primi tre esempi possono essere usati per collegare un’istanza di una classe Persona ad un’altra istanza della classe Persona (e pertanto sono occorrenze di ObjectProperty) mentre l’ultimo (haEtà) può essere usato per collegare un’istanza della classe Persona ad un’istanza del tipo di dati NumeroIntero (e pertanto è un’occorrenza di DatatypeProperty). Sia owl:ObjectProperty sia owl:DatatypeProperty sono sottoclassi della classe rdf:Property di RDF.
  • rdfs:subPropertyOf: gerarchie di proprietà possono essere create attraverso una o più istruzioni secondo le quali una proprietà è una sottoproprietà di una o più altre proprietà. Per esempio, si può affermare che haFratelloSorella è una sottoproprietà di haParente. Da ciò un ragionatore può dedurre che se un individuo è collegato ad un altro dalla proprietà haFratelloSorella, allora esso è collegato all’altro dalla proprietà haParente.
  • rdfs:domain: il dominio di una proprietà limita gli individui a cui si applica la proprietà. Se una proprietà collega un individuo ad un altro individuo e se la proprietà ha una classe per uno dei propri domini, allora l’individuo deve appartenere alla classe. Per esempio, si può affermare che la proprietà haFiglioFiglia ha il dominio Mammifero. Un ragionatore può quindi dedurre che se Frank haFiglioFiglia Anna, allora Frank deve essere un Mammifero. Si osservi che rdfs:domain è chiamata limitazione globale in quanto la limitazione viene affermata in base alla proprietà e non solo in base alla proprietà quando è associata con una particolare classe.
  • rdfs:range: la portata (range) di una proprietà limita gli individui che la proprietà può avere come suoi valori. Se la proprietà collega un individuo ad un altro individuo e se la proprietà ha una classe come sua portata, allora l’altro individuo deve appartenere alla classe portata (range). Per esempio, si può dichiarare che la proprietà haFiglioFiglia possiede la portata di Mammifero. Da ciò un ragionatore può dedurre che se Louise è collegata a Deborah attraverso la proprietà haFiglioFiglia (per es., Deborah è la figlia di Louise), allora Deborah è un Mammifero. La portata è anche una limitazione globale tanto quanto il dominio di cui sopra.

domenica 13 novembre 2011

Esempi SPARQL e dbpedia

About: Silvio Berlusconi
An Entity of Type : person, from Named Graph : http://dbpedia.org, within Data Space : dbpedia.org
About DBpedia

Property    Value
dbpedia-owl:abstract    
    * Silvio Berlusconi ist ein italienischer Politiker und Unternehmer.
dbpedia-owl:activeYearsEndDate    
    * 2010-10-04 (xsd:date)
dbpedia-owl:activeYearsStartDate    
    * 2010-05-05 (xsd:date)
dbpedia-owl:almaMater    
    * dbpedia:University_of_Milan
dbpedia-owl:birthDate    
    * 1936-09-29 (xsd:date)
dbpedia-owl:birthPlace    
    * dbpedia:Milan
    * dbpedia:Kingdom_of_Italy_(1861–1946)
dbpedia-owl:child    
    * dbpedia:Marina_Berlusconi
    * dbpedia:Pier_Silvio_Berlusconi
    * dbpedia:Barbara_Berlusconi
dbpedia-owl:deputy    
    * dbpedia:Giulio_Tremonti
dbpedia-owl:office    
    * Acting
    * Minister of Foreign Affairs
    * Minister of Health
dbpedia-owl:orderInOffice    
    * Prime Minister of Italy
dbpedia-owl:otherParty    
    * dbpedia:Forza_Italia
dbpedia-owl:party    
    * dbpedia:The_People_of_Freedom
dbpedia-owl:president    
    * dbpedia:Carlo_Azeglio_Ciampi
    * dbpedia:Giorgio_Napolitano
    * dbpedia:Oscar_Luigi_Scalfaro
dbpedia-owl:profession    
    * dbpedia:Businessperson
dbpedia-owl:region    
    * dbpedia:Molise
    * dbpedia:Latium
    * dbpedia:Lombardy
    * dbpedia:Campania
dbpedia-owl:residence    
    * dbpedia:Arcore
    * dbpedia:Kingdom_of_Italy_(1861–1946)
dbpedia-owl:spouse    
    * dbpedia:Veronica_Lario
dbpedia-owl:successor    
    * dbpedia:Lamberto_Dini
    * dbpedia:Livia_Turco
    * dbpedia:Romano_Prodi
dbpedia-owl:thumbnail    
    * http://upload.wikimedia.org/wikipedia/commons/
    thumb/4/43/Silvio_Berlusconi_%282010%29.jpg/200px-Silvio_Berlusconi_%282010%29.jpg
dbpedia-owl:wikiPageExternalLink    
    * http://www.newyorker.com/reporting/2008/11/03/081103fa_fact_stille
    * http://www.margheritaonline.it/stampa/scheda.php?id_stampa=4671
    * http://www.ifex.org/en/content/view/full/66079/
    * http://www.forza-italia.it/
    * http://news.bbc.co.uk/1/hi/world/europe/2055418.stm
dbpprop:after    
    * dbpedia:Jean_Chrétien
    * dbpedia:Francesco_Amirante
dbpprop:birthDate    
    * 1936-09-29 (xsd:date)
dbpprop:birthPlace    
    * dbpedia:Milan
    * dbpedia:Kingdom_of_Italy_(1861–1946)
dbpprop:children    
    * dbpedia:Marina_Berlusconi
    * dbpedia:Pier_Silvio_Berlusconi
    * dbpedia:Barbara_Berlusconi
    * Luigi
    * Eleonora
dbpprop:dateOfBirth    
    * 29 (xsd:integer)
dbpprop:deputy    
    * dbpedia:Giulio_Tremonti
dbpprop:name    
    * Silvio Berlusconi
    * Berlusconi, Silvio
dbpprop:office    
    * dbpedia:Ministry_of_Economic_Development_(Italy)
    * dbpedia:Minister_of_Foreign_Affairs_(Italy)
dbpprop:otherparty    
    * Forza Italia
dbpprop:party    
    * The People of Freedom
dbpprop:placeOfBirth    
dbpprop:president    
    * dbpedia:Carlo_Azeglio_Ciampi
    * dbpedia:Giorgio_Napolitano
    * dbpedia:Oscar_Luigi_Scalfaro
dbpprop:profession    
    * dbpedia:Businessperson
dbpprop:religion    
    * Roman Catholicism
dbpprop:residence    
    * Arcore, Italy
dbpprop:shortDescription    
    * Italian politician, entrepreneur, and media proprietor
dbpprop:signature    
    * Silvio Berlusconi Signature.svg
dcterms:subject    
    * category:A.C._Milan
    * category:Italian_businesspeople
    * category:The_People_of_Freedom_politicians
    * category:Living_people
    * category:1936_births
    * category:Newspaper_publishers_(people)
    * category:Italian_billionaires
rdf:type    
    * owl:Thing
    * dbpedia-owl:Person
    * http://schema.org/Person
    * yago:Person100007846
    * yago:CurrentNationalLeaders
    * yago:PrimeMinistersOfItaly
    * foaf:Person
    * yago:PeopleFromMilan
    * dbpedia-owl:OfficeHolder
    * yago:LivingPeople
    * yago:ItalianMassMediaOwners
    * http://umbel.org/umbel/rc/PrimeMinister_HeadOfGovernment
    * yago:ForzaItaliaPoliticians
    * yago:ItalianBillionaires
    * http://umbel.org/umbel/rc/Politician
    * yago:ThePeopleOfFreedomPoliticians
    * http://umbel.org/umbel/rc/PersonWithOccupation
rdfs:comment    
    * Silvio Berlusconi es un político y empresario italiano,
    actualmente primer ministro de Italia y líder del partido El Pueblo de la Libertad.
    Es asimismo propietario del equipo de fútbol AC Milan.
rdfs:label    
    * Silvio Berlusconi
    * Silvio Berlusconi
    * Silvio Berlusconi
foaf:depiction    
    * http://upload.wikimedia.org/wikipedia/commons/4/43/Silvio_Berlusconi_%282010%29.jpg
foaf:page    
    * http://en.wikipedia.org/wiki/Silvio_Berlusconi
foaf:surname    
    * Berlusconi
is dbpedia-owl:firstLeader of   
    * dbpedia:Italian_Senate_election_in_Lombardy,_2001
    * dbpedia:Italian_general_election,_2001
is dbpedia-owl:starring of   
    * dbpedia:Videocracy_(film)
    * dbpedia:Claudio_Scajola
is owl:sameAs of   
    * http://www4.wiwiss.fu-berlin.de/flickrwrappr/photos/Silvio_Berlusconi
    * http://data.nytimes.com/27152631733516660623
    * yago-res:Silvio Berlusconi
is foaf:primaryTopic of   
    * http://en.wikipedia.org/wiki/Silvio_Berlusconi

Esempi SPARQL e php

While the code may look complex at first blush, it is actually a straightforward tool.

We will begin by taking a quick glance at the first dozen lines:

  // URL to DB Pedia's SPARQL endpoint.
  $url = 'http://dbpedia.org/sparql';

  // The SPARQL query to run.
  $sparql = '
    PREFIX foaf: <http://xmlns.com/foaf/0.1/>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    SELECT ?uri ?name ?label
    WHERE {
      ?uri foaf:name ?name .
      ?uri rdfs:label ?label
      FILTER (?name = "The Beatles")
      FILTER (lang(?label) = "en")
    }
  ';

  // We first set up the parameters that will be sent.
  $params = array(
    'query' => $sparql,
    'format' => 'application/sparql-results+xml',
  );

  // DB Pedia wants a GET query, so we create one.
  $data = http_build_query($params);
  $url .= '?' . $data;


The snippet above shows all of the preparation we must make to run the query.

We begin with a base $url, which points to the DBPedia SPARQL endpoint. Next we write our SPARQL query. The query above is the same as the one we saw earlier in this article.

With the query and the base URL, we need to build a full URL to access the remote server. This is done with the $params array. There we create the name/value pairs that will be condensed into a GET string by http_build_query(). Note that we set the MIME type as the value of the $params['format'] entry. This is to tell the remote server what kind of data we expect to have returned.

A SPARQL query need not return information encoded as XML. Other data formats are equally capable of representing SPARQL query results. XML is probably the most widely used, though, and is the easiest for us to parse.

In the last line of the snippet above, we assemble our base URL and query params into a complete URL.

Next, we need to execute the query and handle the results.

<?php
  // Next, we simply retrieve, parse, and output the contents.
  $qp = qp($url, 'head');

  // Get the headers from the resulting XML.
  $headers = array();
  foreach ($qp->children('variable') as $col) {
    $headers[] = $col->attr('name');
  }

  // Get rows of data from result.
  $rows = array();
  $col_count = count($headers);
  foreach ($qp->top()->find('results>result') as $row) {
    $cols = array();
    $row->children();
    for ($i = 0; $i < $col_count; ++$i) {
      $cols[$i] = $row->branch()->eq($i)->text();
    }
    $rows[] = $cols;
  }
?>

We begin by creating a new QueryPath object, stored in $qp. Based on the CSS query, we can see that it will be pointed to the header element in the returned results. This element will contain the names of each of the returned variables of data.

From there, we build an array of $headers, getting the name of each returned variable. These we will use to generate the headers in our table. The headers come back in variable elements, and each variable has a name attribute. To fetch them, then, we select the variables and loop through them, retrieving the name attribute of each.

Next comes the fancy part. We need to loop through each result and fetch each variable out of each result. Or, to use the table metaphor we SQL developers are familiar with, we loop through each row, and fetch each column of data. This is al accomplished in the this foreach loop:

foreach ($qp->top()->find('results>result') as $row) {
  $cols = array();
  $row->children();
  for ($i = 0; $i < $col_count; ++$i) {
    $cols[$i] = $row->branch()->eq($i)->text();
  }
  $rows[] = $cols;


When this loop is finished, there will be an array of rows, each of which will have an array of columns. The index of the columns should match the index of the headers array. That is how we correlate headers to columns. You may also notice that we use QueryPath's 'branch() method in combination with eq() so that we can (relatively cheaply) get the text for each column.

With this complete, the next thing to do is format the table output:

Esempi SPARQL

Abstracts of movies starring Tom Cruise, released before 1999

SELECT ?subject ?label ?released ?abstract WHERE {
?subject rdf:type <http://dbpedia.org/ontology/Film>.
?subject dbpedia2:starring <http://dbpedia.org/resource/Tom_Cruise>.
?subject rdfs:comment ?abstract.
?subject rdfs:label ?label.
FILTER(lang(?abstract) = "en" && lang(?label) = "en").
?subject <http://dbpedia.org/ontology/releaseDate> ?released.
FILTER(xsd:date(?released) < "2000-01-01"^^xsd:date).
} ORDER BY ?released
LIMIT 20

----
The official websites of companies with more than 50000 employees

SELECT DISTINCT ?subject
                ?employees
                ?homepage
  WHERE
    {
      ?subject  rdf:type               <http://dbpedia.org/class/yago/Company108058098>  .
      ?subject  dbpedia2:numEmployees  ?employees
        FILTER  ( xsd:integer(?employees) >= 50000 )                                     .
      ?subject  foaf:homepage          ?homepage                                         .
    }
  ORDER BY  DESC(xsd:integer(?employees))
  LIMIT  20
  ----

Cities with more than 2 million habitants

SELECT ?subject ?population WHERE {
?subject rdf:type <http://dbpedia.org/ontology/City>.
?subject <http://dbpedia.org/ontology/populationUrban> ?population.
FILTER (xsd:integer(?population) > 2000000)
}
ORDER BY DESC(xsd:integer(?population))
LIMIT 20

---------------

Querying the Infobox Ontology

SELECT *
  WHERE
    {
      ?e <http://dbpedia.org/ontology/series>         <http://dbpedia.org/resource/The_Sopranos>  .
      ?e <http://dbpedia.org/ontology/releaseDate>    ?date                                       .
      ?e <http://dbpedia.org/ontology/episodeNumber>  ?number                                     .
      ?e <http://dbpedia.org/ontology/seasonNumber>   ?season
    }
  ORDER BY DESC(?date)
 
-----

Executing a SPARQL Query from QueryPath

Executing a SPARQL Query from QueryPath

The Semantic Web. It is a concept that has sparked heated debate for years. While the debate may continue to rage for some time, there are already a host of technologies that can be used to build advanced applications based on XML technology. In this article, we will see how the SPARQL query language can be used to retrieve XML information from remote semantic databases (usually called SPARQL endpoints).
QueryPath already contains all of the tools necessary for running a SPARQL query and handling the results. This is not because QueryPath has been specially fitted to the task, but because SPARQL uses technologies that are widely supported: XML and HTTP. Since QueryPath can be used to make HTTP requests and then digest the XML results, we can use it to execute SPARQL queries and handle the results.
In this article, we will look at a basic SPARQL query, and see how we can use QueryPath to execute it and parse the returned results.
While SPARQL will be introduced here, it is far too robust a language to be explained in a short article. One starting point is the SPARQL Working Group home page.
The queries presented in this chapter will be run against DBPedia, a semantic version of Wikipedia. It makes all of the content from Wikipedia available as semantic content.

The SPARQL Query: A Brief Anatomy

Let's begin by looking at the SPARQL query that we will be running:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?uri ?name ?label
WHERE {
  ?uri foaf:name ?name .
  ?uri rdfs:label ?label
  FILTER (?name = "The Beatles")
  FILTER (lang(?label) = "en")
}
The query above begins by defining two prefixes:
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
A prefix is a convenient method for representing a namespace URI with a short string. Above, we create one for the Friend of a Friend namespace (foaf:) and one for the RDF Schema namespace (rdfs). Now, whenever we need to represent entities from those two schemata, we can just use the short prefix instead of the full URL.
The next part of the code above is the actual query:
SELECT ?uri ?name ?label
WHERE {
  ?uri foaf:name ?name .
  ?uri rdfs:label ?label
  FILTER (?name = "The Beatles")
  FILTER (lang(?label) = "en")
}
We are going to use the URI a lot, and it is easy to get hung up on the URI as a URL expressing a location. However, you are better off thinking of the URI as a unique identifier for an object -- a unique identifier that just happens to also be "dereferenceable". We can, in fact, use the URI to access information over the network (in this case).
If you have developed SQL before, this should look vaguely familiar. It functions similarly to a SQL SELECT operation. Here's what the code above does, phrased in plain English:
  1. Select the uri, name, and label
  2. where...
  3. the uri has the name ?name (or, where the uri's name is stored in ?name)
  4. the uri has a label ?label
  5. the name is "The Beatles"
  6. the language of the label is English
There are a few things to note about the structure of the query.
First, remember that the URI (?uri), is just a unique identifier. It is functioning sort of like a primary key for each object we query.
Second, the items that begin with question marks (?) are variables. Their value is assigned when the query is being executed.
Third, the items in the WHERE clause are not simply restrictive, as they are in SQL. In fact, the purpose of lines 3 and 4 isn't so much to limit the items returned, but to express a relationship between items. The general pattern of lines 3 and 4 is:
?subject ?relationship ?object
So ?uri foaf:name ?name can be understood to mean "Some object ID (subject) named (relationship) Some name(object)". As you may have guessed, foaf:name expresses the relationship "is named". Likewise, rdfs:label expresses the relationship "is labeled".
Assuming that we did not have the two FILTER functions, the query would simply return all objects (together with their names and labels) that had a name and a label.
The FILTER function is used to limit what content is returned. Above, we used two filters:
FILTER (?name = "The Beatles")
  FILTER (lang(?label) = "en")
The first filter says that the value of ?name must match (exactly) the string "The Beatles". Keep in mind that a given item may have multiple foaf:name items. The filter need only match one of the items.
The second filter requires that the label's language be in English. RDFS labels in the DBPedia database tend to have attributes indicating the language of the label. We are only interested in the English language content. In the query above, if we omit this, we will see results in Chinese, German, and Spanish, as well as other languages.
Putting this all together, then, our query will return the URI, the name, and the label for any URIs in the database that...
  • Have a name
  • Have a label
  • Have a name that is "The Beatles"
  • Have a label that is in English.
Next, we're ready to see how this query can be run against a remote, publicly available SPARQL endpoint (server) from QueryPath.

Running the Query

The query is, by far, the most complex aspect of our sample code. Here's what the entire code looks like:
<?php
require '../src/QueryPath/QueryPath.php';
 
// We are using the dbpedia database to execute a SPARQL query.
 
// URL to DB Pedia's SPARQL endpoint.
$url = 'http://dbpedia.org/sparql';
 
// The SPARQL query to run.
$sparql = '
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  SELECT ?uri ?name ?label
  WHERE {
    ?uri foaf:name ?name .
    ?uri rdfs:label ?label
    FILTER (?name = "The Beatles")
    FILTER (lang(?label) = "en")
  }
';
 
// We first set up the parameters that will be sent.
$params = array(
  'query' => $sparql,
  'format' => 'application/sparql-results+xml',
);
 
// DB Pedia wants a GET query, so we create one.
$data = http_build_query($params);
$url .= '?' . $data;
 
// Next, we simply retrieve, parse, and output the contents.
$qp = qp($url, 'head');
 
// Get the headers from the resulting XML.
$headers = array();
foreach ($qp->children('variable') as $col) {
  $headers[] = $col->attr('name');
}
 
// Get rows of data from result.
$rows = array();
$col_count = count($headers);
foreach ($qp->top()->find('results>result') as $row) {
  $cols = array();
  $row->children();
  for ($i = 0; $i < $col_count; ++$i) {
    $cols[$i] = $row->branch()->eq($i)->text();
  }
  $rows[] = $cols;
}
 
// Turn data into table.
$table = '<table><tr><th>' . implode('</th><th>', $headers) . '</th></tr>';
foreach ($rows as $row) {
  $table .= '<tr><td>';
  $table .= implode('</td><td>', $row);
  $table .= '</td></tr>';
}
$table .= '</table>';
 
// Add table to HTML document.
qp(QueryPath::HTML_STUB, 'body')->append($table)->writeHTML();
?>

venerdì 16 settembre 2011

Modifica logo joomla

cbg

giovedì 15 settembre 2011

Procedure Trigger, function trigger

39.9. Procedure Trigger

PL/pgSQL può essere usato per definire procedure trigger. Una procedura trigger viene creata con il comando CREATE FUNCTION, dichiarandola come una funzione senza argomenti e trigger come tipo di ritorno. Notare che la funzione deve essere dichiarata senza argomenti anche se si aspetta di ricevere argomenti specificati in CREATE TRIGGER - gli argomenti del trigger sono passati via TG_ARGV, come descritto sotto.
Quando una funzione PL/pgSQL è chiamata come trigger, diverse variabili speciali sono create automaticamente nel blocco superiore. Esse sono:

NEW
Tipo di dato RECORD; variabile che tiene la nuova riga del database per operazioni INSERT/UPDATE in trigger a livello di riga. Questa variabile è NULL in trigger a livello di istruzione e per operazioni DELETE.
OLD
Tipo di dato RECORD; variabile che tiene la vecchia riga del database per operazioni UPDATE/DELETE in trigger a livello di riga. Questa variabile è NULL in trigger a livello di istruzione e per operazioni INSERT.
TG_NAME
Tipo di dato name; variabile che contiene il nome del trigger attualmente attivato.
TG_WHEN
Data type text; a string of either Tipo di dato text; una stringa BEFORE o AFTER a seconda della definizione del trigger.
TG_LEVEL
Tipo di dato text; una stringa ROW o STATEMENT a seconda della definizione del trigger.
TG_OP
Data type text; a string of Tipo di dato text; una stringa INSERT, UPDATE, DELETE, o TRUNCATE che dice per quale operazione è stato attivato il trigger.
TG_RELID
Tipo di dato oid; l'ID dell'oggetto della tabella che ha causato l'invocazione del trigger.
TG_RELNAME
Tipo di dato name; il nome della tabella che ha causato l'invocazione del trigger. Questo ora è deprecato, e può sparire in una versione futura. Usare invece TG_TABLE_NAME.
TG_TABLE_NAME
Tipo di dato name; il nome della tabella che ha causato l'invocazione del trigger.
TG_TABLE_SCHEMA
Tipo di dato name; il nome dello schema della tabella che ha causato l'invocazione del trigger.
TG_NARGS
Tipo di dato integer; il numero di argomenti forniti alla procedura trigger nell'istruzione CREATE TRIGGER.
TG_ARGV[]
Tipo di dato text; gli argomenti dell'istruzione CREATE TRIGGER. L'indice conta da 0. Gli indici invalidi (minori di 0 o maggiori di, o uguali, a tg_nargs) risultano in un valore null.

Una funzione trigger deve restituire o NULL o un valore record/riga avente esattamente la struttura della tabelle per cui è stato attivato il trigger.
Trigger a livello di riga attivati prima (BEFORE) possono restituire null per segnalare al gestore dei trigger di saltare il resto dell'operazione per questa riga. (per es., i trigger successivi non vengono attivati, e le INSERT/UPDATE/DELETE non accadono per questa riga). Se viene restituito un valore nonnull allora l'operazione procede con quel valore della riga. Restituire un valore rida diverso dal valore originale di NEW altera la riga che sarà inserita o aggiornata. Così, se la funzione trigger vuole che l'azione di trigger riesca normalmente senza alterare il valore della riga, deve essere restituito NEW (o un valore ad esso equivalente). Per modificare la riga da salvare, è possibile sostituire singoli valori direttamente in NEW e restituire la NEW modificata, o costruire un record/riga completamente nuovo da restituire. Nel caso di un trigger before su DELETE, il valore restituito non ha un effetto diretto, ma deve essere non null per permettere all'azione trigger di procedere. Notare che NEW è null nei trigger DELETE, quindi restituirlo di solito non è sensato. Un'espressione utile nei trigger DELETE potrebbe restituire OLD.
Il valore di ritorno di un trigger a livello di riga attivato AFTER o un trigger a livello di instruzione attivato BEFORE o AFTER è sempre ignorato; potrebbe anch'esso essere null. Comunque, uno qualsiasi di questi tipi di trigger potrebbe ancora annullare l'intera operazione sollevando un errore.
Esempio 39.3, «Una procedura trigger PL/pgSQL» mostra un esempio di una procedura trigger in PL/pgSQL.
Esempio 39.3. Una procedura trigger PL/pgSQL
Questo trigger di esempio assicura che ogni volta una riga venga inserita o aggiornata nella tabella, il nome utente corrente e l'orario siano salvati nella riga. E controlla che oil nome di un impiegato sua fornito e che il salario sia un valore positivo.
CREATE TABLE emp (
    empname text,
    salary integer,
    last_date timestamp,
    last_user text
);

CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
    BEgin
        -- Check that empname and salary are given
        IF NEW.empname IS NULL THEN
            RAISE EXCEPTION 'empname cannot be null';
        END IF;
        IF NEW.salary IS NULL THEN
            RAISE EXCEPTION '% cannot have null salary', NEW.empname;
        END IF;

        -- Who works for us when she must pay for it?
        IF NEW.salary < 0 THEN
            RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
        END IF;

        -- Remember who changed the payroll when
        NEW.last_date := current_timestamp;
        NEW.last_user := current_user;
        RETURN NEW;
    END;
$emp_stamp$ LANGUAGE plpgsql;

CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_stamp();

Un altro modo di annotare i cambiamenti a una tabella implica la creazione di una nuova tabella che salva una riga per ogni insert, update, o delete che accade. Questo approccio può essere pensato come una revisione dei cambiamenti a una tabella. Esempio 39.4, «Una procedura trigger PL/pgSQL per la revisione» mostra un esempio di una procedura trigger di revisione in PL/pgSQL.
Esempio 39.4. Una procedura trigger PL/pgSQL per la revisione
Questo trigger di esempio assicura che qualsiasi inserimento, aggiornamento o cancellazione di una riga nella tabella emp sia registrata nella tabella emp_audit. L'orario e il nome utente corrente sono salvati nella riga, insieme al tipo di operazione svolta.
CREATE TABLE emp (
    empname           text NOT NULL,
    salary            integer
);

CREATE TABLE emp_audit(
    operation         char(1)   NOT NULL,
    stamp             timestamp NOT NULL,
    userid            text      NOT NULL,
    empname           text      NOT NULL,
    salary integer
);

CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$
    BEGIN
        --
        -- Crea una riga un emp_audit per riflettere l'operazione eseguita su emp, 
        -- usa la variabile speciale TG_OP per portare a termine l'operazione.
        --
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*;
            RETURN OLD;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*;
            RETURN NEW;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*;
            RETURN NEW;
        END IF;
        RETURN NULL; -- il risultato viene ignorato dato che questo è un trigger AFTER
    END;
$emp_audit$ LANGUAGE plpgsql;

CREATE TRIGGER emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
    FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();

Un uso dei trigger è di mantenere una tabella di sommario di un'altra tabella. Il sommario risultante può essere usato al posto della tabella originale per certe query - spesso con tempi di esecuzione enormemente ridotti. Questa tecnica è usata comunemente nel Data Warehousing, dove le tabelle dei dati misurati o osservati (chiamate tabelle dei fatti) potrebbero essere estremamente grandi. Esempio 39.5, «Una procedura trigger PL/pgSQL per mantenere una tabella di sommario» mostra un esempio di una procedura trigger in PL/pgSQL che mantiene una tabella di sommario per una tabella di fatti in un data warehouse.
Esempio 39.5. Una procedura trigger PL/pgSQL per mantenere una tabella di sommario
Lo schema presentato in dettaglio qui è basato parzialmente sull'esempio Grocery Store preso da The Data Warehouse Toolkit di Ralph Kimball.
--
-- Main tables - time dimension and sales fact.
-- Tabelle principali - time dimension e sales fact.
--
CREATE TABLE time_dimension (
    time_key                    integer NOT NULL,
    day_of_week                 integer NOT NULL,
    day_of_month                integer NOT NULL,
    month                       integer NOT NULL,
    quarter                     integer NOT NULL,
    year                        integer NOT NULL
);
CREATE UNIQUE INDEX time_dimension_key ON time_dimension(time_key);

CREATE TABLE sales_fact (
    time_key                    integer NOT NULL,
    product_key                 integer NOT NULL,
    store_key                   integer NOT NULL,
    amount_sold                 numeric(12,2) NOT NULL,
    units_sold                  integer NOT NULL,
    amount_cost                 numeric(12,2) NOT NULL
);
CREATE INDEX sales_fact_time ON sales_fact(time_key);

--
-- Tabella di sommario - sales by time.
--
CREATE TABLE sales_summary_bytime (
    time_key                    integer NOT NULL,
    amount_sold                 numeric(15,2) NOT NULL,
    units_sold                  numeric(12) NOT NULL,
    amount_cost                 numeric(15,2) NOT NULL
);
CREATE UNIQUE INDEX sales_summary_bytime_key ON sales_summary_bytime(time_key);

--
-- Funzioni e trigger per rettificare le colonne sommarizate sulle UPDATE, INSERT, DELETE.
--
CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER
AS $maint_sales_summary_bytime$
    DECLARE
        delta_time_key          integer;
        delta_amount_sold       numeric(15,2);
        delta_units_sold        numeric(12);
        delta_amount_cost       numeric(15,2);
    BEgin

        -- Mette a posto l'ammontare degli incrementi/decrementi.
        IF (TG_OP = 'DELETE') THEN

            delta_time_key = OLD.time_key;
            delta_amount_sold = -1 * OLD.amount_sold;
            delta_units_sold = -1 * OLD.units_sold;
            delta_amount_cost = -1 * OLD.amount_cost;

        ELSIF (TG_OP = 'UPDATE') THEN

            -- forbid updates that change the time_key -
            -- (probably not too onerous, as DELETE + INSERT is how most
            -- changes will be made).
            IF ( OLD.time_key != NEW.time_key) THEN
                RAISE EXCEPTION 'Update of time_key : % -> % not allowed',
                                                      OLD.time_key, NEW.time_key;
            END IF;

            delta_time_key = OLD.time_key;
            delta_amount_sold = NEW.amount_sold - OLD.amount_sold;
            delta_units_sold = NEW.units_sold - OLD.units_sold;
            delta_amount_cost = NEW.amount_cost - OLD.amount_cost;

        ELSIF (TG_OP = 'INSERT') THEN

            delta_time_key = NEW.time_key;
            delta_amount_sold = NEW.amount_sold;
            delta_units_sold = NEW.units_sold;
            delta_amount_cost = NEW.amount_cost;

        END IF;


        -- Inserisce o aggiorna la riga di sommario con i nuovi valori.
        <<insert_update>>
        LOOP
            UPDATE sales_summary_bytime
                SET amount_sold = amount_sold + delta_amount_sold,
                    units_sold = units_sold + delta_units_sold,
                    amount_cost = amount_cost + delta_amount_cost
                WHERE time_key = delta_time_key;

            EXIT insert_update WHEN found;

            BEGIN
                INSERT INTO sales_summary_bytime (
                            time_key,
                            amount_sold,
                            units_sold,
                            amount_cost)
                    VALUES (
                            delta_time_key,
                            delta_amount_sold,
                            delta_units_sold,
                            delta_amount_cost
                           );

                EXIT insert_update;

            EXCEPTION
                WHEN UNIQUE_VIOLATION THEN
                    -- non fare niente
            END;
        END LOOP insert_update;

        RETURN NULL;

    END;
$maint_sales_summary_bytime$ LANGUAGE plpgsql;

CREATE TRIGGER maint_sales_summary_bytime
AFTER INSERT OR UPDATE OR DELETE ON sales_fact
    FOR EACH ROW EXECUTE PROCEDURE maint_sales_summary_bytime();

INSERT INTO sales_fact VALUES(1,1,1,10,3,15);
INSERT INTO sales_fact VALUES(1,2,1,20,5,35);
INSERT INTO sales_fact VALUES(2,2,1,40,15,135);
INSERT INTO sales_fact VALUES(2,3,1,10,1,13);
SELECT * FROM sales_summary_bytime;
DELETE FROM sales_fact WHERE product_key = 1;
SELECT * FROM sales_summary_bytime;
UPDATE sales_fact SET units_sold = units_sold * 2;
SELECT * FROM sales_summary_bytime;

martedì 6 settembre 2011

Confronti di soluzioni etl

Integration Vendors Comparison

Detailed Comparison Matrix of Integration Solutions

 Feature
IBM, TIBCO, WebMethods
Sterling Commerce Gentran IS
Microsoft BizTalk
Pervasive Data Integrator
Cast Iron Systems (Appliance)
Boomi
JitterBit Enterprise
 Easy to Use
Yes
No
No
No
OK
Yes
Yes
Yes
 Web-based UI
Yes
No
No
No
No
No
Yes
No
 Multi-role Team Collaboration
Yes
Yes
Yes
No
No
No
No
Yes
 Graphical Process Orchestration
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Graphical Data Mapper
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Process Centric Approach
Yes
Yes
Yes
Yes
No
No
No
No
 Enables SOA
Yes
Yes
Yes
No
No
No
No
Yes
 Reusable Services Repository
Yes
Yes
No
No
No
No
No
Yes
 Single-install,Light Footprint
Yes
No
No
No
Yes
Yes
Yes
Yes
 Large Volume Performance
Yes
Yes
OK
OK
OK
No
No
Yes
 Clustering and Job Distribution
Yes
Yes
Yes
Yes
No
No
Yes
Yes
 Data Partitioning
Yes
Yes
Yes
Yes
Yes
No
No
No
 Automatic Recovery of Flows
Yes
Yes
No
OK
No
No
No
No
 XA-Transaction Rollbacks
Yes
Yes
Yes
OK
No
No
No
No
 Meta-Driven Approach vs.Code
Yes
Yes
No
No
No
No
No
Yes
 Complex Flows (Fork/Join etc.)
Yes
Yes
Yes
Yes
Yes
No
No
Yes
 Sub-Processes
Yes
Yes
Yes
OK
Yes
No
No
Yes
 Built-in Scheduler
Yes
Yes
Yes
No
No
Yes
Yes
Yes
 Real-time Triggers
Yes
Yes
Yes
Yes
Yes
OK
Yes
Yes
 Event Driven Processing
Yes
Yes
Yes
Yes
Yes
No
Yes
Yes
 RDBMS Connections
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Non-RDBMS Connections
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Message Queues (JMS etc.)
Yes
Yes
Yes
OK
Yes
No
No
Yes
 B2B Standards - EDI, ACORD
Yes
Yes
Yes
OK
Yes
No
No
Yes
 SaaS App Connections (SF, NS)
Yes
Yes
No
OK
Yes
Yes
Yes
Yes
 Web Services Client
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Publish Flows as Web Services
Yes
Yes
Yes
Yes
No
No
No
Yes
 Join Multiple Sources
Yes
Yes
Yes
Yes
Yes
No
No
Yes
 Split Data Streams
Yes
Yes
Yes
Yes
Yes
No
No
No
 Complex Transformations
Yes
Yes
Yes
Yes
Yes
No
No
Yes
 Data Validations
Yes
Yes
Yes
Yes
Yes
No
No
Yes
 Preview Source Data In-Design
Yes
Yes
Yes
No
No
No
No
Yes
 Run Mapping Rules In-Design
Yes
Yes
Yes
No
No
No
No
Yes
 Library of New Mapping Functions
Yes
Yes
OK
No
No
No
Yes
Yes
 Complex Lookups in Mappings
Yes
Yes
OK
Yes
Yes
No
No
Yes
 Automatic Documentation
Yes
Yes
No
No
No
No
No
No
 Human Workflow for Error Handling
Yes
Yes
Yes
OK
No
No
No
No
 Workflow Task Manager
Yes
Yes
No
No
No
No
No
No
 Plug-in External Programs
Yes
Yes
No
No
Yes
No
No
Yes
 Alerts and Notifications
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
 Rich Logging and Tracking
Yes
Yes
Yes
Yes
OK
OK
OK
OK
 Version Control
No
Yes
No
No
No
No
No
No
 Deploy in Cloud Option
Yes
No
No
No
Yes
Yes
Yes
Yes
 Commerical or Open Source
C
C
C
C
C
C
C
C
 License Pricing
$
$$$$
$$$
$$
$$
$$$
$
$

Note:
  • OK implies limited functionality or that the functionality is available thru third-parties.
  • The content in this comparison matrix has been collected by reviewing publicly available information. Some of the products may have newer versions with updated features. If you have information to help us correct and update the data in this table, please send us an email at marketing@adeptia.com.
  • License Pricing estimate for first year cost (basic configuration):
    $$$$ $150,000+
    $$$
    $60,000 to $150,000
    $$ $20,000 to $60,000
    $ Less than $20,000