Riassunto e traduzione della reference ufficiale del W3C del linguaggio per il tagging semantico di documenti WSDL (linguaggio per la descrizione di servizi)
1. SAWSDL // Restricted!
Liberamente estratto e sintetizzato da
Semantic Annotations for WSDL and XML Schema - Usage Guide (http://www.w3.org/TR/sawsdl-guide/)
Per la presentazione di SAWSDL ci si avvarrà di due esempi:
Listato 1.2-1
<wsdl:description
targetNamespace=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestService/quot;
xmlns=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestService/quot;
xmlns:wsdl=quot;http://www.w3.org/ns/wsdlquot;
xmlns:xsd=quot;http://www.w3.org/2001/XMLSchemaquot;>
<wsdl:types>
<xsd:schema
targetNamespace=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestServicequot;>
<xsd:element name=quot;CheckAvailabilityRequestServiceRequestquot;>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=quot;itemCodequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;datequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;qtyquot; type=quot;xsd:floatquot;/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name=quot;CheckAvailabilityRequestServiceResponsequot;
type=quot;itemConfirmationquot;/>
<xsd:simpleType name=quot;itemConfirmationquot;>
<xsd:restriction base=quot;xsd:booleanquot;/>
</xsd:simpleType>
</xsd:schema>
</wsdl:types>
<wsdl:interface name=quot;CheckAvailabilityRequestServicequot;>
<wsdl:operation name=quot;CheckAvailabilityRequestOperationquot;
pattern=quot;http://www.w3.org/ns/wsdl/in-outquot;>
<wsdl:input element=quot;CheckAvailabilityRequestServiceRequestquot;/>
<wsdl:output element=quot;CheckAvailabilityRequestServiceResponsequot;/>
</wsdl:operation>
</wsdl:interface>
</wsdl:description>
Listato 1.2-2
<wsdl:description
targetNamespace=quot;http://org2.example.com/wsdl/CheckInventoryService/quot;
xmlns=quot;http://org2.example.com/wsdl/CheckInventoryService/quot;
xmlns:wsdl=quot;http://www.w3.org/ns/wsdlquot;
xmlns:xsd=quot;http://www.w3.org/2001/XMLSchemaquot;>
<wsdl:types>
<xsd:schema
targetNamespace=quot;http://org2.example.com/wsdl/CheckInventoryServicequot;>
<xsd:element name=quot;CheckInventoryServiceRequestquot;>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=quot;SKUquot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;deliveryDatequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;numBundlesquot; type=quot;xsd:floatquot;/>
</xsd:sequence>
2. </xsd:complexType>
</xsd:element>
<xsd:element name=quot;CheckInventoryServiceResponsequot;>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=quot;confquot; type=quot;xsd:booleanquot;/>
<xsd:element name=quot;numBundles_availablequot; type=quot;xsd:stringquot;/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:interface name=quot;CheckInventoryServicequot;>
<wsdl:operation name=quot;checkInventoryServicequot;
pattern=quot;http://www.w3.org/ns/wsdl/in-outquot;>
<wsdl:input element=quot;CheckInventoryServiceRequestquot;/>
<wsdl:output element=quot;CheckInventoryServiceResponsequot;/>
</wsdl:operation>
</wsdl:interface>
</wsdl:description>
Definire le annotazioni per la pubblicazione di un Web Service
Un web service può essere corredato di annotazioni semantiche al fine di fornirne una
categorizzazione. Il meccanismo di estensione SAWSDL chiamato modelReference può essere usato
per aggiungere queste informazioni sulla categorizzazione al servizio.
Aggiungere le informazioni di categorizzazione come URI di categoria
Se esiste già un modello semantico di categorizzazione (per esempio una tassonomia) un elemento
modelReference potrebbe essere associato ad un'interfaccia o ad un'operazione di un servizio in
modo tale da puntare a una particolare categoria nella tassonomia.
Aggiunge le informazioni di categorizzazione come Identificatori di categoria
Alcune tassonomie non forniscono direttamente URI per le rispettive categorie e potrebbero
richiedere più porzioni di informazione per identificare le categorie.In tal caso, gli utenti possono
definire tali informazioni secondo le esigenze e associare un modelReference a tali informazioni
tassonomiche definite dall'utente.
Definire le annotazioni per usarle nel matching e nella composizione di
servizi
Una delle più grandi motivazioni per cui SAWSDL è stato introdotto è la necessità di provvedere un
meccanismo per inserire annotazioni semantiche nella descrizione WSDL per facilità la
composizione e la scoperta di web service.
Matching delle interfacce dei Web Service usando un'ontologia condivisa
Consideriamo i listati dei due esempi. Il primo rappresenta una richiesta di un servizio mentre il
secondo mostra il servizio effettivamente fornito. Un matching ad alto livello tra richiesta e servizio
fornirebbe un risultato positivo. Un matching engine tradizionale non ha gli strumenti per capire che
SKU e itemCode si riferiscono entrambe ad un codice univoco di un oggetto o che qty e
numBundles riguardano sempre un concetto di quantità. In questo senso delle annotazioni
semantiche associate alla descrizione WSDL permetterebbero un match tra la richiesta ed il
servizio. Nel seguente esempio le annotazioni semantiche sono aggiunte usando l'attributo di
estensibilità del modelReference di SAWSDL.
<wsdl:description
targetNamespace=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestService/quot;
xmlns=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestService/quot;
xmlns:wsdl=quot;http://www.w3.org/ns/wsdlquot;
xmlns:xsd=quot;http://www.w3.org/2001/XMLSchemaquot;
3. xmlns:sawsdl=quot;http://www.w3.org/ns/sawsdlquot;>
<wsdl:types>
<xsd:schema
targetNamespace=quot;http://org1.example.com/wsdl/CheckAvailabilityRequestServicequot;>
<xsd:element name=quot;CheckAvailabilityRequestServiceRequestquot;>
<xsd:complexType>
<xsd:sequence>
<xsd:element name=quot;itemCodequot; type=quot;xsd:stringquot;
sawsdl:modelReference=quot;http://org1.example.com/ontologies/SampleOnto
logy#PartNumberquot;/>
<xsd:element name=quot;datequot; type=quot;xsd:stringquot;
sawsdl:modelReference=quot;http://org1.example.com/ontologies/SampleOnto
logy#DueDatequot;/>
<xsd:element name=quot;qtyquot; type=quot;xsd:floatquot;
sawsdl:modelReference=quot;http://org1.example.com/ontologies/SampleOnto
logy#Quantityquot;/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name=quot;CheckAvailabilityRequestServiceResponsequot;
type=quot;itemConfirmationquot;/>
<xsd:simpleType name=quot;itemConfirmationquot;
sawsdl:modelReference=quot;http://org1.example.com/ontologies/SampleOntology#A
vailabilityConfirmationquot;>
<xsd:restriction base=quot;xsd:booleanquot;/>
</xsd:simpleType>
</xsd:schema>
</wsdl:types>
<wsdl:interface name=quot;CheckAvailabilityRequestServicequot;>
<wsdl:operation name=quot;checkAvailabilityRequestOperationquot;
pattern=quot;http://www.w3.org/ns/wsdl/in-outquot;>
<wsdl:input element=quot;CheckAvailabilityRequestServiceRequestquot;/>
<wsdl:output element=quot;CheckAvailabilityRequestServiceResponsequot;/>
</wsdl:operation>
</wsdl:interface>
</wsdl:description>
Similmente può essere fatto per il secondo esempio. In entrambi gli esempi, i documenti WSDL
sono stati annotati con concetti presi da una stessa ontologia. Un motore semantico può usare le
relazioni tra i concetti durante il matching delle interfacce ragionando su un modello semantico.
Matching delle interfacce dei Web Service con Mediazione tra ontologia
L'ipotesi fatta precedentemente per cui tutti i concetti usati nelle annotazioni debbano provenire da
una sola ontologia condivisa può non essere sempre vera. E' possibile che si usino due ontologie
diverse dello stesso dominio in due documenti diversi: ad esempio usiamo concetti da una ontologia
per il primo esempio e concetti da un'altra ontologia nel secondo. Se abbiamo una mapping
ontology possiamo usare le relazioni definite in tale ontologia per eseguire il matching.
4. Composizione di Web Service usando il ragionamento sulle Ontologie (Ontology Reasoning)
Supponiamo di avere un servizio checkInventoryService() che prende un UPC ( e non uno SKU):
ovviamente questo servizio non avrò nessun match con la richiesta checkAvailabilityRequest() in
quanto non ci sono relazioni nella mapping ontology tra partNumber e UPC. Supponiamo inoltre di
avere un servizio SKU2UPCLookup() che prende uno SKU e ritorna un UPC. Supponiamo inoltre
che ci siano tre ontologie differenti: una per la richiesta, una per l'advertise e una per il mapping tra
le prime due. La relazione tra SKU e UPC nell'ontologia è mostrata dalla seguente figura.
Un engine semantico estrae l'elemento PartNumeber dal servizio checkAvailabilityRequest() e
l'elemento SKU dal servizio SKU2UPCLookup() e dal punto di vista lessicale si trova che questi
due concetti non ci sono somiglianze. L'engine semantico a questo punto può consultare un
Mapping Ontology per vedere se ci sono relazioni tra PartNumber e SKU: il reasoner riornerà
l'esistenza di una relazione “subClassOf” tra SKU e PartNumber. Questa informazione sarà usata
per comporre SKU2UPCLoolup() con CheckInventoryService().
Matching usando annotazioni multiple
SAWSDL permette annotazioni multiple associate ad uno stesso elemento: queste annotazioni
possono puntare a concetti differenti della stessa ontologia o di ontologie diverse. SAWSDL non
specifica nessun tipo di relazione tra le annotazioni multiple: spetta a chi consulta queste
annotazioni decidere se c'è qualche relazione tra questi concetti consultando l'ontologia ( o le
ontologie di riferimento).
...
<xsd:simpleType name=quot;itemCodequot;
sawsdl:modelReference=quot;http://org3.example.com/ontologies/SampleOntologyOrg3#PartNumber
http://org3.example.com/ontologies/SampleOntologyOrg3#SKUquot;/>
<xsd:restriction base=quot;xsd:stringquot;/>
</xsd:simpleType>
...
Matching usando annotazioni su tipi complessi (Complex Type)
SAWSDL permette l'aggiunta di annotazioni sia al livello di tipo complesso (top level) oppure al
livello degli elementi membro (lower level) oppure ad entrambi i livelli. Nei casi in cui sia il tipo
complesso che i membri del tipo siano forniti di annotazioni, SAWSDL non specifica nessuna
relazione tra i modelReference dei due livelli.
Il motore semantico generalmente usa le annotazioni a livello di tipo complesso per trovare le
relazioni tra i due tipi e poi inizia ad analizzare le possibili relazioni tra gli elementi membro del
tipo complesso in base alle annotazioni espresse a tale livello.
Condizioni di Rappresentazione
L'attributo modelReference può essere usato per rappresentare vincoli comportamentali collegati al
servizio.
5. Definire mappature di schema (Schema Mappings) per abilitare
l'invocazione di Web Service
Supponiamo di avere due dati separati: nome e cognome. Supponiamo ora che un servizio abbia
come ingresso il nome completo: per usare tale servizio è necessario il concatenamento di nome e
cognome. Per facilitare questo tipo di trasformazioni SAWSDL mette a disposizione il meccanismo
delle mappature di schema (Schema Mapping). Uno Schema Mapping permette di specificare una
funzione di trasformazione su elementi WSDL per mappare istanze di dati definiti tramite XML
Schema su dei dati di concetti ontologici definiti in un modello semantico. Questo meccanismo ci
permette anche di definire delle funzioni di trasformazione che mappano i dati concettuali delle
ontologie su istanze di dati definiti tramite XML Schema. Nel primo caso ci si riferisce alle funzioni
di trasformazione usante l'attributo di estensibilità liftingSchemaMapping mentre nel secondo caso
ci si riferisce all'attributo loweringSchemaMapping.
Lifting Schema Mapping
Un liftingSchemaMapping prende come input un dato XML (che aderisce ad un determinato XML
Schema) e produce dati semantici. Supponiamo di avere dei tipi complessi OrderRequest, item e
OrderResponse e che vogliamo specificare un lifting schema mapping su OrderRequest in modo
che un'istanza XML di OrderRequest possa essere mappata su un dato semantico su un grafo RDF.
<wsdl:description>
...
<wsdl:types>
<xsd:schema
targetNamespace=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/wsdl/PurchaseOrderSe
rvice#quot; elementFormDefault=quot;qualifiedquot;>
<xsd:element name=quot;OrderRequestquot;>
<xsd:complexType
sawsdl:liftingSchemaMapping=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/mapping/Orde
rRequest2Ont.xsltquot;>
<xsd:sequence>
<xsd:element name=quot;firstNamequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;lastNamequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;itemquot; type=quot;itemquot; minOccurs=quot;1quot; maxOccurs=quot;unboundedquot; />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name=quot;itemquot;>
<xsd:all>
<xsd:element name=quot;itemCodequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;quantityquot; type=quot;xsd:floatquot;/>
<xsd:element name=quot;dueDatequot; type=quot;xsd:stringquot;/>
<xsd:element name=quot;billingInfoquot; type=quot;xsd:POBillingquot;/>
</xsd:all>
</xsd:complexType>
<xsd:element name=quot;OrderResponsequot; type=quot;Confirmationquot;/>
<xsd:simpleType name=quot;Confirmationquot;>
<xsd:restriction base=quot;xsd:stringquot;>
<xsd:enumeration value=quot;Confirmedquot;/>
<xsd:enumeration value=quot;Pendingquot;/>
<xsd:enumeration value=quot;Rejectedquot;/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</wsdl:types>
<wsdl:interface name=quot;Orderquot;>
<wsdl:operation name=quot;orderquot; pattern=quot;http://www.w3.org/ns/wsdl/in-outquot;>
<wsdl:input element=quot;OrderRequestquot;/>
<wsdl:output element=quot;OrderResponsequot;/>
</wsdl:operation>
6. </wsdl:interface>
</wsdl:description>
...
Vediamo ora l'XLST che mappa gli elementi del tipo complesso OrderRequest su i dati
corrispondeti dell'ontologia.
@prefix xs: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix : <http://org1.example.com/ontologies/PurchaseOrder#> .
<http://org1.example.com/ontologies/PurchaseOrder#> rdf:type owl:Ontology .
:OrderRequest rdf:type owl:Class .
:hasLineItems rdf:type owl:ObjectProperty ;
rdfs:domain :OrderRequest ;
rdfs:range :LineItem .
:LineItem rdf:type owl:Class .
:hasPart rdf:type owl:ObjectProperty , owl:FunctionalProperty ;
rdfs:domain :LineItem ;
rdfs:range :Part .
:Part rdf:type owl:Class .
:hasPartCode rdf:type owl:ObjectProperty ;
rdfs:domain :Part ;
rdfs:range :PartNum .
:PartNum rdf:type owl:Class .
:hasLexicalRespresentation rdf:type owl:DatatypeProperty ,
owl:FunctionalProperty ;
rdfs:domain
[ rdf:type owl:Class ;
owl:unionOf (:Name :PartNum :Date)
];
rdfs:range xs:string .
:hasDueDate rdf:type owl:ObjectProperty ;
rdfs:domain :LineItem ;
rdfs:range :Date .
:Date rdf:type owl:Class .
:hasQuantity rdf:type owl:DatatypeProperty ;
rdfs:domain :LineItem ;
rdfs:range xs:float .
:hasBillingInfo rdf:type owl:DatatypeProperty ;
rdfs:domain :LineItem ;
rdfs:range xs:billingInfo .
:hasCustomer rdf:type owl:ObjectProperty , owl:FunctionalProperty ;
rdfs:domain :OrderRequest ;
rdfs:range :Customer .
:Customer rdf:type owl:Class .
:hasCustomerName rdf:type owl:ObjectProperty ;
rdfs:domain :Customer ;
rdfs:range :Name .
:Name rdf:type owl:Class .
Vediamo ora un file XML di esempio che contiene dei dati strutturati in base allo schema.
<OrderRequest
xmlns=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/wsdl/PurchaseOrderServic
e#quot;>
<firstName>John</firstName>
8. <po:hasDueDate>
<po:Date>
<po:hasLexicalRepresentation>
<xsl:value-of select=quot;order:item/order:dueDatequot;/>
</po:hasLexicalRepresentation>
</po:Date>
</po:hasDueDate>
<po:hasQuantity rdf:datatype=quot;&xs;floatquot;>
<xsl:value-of select=quot;order:item/order:quantityquot;/>
</po:hasQuantity>
<po:hasBillingInfo rdf:datatype=quot;&xs;POBillingquot;>
<xsl:value-of select=quot;order:item/order:billingInfoquot;/>
</po:hasBillingInfo>
</po:LineItem>
<xsl:apply-templates select=quot;order:OrderRequestquot; />
</po:hasLineItems>
</po:OrderRequest>
</rdf:RDF>
</xsl:template>
</xsl:transform>
Lowering Schema Mapping
Iniziamo con l'aggiungere ad una annotazione con un liftingSchemaMapping un loweringSchemaMapping.
<xsd:element name=quot;OrderRequestquot;>
<xsd:complexType
sawsdl:liftingSchemaMapping=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/mapp
ing/OrderRequest2Ont.xslt
sawsdl:loweringSchemaMapping=quot;http://www.w3.org/2002/ws/sawsdl/spec/ex
amples/mapping/Ont2OrderRequest.loweringquot;>
<xsd:sequence>
<xsd:element name=quot;firstNamequot; type=quot;xsd:integerquot;>John</xsd:element>
<xsd:element name=quot;lastNamequot; type=quot;xsd:integerquot;>Smith</xsd:element>
<xsd:element name=quot;itemquot; type=quot;itemquot; minOccurs=quot;1quot;
maxOccurs=quot;unboundedquot; />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Un loweringSchemaMapping dovrebbe prendere dei dati semantici ma non è molto chiaro in che
forma questi devono essere presentati: per risolvere questo problema usiamo delle query nel
linguaggio SPARQL per prelevare dei dati semantici dall'ontologia e ottenerne una rappresentazione
XML che poi può essere usata per formulare una trasformazione XSLT.
<lowering>
<sparqlQuery>
PREFIX po: <http://org1.example.com/ontologies/PurchaseOrder#>
SELECT ?name ?partNum ?quantity ?dueDate ?billingInfo
WHERE {
?order po:hasCustomer ?customer .
?customer po:hasCustomerName ?custName .
?custName po:hasLexicalRespresentation ?name .
?order po:hasLineItems ?item .
?item po:hasQuantity ?quantity .
?item po:hasBillingInfo ?billingInfo .
?item po:hasDueDate ?Date .
?date po:hasLexicalRepresentation ?dueDate .
?item po:hasPart ?part .
?part po:hasPartCode ?code .
?code po:hasLexicalRespresentation ?partNum }
</sparqlQuery>
9. Si genera quindi una risposta alla query in formato XML.
<sparql xmlns=quot;http://www.w3.org/2005/sparql-results#quot;>
<head>
<variable name=quot;quantityquot; />
<variable name=quot;partNumquot; />
<variable name=quot;namequot; />
<variable name=quot;dueDatequot; />
<variable name=quot;billingInfoquot; />
</head>
<results>
<result>
<binding name=quot;quantityquot;>
<literal>12.0</literal>
</binding>
<binding name=quot;partNumquot;>
<literal>052053811</literal>
</binding>
<binding name=quot;namequot;>
<literal>John Smith</literal>
</binding>
<binding name=quot;billingInfoquot;>
<literal>88 Park Road, Lower Dangan, Galway, Ireland</literal>
</binding>
<binding name=quot;dueDatequot;>
<literal>20061114</literal>
</binding>
</result>
</results>
</sparql>
A questo punto possiamo definire una trasformazione XSLT che ci ritornerà di nuovo il tipo
complesso originale.
<xsl:transform version=quot;2.0quot;
xmlns:po=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/wsdl/PurchaseOrderS
ervice#quot;
xmlns:xsd=quot;http://www.w3.org/2001/XMLSchemaquot;
xmlns:xsl=quot;http://www.w3.org/1999/XSL/Transformquot;
xmlns:sp=quot;http://www.w3.org/2005/sparql-results#quot;>
<xsl:output method=quot;xmlquot; version=quot;1.0quot; encoding=quot;iso-8859-1quot; indent=quot;yesquot; />
<xsl:template match=quot;/sp:sparqlquot;>
<po:OrderRequest>
<xsl:variable name=quot;fullNamequot;>
<xsl:value-of
select=quot;sp:results/sp:result[position()=1]/sp:binding[@name='name']/sp:literalquot;/
>
</xsl:variable>
<po:firstName>
<xsl:value-of select=quot;substring-before($fullName,' ')quot; />
</po:firstName>
<po:lastName>
10. <xsl:value-of select=quot;substring-after($fullName,' ')quot; />
</po:lastName>
<xsl:apply-templates select=quot;sp:results/sp:resultquot; />
</po:OrderRequest>
</xsl:template>
<xsl:template match=quot;sp:resultquot;>
<po:quot;itemquot;>
<po:itemCode>
<xsl:value-of select=quot;sp:binding[@name='partNum']/sp:literalquot; />
</po:itemCode>
<po:quantity>
<xsl:value-of select=quot;sp:binding[@name='quantity']/sp:literalquot; />
</po:quantity>
<po:dueDate>
<xsl:value-of select=quot;sp:binding[@name='dueDate']/sp:literalquot; />
</po:dueDate>
<po:billingInfo>
<xsl:value-of select=quot;sp:binding[@name='billingInfo']/sp:literalquot; />
</po:billingInfo>
</po:item>
</xsl:template>
</xsl:transform>
</lowering>
Il risultato della trasformazione è il seguente.
<po:OrderRequest
xmlns:po=quot;http://www.w3.org/2002/ws/sawsdl/spec/examples/wsdl/PurchaseOrderSer
vice#quot;
xmlns:sp=quot;http://www.w3.org/2005/sparql-results#quot;
xmlns:xsd=quot;http://www.w3.org/2001/XMLSchemaquot;>
<po:firstName>John</po:firstName>
<po:lastName>Smith</po:lastName>
<po:item>
<po:itemCode>052053811</po:itemCode>
<po:quantity>12.0</po:quantity>
<po:dueDate>20061114</po:dueDate>
<po:billingInfo>88 Park Road, Lower Dangan, Galway,
Ireland</po:billingInfo>
</po:item>
</po:OrderRequest>
Come nel caso delle annotazioni multiple, ad uno stesso elemento possiamo associare più di uno
schema mapping. Quando vengono specificati URI multipli in liftingSchemaMapping e
loweringSchemaMapping, SAWSDL specifica che questi schema mapping devono essere
considerati come delle alternative la cui scelta è lasciata alla discrezione del client.