In questo documento si descrive la piattaforma dei Web Service esposti da Titulus XML. Vengono descritte le modalità per la connessione all’applicativo, nonché la ricerca, modifica e registrazione di documenti.
Java DOC dei Web Service.
A questa documentazione si accede dalla pagina di presentazione dei servizi.
Titulus espone una pagina di presentazione dei web service, il cui URL è
http://<host>:<port>/titulus_ws/services
dove <host> e <port> sono quelli della macchina che ospita i web service.
In questa pagina viene presentato un elenco dei servizi esposti e, per ognuno di essi, oltre all'elenco dei metodi che possono essere invocati, vengono forniti dei link per accedere al WSDL, al javadoc e alla corrispondente pagina del manuale.
A titolo di esempio, di seguito viene riportata una porzione di questa pagina.
I servizi di base sono Titulus, per l'accesso all'archivio dei documenti, e Acl (Access Control List), per l'accesso all'archivio degli utenti e dei loro diritti.
I rispettivi URL hanno la seguente struttura (<host> e <port> sono quelli della macchina che ospita i web service):
http://<host>:<port>/titulus_ws/services/Titulus http://<host>:<port>/titulus_ws/services/Acl
Il WSDL dei servizi può essere recuperato ai seguenti URL (essi vengono riportati anche nella pagina di presentazione dei servizi):
http://<host>:<port>/titulus_ws/services/Titulus?wsdl http://<host>:<port>/titulus_ws/services/Acl?wsdl
Oltre ai servizi di base, Titulus espone i seguenti servizi che espongono delle funzionalità specifiche:
I web service di Titulus sono indipendenti dall'autenticazione usata. E' quindi possibile impiegare la Basic Authentication di Tomcat, Shibboleth o altro.
Il Web Service espone una serie di porte d’accesso per la registrazione di nuovi documenti e la consultazione della base dati.
Di seguito riportiamo l’elenco dei metodi principali con una breve descrizione:
Per una descrizione dettagliata dei metodi e dei relativi parametri, si rimanda al Java Doc di riferimento. Segue una descrizione sommaria delle principali funzionalità messe a disposizione dal servizio.
Invocando il metodo init() si stabilisce una connessione con Titulus e si attiva una nuova sessione di lavoro utilizzata per tutte le richieste provenienti dallo stesso client (a carico del client rimane la notifica al server dell’intenzione di avvalersi delle sessioni, impostando lo scope di chiamata a “session”).
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Gli stub client usati (nel codice ”titulus” e ”acl”), sono stati generati a partire dal wsdl dei servizi, mediante il tool WSDL2Java.
Nell'esempio vengono effettuate le connessioni all'archivio centrale e ad ACL con l'utente “test-ws” (che deve essere registrato in ACL con login “test-ws”).
TitulusServiceLocator tsl = new TitulusServiceLocator(); AclServiceLocator asl = new AclServiceLocator(); // impostazione dello scope di chiamata a "session" tsl.setMaintainSession(true); asl.setMaintainSession(true); Titulus_PortType titulus = tsl.getTitulus(); Acl_PortType acl = asl.getAcl(); // impostazione della login per l'accesso autenticato al servizio ((TitulusSoapBindingStub)titulus).setUsername("prova"); ((TitulusSoapBindingStub)titulus).setPassword("XXX"); ((AclSoapBindingStub)acl).setUsername("prova"); ((AclSoapBindingStub)acl).setPassword("XXX"); ... titulus.init(null, null, "test-ws", null, "xdocwaydoc", -1, -1); ... acl.init(null, null, "test-ws", null); ...
In caso di fallimento viene sollevata una “Exception” con una descrizione testuale della causa dell’errore (da intercettare lato client).
Una volta attivata la connessione, per consultare il database è sufficiente invocare il metodo executeQuery(). Tramite questo metodo è possibile ricercare un insieme di dati che rispondono a determinati criteri di ricerca. Il primo parametro rappresenta la query espressa secondo la sintassi di eXtraWay:
([NON] [<canale di ricerca>]=<termini>) [<operatore> ([<canale di ricerca>]=termini) …]
Dove:
Esempi:
I principali canali di ricerca attivi per i documenti sono i seguenti:
I canali di ricerca attivi per le sedute di Organi sono:
Per una descrizione più dettagliata delle opzioni di ricerca si rimanda al documento: Sintassi di ricerca linguaggio nativo eXtraWay.
E’ inoltre previsto il passaggio di ulteriori parametri per:
Di seguito la specifica XML per impostare le opzioni di ricerca attraverso il metodo setSearchOprion():
<?xml version="1.0"?>
<SearchOption>
<TermPresence>
<AnyPosition active="true" />
<WordDistance active="false" value="2" order="true" />
<AtLeastOneTerm active="false" />
<IgnoreStopList active="false" />
</TermPresence>
<ServerExtension>
<GenderAndNumber active="false" />
<Ranking active="false" />
<Probabilistic active="false" />
<SimilarDocument active="false" key="null" />
<SimilarTerm active="false" error="1" character="3" prefix="1" />
</ServerExtension>
<ThesaurusExtension />
<ApplicationLevel>
<SearchComposition active="true" operator="and" />
<SimilarTermProposal active="false" key="null" void_result="true" />
</ApplicationLevel>
</SearchOption>
Esempio: ... <SimilarTerm active="true" error="1" character="3" prefix="1"/> ...
Il primo carattere del termine cercato deve risultare lo stesso (prefix=1) e si ammette un carattere errato ogni tre (error=1 e character=3), quindi su parole di quattro, cinque e sei caratteri si ammettono due errori, su parole di sette, otto e nove se ne ammettono tre ecc.
L’esito positivo di una ricerca produce una “busta XML” (envelope) contenente un estratto (titoli) dei primi N documenti rispondenti ai requisiti di ricerca. In alternativa, utilizzando il metodo getCurrentSet() è possibile ottenere una vista gerarchica (sempre in formato XML) della storia delle ricerche effettuate. Su tale vista gerarchica è possibile intervenire in raffinamento o rimozione di rami corrispondenti a ricerche non più ritenute interessanti.
Per navigare sui titoli di tutti i documenti trovati si fa uso dei metodi firstTitlePage(), nextTitlePage(), prevTitlePage(), lastTitlePage(): ognuno di essi restituisce un envelope XML contenente un estratto (risultati di sintesi) di un insieme di N documenti, ove la dimensione N di una pagina di titoli è un parametro configurabile.
Per navigare sui singoli documenti trovati si fa uso dei metodi loadFirstDocument(), loadNextDocument(), loadPrevDocument(), loadLastDocumento(): ognuno di essi restituisce un envelope XML contenente i metadati di registrazione di un documento.
È prevista anche una modalità di caricamento diretto di un documento, sulla base di un identificativo fisico univoco (idUnit): loadDocument(idUnit); il numero fisico di ogni documento è tra le informazioni presenti nei risultati di sintesi (titoli).
Ad ogni file (allegato multimediale) associato al metadato XML di un documento viene attribuito un id univoco di archivio. Il percorso XPath per recuperare tale identificativo nell'ambito del metadato XML è:
/doc/files/xw:file/@name (per i file) /doc/immagini/xw:file/@name (per le immagini)
All’interno di /doc/files e di /doc/immagini possono essere incapsulati 0 o più riferimenti ad allegati.
Per richiedere il download di uno di questi file si invoca il metodo getAttachment() (per i dettagli si rimanda al javadoc).
Questo metodo supporta due specifiche differenti per l'invio del file al client: la prima è la SwA (SOAP with Attachments), che consiste nell'inviare una risposta SOAP multipart mediante la codifica MIME (riferimento w3c: SOAP Messages with Attachments); la seconda, invece, è la DIME, un formato ideato da Microsoft.
Un parametro del metodo getAttachment() consente di indicare la specifica da rispettare.
DIME dovrebbe essere meglio supportato dal framework .NET, quindi, se si utilizza questo framework per sviluppare i client e se ci sono problemi nell'uso di SwA, si consiglia di provare DIME.
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
In questo caso si richiede la restituzione dell'allegato mediante SwA (con Axis, il codice client non cambia usando l'altra specifica, cioè DIME).
import org.apache.axis.attachments.AttachmentPart; import org.dom4j.Document; import org.dom4j.DocumentHelper; ... ... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // loading document 00019099 this.titulus.executeQuery("[docnrecord]=00019099", null, false, false, false, false, -1); String resp = this.titulus.loadFirstDocument(false, false, false); Document respDoc = DocumentHelper.parseText(resp); // checking attachment List files = respDoc.selectNodes("//doc/files/*[name()='xw:file'][not(@der_from)]"); for (int j = 0; j < files.size(); j++) { Element file = (Element)files.get(j); String fileId = file.attributeValue("name", ""); // downloading file with SwA (second parameter to false) this.titulus.getAttachment(fileId, false); Object[] attachments = ((TitulusSoapBindingStub)this.titulus).getAttachments(); // attachment size: ((AttachmentPart)attachments[0]).getSize() // attachment name: ((AttachmentPart)attachments[0]).getAttachmentFile() // getting file's bytes ByteArrayOutputStream baos = new ByteArrayOutputStream(); ((AttachmentPart)attachments[0]).getDataHandler().writeTo(baos); baos.flush(); baos.close(); byte[] attachment = baos.toByteArray(); ... }
Dal momento che le specifiche SwA e DIME non è detto che siano supportate da tutte le librerie per lo sviluppo di applicazioni client, nella release 3.11.0.8 dei servizi sono stati introdotti altri due metodi per il download dei file: getAttachmentByteArray() e getAttachmentBase64().
Questo metodo restituisce l'allegato richiesto senza fare uso di messaggi SOAP multipart, il che semplifica la gestione della chiamata da parte dei client.
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
import org.dom4j.Document; import org.dom4j.DocumentHelper; ... ... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // loading document 00019099 this.titulus.executeQuery("[docnrecord]=00019099", null, false, false, false, false, -1); String resp = this.titulus.loadFirstDocument(false, false, false); Document respDoc = DocumentHelper.parseText(resp); // checking attachment List files = respDoc.selectNodes("//doc/files/*[name()='xw:file'][not(@der_from)]"); for (int j = 0; j < files.size(); j++) { Element file = (Element)files.get(j); String fileId = file.attributeValue("name", ""); // downloading file byte[] attachment = this.titulus.getAttachmentByteArray(fileId); ... }
Di seguito si riporta la struttura della risposta SOAP inviata al client (l'array di byte viene codificato come xsi:type=“soapenc:base64Binary”):
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:getAttachmentByteArrayResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ws.titulus.kion.it"> <getAttachmentByteArrayReturn xsi:type="soapenc:base64Binary" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">...</getAttachmentByteArrayReturn> </ns1:getAttachmentByteArrayResponse> </soapenv:Body> </soapenv:Envelope>
Anche questo metodo restituisce l'allegato richiesto senza fare uso di messaggi SOAP multipart. A differenza di getAttachmentByteArray(), però, restituisce un xml con la seguente struttura:
<?xml version="1.0" encoding="UTF-8"?> <file id="..." mime="...">BASE64</file>
dove:
In questo caso, quindi, il client ottiene: il mime type dell'allegato; il contenuto binario del file in base64, il che comporta la sua decodifica da parte del client prima di poter essere utilizzato.
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import org.dom4j.Document; import org.dom4j.DocumentHelper; ... ... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // loading document 00019099 this.titulus.executeQuery("[docnrecord]=00019099", null, false, false, false, false, -1); String resp = this.titulus.loadFirstDocument(false, false, false); Document respDoc = DocumentHelper.parseText(resp); // checking attachment List files = respDoc.selectNodes("//doc/files/*[name()='xw:file'][not(@der_from)]"); for (int j = 0; j < files.size(); j++) { Element file = (Element)files.get(j); String fileId = file.attributeValue("name", ""); // downloading file resp = this.titulus.getAttachmentBase64(fileId); respDoc = DocumentHelper.parseText(resp); String mimeType = respDoc.getRootElement().attributeValue("mime"); byte[] attachment = Base64.decode(respDoc.getRootElement().getText()); ... }
Sebbene i metodi getAttachmentByteArray() e getAttachmentBase64() siano più semplici da usare da parte dei client, essi utilizzano una codifica inefficiente dei dati binari, soprattutto se i file richiesti sono di grosse dimensioni. Quando le librerie usate lo consentono, è quindi consigliato l'uso di getAttachment(), perché le codifiche MIME/DIME risultano essere più efficienti e perché le librerie che le gestiscono normalmente si occupano anche dello swap automatico su disco dei file grandi, il che evita problemi di gestione della memoria.
Ecco un'interessante lettura a riguardo: Fear of Attachments.
La registrazione di un nuovo documento è gestita attraverso la chiamata al metodo
saveDocument(), che ha come primo parametro il documento (i suoi metadati) in formato XML.
Il nuovo documento prima di essere salvato subisce un processo di validazione per mezzo di una DTD (Document Type Definition) e successivamente un controllo semantico per verificarne la consistenza in funzione della tipologia indicata.
Per la DTD completa del documento xml si faccia riferimento al javadoc del metodo saveDocument().
Di seguito si riporta un esempio di inserimento in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // *** composizione del nuovo documento (stringa XML) *** ... // inserimento del nuovo documento con invio delle notifiche email ai suoi assegnatari String savedDocumentStr = this.titulus.saveDocument(newDoc, true); log.debug("saved document is:\r\n\n" + savedDocumentStr + "\n"); ...
Di seguito si riporta un esempio di codice XML riferito alla richiesta di registrazione di un documento non protocollato (tipo “varie”):
<?xml version="1.0" encoding="UTF-8"?> <doc tipo="varie"> <repertorio cod="NOT">Atti di notifica</repertorio> <autore>Dante Alighieri</autore> <oggetto>Invio bozza opera La Divina Commedia</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione costo="10" valuta="euro" cod="Raccomandata"></mezzo_trasmissione> <note>Note al documento</note> <riferimenti xml:space="preserve">Volumi Inferno, Purgatorio, Paradiso</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato>0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Letteratura</voce_indice> </doc>
L’elemento “repertorio” non è obbligatorio; tuttavia nel caso di registrazione di un documento appartenente ad un repertorio, deve essere indicato.
Ecco la risposta restituita dal metodo saveDocument():
<?xml version="1.0" encoding="UTF-8"?> <Response xmlns:xw="http://www.3di.it/ns/xw-200303121136" canSee="true" canEdit="true" canAddCC="true" canDelCC="true" canAddCDS="true" canDelCDS="true" canAddRPA="true" canAddPostIt="true" canAddFile="true" canAddImage="true" canInsInFolder="true" canLinkFolder="true" canCancel="true" canDelete="true"> <Document idIUnit="19643"> <doc anno="2011" annullato="no" cod_amm_aoo="KIONCLE" data_prot="20110721" nrecord="00020285" scarto="10" tipo="varie"> <repertorio cod="NOT" numero="NOT^KIONCLE-20110000006">Atti di notifica</repertorio> <autore xml:space="preserve">Dante Alighieri</autore> <oggetto xml:space="preserve">Invio bozza opera La Divina Commedia</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione cod="Raccomandata" costo="10" valuta="euro"/> <classif cod="01/01" xml:space="preserve">01/01 - Letteratura</classif> <note xml:space="preserve">Note al documento</note> <riferimenti xml:space="preserve">Volumi Inferno, Purgatorio, Paradiso</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato xml:space="preserve">0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Letteratura</voce_indice> <rif_interni> <rif diritto="RPA" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta"/> <rif diritto="CC" cod_persona="3" cod_uff="00003" nome_persona="Verdi Luca" nome_uff="Smistamenti"/> </rif_interni> <storia> <creazione cod_oper="PI000121" cod_uff_oper="SI000084" data="20110721" oper="Applicazione Client WS" ora="11:41:46" uff_oper="Ufficio Protocollo KION"/> <responsabilita cod_operatore="PI000121" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta" data="20110721" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> <assegnazione_cc cod_operatore="PI000121" cod_persona="3" cod_uff="00003" data="20110721" nome_persona="Verdi Luca" nome_uff="Smistamenti" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> </storia> <?xw-meta Dbms="ExtraWay" DbmsVer="21.1.3.116" OrgNam="Kion s.p.a." OrgVer="3.2" Classif="1.0" ManGest="1.0" ManTec="0.0.4" DocType="" InsUser="clWS" InsTime="20110721114146" ModUser="clWS" ModTime="20110721114146"?> <?xw-crc key32=d1b0d1e4-94c10140?> </doc> </Document> </Response>
Di seguito si riporta un esempio di codice XML riferito alla richiesta di registrazione di un documento in arrivo (tipo “arrivo”):
<?xml version="1.0" encoding="UTF-8"?> <doc tipo="arrivo"> <prot_differito data_arrivo="20110709" xml:space="preserve"> Data conclusione presentazione domande. Il carico di lavoro ha superato le capacità operative dell'ufficio. </prot_differito> <repertorio cod="V_D_CDA">Verbali Consiglio di Amministrazione</repertorio> <oggetto>Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione costo="23" valuta="euro" cod="Posta Ordinaria"></mezzo_trasmissione> <note>Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato>0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> <rif_esterni> <rif_esterno data_prot="20040101" n_prot="1243"> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <referente cod="PE000928" nominativo="Mario Rossi"/> <indirizzo email="mrossi@ditta.it" fax="051 451242" tel="051 452844" xml:space="preserve"> Via Manzoni 2 - 40033 Casalecchio di Reno - BO - Italia </indirizzo> </rif_esterno> </rif_esterni> </doc>
L’elemento “repertorio” non è obbligatorio, tuttavia nel caso di registrazione di un documento appartenente ad un repertorio, deve essere indicato.
Ecco la risposta restituita dal metodo saveDocument():
<?xml version="1.0" encoding="UTF-8"?> <Response xmlns:xw="http://www.3di.it/ns/xw-200303121136" canSee="true" canEdit="true" canAddCC="true" canDelCC="true" canAddRPA="true" canAddPostIt="true" canAddFile="true" canAddImage="true" canInsInFolder="true" canLinkFolder="true" canCancel="true"> <Document idIUnit="19644"> <doc anno="2011" annullato="no" cod_amm_aoo="KIONCLE" data_prot="20110721" nrecord="00020286" num_prot="2011-KIONCLE-0000128" scarto="01" tipo="arrivo"> <prot_differito data_arrivo="20110709" xml:space="preserve"> Data conclusione presentazione domande. Il carico di lavoro ha superato le capacità operative dell'ufficio. </prot_differito> <repertorio cod="V_D_CDA" numero="V_D_CDA^KIONCLE-20110000047">Verbali Consiglio di Amministrazione</repertorio> <oggetto xml:space="preserve">Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione cod="Posta Ordinaria" costo="23" valuta="euro"/> <classif cod="06/04" xml:space="preserve">06/04 - Documentazione</classif> <note xml:space="preserve">Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato xml:space="preserve">0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> <rif_esterni> <rif data_prot="20040101" n_prot="1243"> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <referente cod="PE000928" nominativo="Mario Rossi"/> <indirizzo email="mrossi@ditta.it" fax="051 451242" tel="051 452844" xml:space="preserve"> Via Manzoni 2 - 40033 Casalecchio di Reno - BO - Italia </indirizzo> </rif> </rif_esterni> <rif_interni> <rif diritto="RPA" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta"/> <rif diritto="CC" cod_persona="3" cod_uff="00003" nome_persona="Verdi Luca" nome_uff="Smistamenti"/> </rif_interni> <storia> <creazione cod_oper="PI000121" cod_uff_oper="SI000084" data="20110721" oper="Applicazione Client WS" ora="11:41:46" uff_oper="Ufficio Protocollo KION"/> <responsabilita cod_operatore="PI000121" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta" data="20110721" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> <assegnazione_cc cod_operatore="PI000121" cod_persona="3" cod_uff="00003" data="20110721" nome_persona="Verdi Luca" nome_uff="Smistamenti" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> </storia> <?xw-meta Dbms="ExtraWay" DbmsVer="21.1.3.116" OrgNam="Kion s.p.a." OrgVer="3.2" Classif="1.0" ManGest="1.0" ManTec="0.0.4" DocType="" InsUser="clWS" InsTime="20110721114146" ModUser="clWS" ModTime="20110721114146"?> <?xw-crc key32=d1b0d1e4-94c10140?> </doc> </Document> </Response>
Di seguito si riporta un esempio di codice XML riferito alla richiesta di registrazione di un documento in partenza (tipo “partenza”):
<?xml version="1.0" encoding="iso-8859-1"?> <doc tipo="partenza"> <repertorio cod="V_D_CDA">Verbali Consiglio di Amministrazione</repertorio> <oggetto>Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione costo="58" valuta="euro" cod="Posta Ordinaria"/> <note>Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato>0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> <rif_esterni> <rif_esterno> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <indirizzo xml:space="preserve"> Via Manzoni, 2 - 40033 Casalecchio di Reno (BO) - Italia </indirizzo> <referente cod="PE000928" nominativo="Mario Rossi"/> </rif_esterno> <rif_esterno copia_conoscenza="si"> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <indirizzo xml:space="preserve"> Via Manzoni, 2 - 40033 Casalecchio di Reno (BO) - Italia </indirizzo> <referente cod="PE000929" nominativo="Ermete Verdi"/> </rif_esterno> </rif_esterni> </doc>
L’elemento “repertorio” non è obbligatorio, tuttavia nel caso di registrazione di un documento appartenente ad un repertorio, deve essere indicato.
Ecco la risposta restituita dal metodo saveDocument():
<?xml version="1.0" encoding="UTF-8"?> <Response xmlns:xw="http://www.3di.it/ns/xw-200303121136" canSee="true" canEdit="true" canAddCC="true" canDelCC="true" canAddRPA="true" canAddPostIt="true" canAddFile="true" canAddImage="true" canInsInFolder="true" canLinkFolder="true" canCancel="true"> <Document idIUnit="19674"> <doc anno="2011" annullato="no" cod_amm_aoo="KIONCLE" data_prot="20110721" nrecord="00020297" num_prot="2011-KIONCLE-0000130" scarto="01" tipo="partenza"> <repertorio cod="V_D_CDA" numero="V_D_CDA^KIONCLE-20110000047">Verbali Consiglio di Amministrazione</repertorio> <oggetto xml:space="preserve">Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione cod="Posta Ordinaria" costo="58" valuta="euro"/> <classif cod="06/04" xml:space="preserve">06/04 - Documentazione</classif> <note xml:space="preserve">Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato xml:space="preserve">0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> <rif_esterni> <rif> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <referente cod="PE000928" nominativo="Mario Rossi"/> <indirizzo email="mrossi@ditta.it" fax="051 451242" tel="051 452844" xml:space="preserve"> Via Manzoni 2 - 40033 Casalecchio di Reno - BO - Italia </indirizzo> </rif> <rif copia_conoscenza="si"> <nome cod="SE000095" xml:space="preserve">Ditta srl</nome> <referente cod="PE000929" nominativo="Ermete Verdi"/> <indirizzo xml:space="preserve"> Via Manzoni, 2 - 40033 Casalecchio di Reno (BO) - Italia </indirizzo> </rif> </rif_esterni> <rif_interni> <rif diritto="RPA" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta"/> <rif diritto="CC" cod_persona="3" cod_uff="00003" nome_persona="Verdi Luca" nome_uff="Smistamenti"/> </rif_interni> <storia> <creazione cod_oper="PI000121" cod_uff_oper="SI000084" data="20110721" oper="Applicazione Client WS" ora="11:41:46" uff_oper="Ufficio Protocollo KION"/> <responsabilita cod_operatore="PI000121" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta" data="20110721" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> <assegnazione_cc cod_operatore="PI000121" cod_persona="3" cod_uff="00003" data="20110721" nome_persona="Verdi Luca" nome_uff="Smistamenti" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> </storia> <?xw-meta Dbms="ExtraWay" DbmsVer="21.1.3.116" OrgNam="Kion s.p.a." OrgVer="3.2" Classif="1.0" ManGest="1.0" ManTec="0.0.4" DocType="" InsUser="clWS" InsTime="20110721114146" ModUser="clWS" ModTime="20110721114146"?> <?xw-crc key32=d1b0d1e4-94c10140?> </doc> </Document> </Response>
Di seguito si riporta un esempio di codice XML riferito alla richiesta di registrazione di un documento tra uffici (tipo “interno”):
<?xml version="1.0" encoding="UTF-8"?> <doc tipo="interno"> <repertorio cod="REPI">Repertorio interno</repertorio> <minuta scarto="99"> <classif cod="03/05" xml:space="preserve">03/05 - Assistenza telefonica</classif> <mittente nome_persona="Marrone Antonio" nome_uff="Archivio" cod_persona="PI000122" cod_uff="SI000085"/> </minuta> <oggetto>Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione costo="5" valuta="euro" cod="Fax"></mezzo_trasmissione> <note>Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato>0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> </doc>
L’elemento “repertorio” non è obbligatorio, tuttavia nel caso di registrazione di un
documento appartenente ad un repertorio, deve essere indicato.
L’elemento “minuta” è obbligatorio.
Ecco la risposta restituita dal metodo saveDocument():
<?xml version="1.0" encoding="UTF-8"?> <Response xmlns:xw="http://www.3di.it/ns/xw-200303121136" canSee="true" canEdit="true" canEditCopy="true" canAddCC="true" canDelCC="true" canAddCDS="true" canDelCDS="true" canAddCDSM="true" canDelCDSM="true" canAddRPA="true" canAddPostIt="true" canAddFile="true" canAddImage="true" canInsInFolder="true" canLinkFolder="true" canInsCopyInFolder="true" canCancel="true"> <Document idIUnit="19660"> <doc anno="2011" annullato="no" cod_amm_aoo="KIONCLE" data_prot="20110721" nrecord="00020302" num_prot="2011-KIONCLE-0000144" scarto="01" tipo="interno"> <minuta scarto="99"> <classif cod="03/05" xml:space="preserve">03/05 - Assistenza telefonica</classif> <mittente nome_persona="Marrone Antonio" nome_uff="Archivio"/> </minuta> <oggetto xml:space="preserve">Richiesta documentazione protocollo informatico</oggetto> <tipologia cod="Dichiarazione"/> <mezzo_trasmissione cod="Fax" costo="5" valuta="euro"/> <classif cod="06/04" xml:space="preserve">06/04 - Documentazione</classif> <note xml:space="preserve">Note al documento</note> <riferimenti xml:space="preserve">CNIPA – Protocollo Informatico</riferimenti> <xlink href="http://www.link.it" xml:space="preserve">descrizione link</xlink> <allegato xml:space="preserve">0 - nessun allegato</allegato> <voce_indice xml:space="preserve">Documentazione</voce_indice> <rif_interni> <rif diritto="RPA" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta"/> <rif diritto="CC" cod_persona="3" cod_uff="00003" nome_persona="Verdi Luca" nome_uff="Smistamenti"/> <rif cod_persona="PI000122" cod_uff="SI000085" diritto="RPAM" nome_persona="Marrone Antonio" nome_uff="Archivio"/> </rif_interni> <storia> <creazione cod_oper="PI000121" cod_uff_oper="SI000084" data="20110721" oper="Applicazione Client WS" ora="11:41:46" uff_oper="Ufficio Protocollo KION"/> <responsabilita cod_operatore="PI000121" cod_persona="11111" cod_uff="SI000006" nome_persona="Rossi Mario" nome_uff="Controllo posta" data="20110721" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> <responsabilita_minuta cod_operatore="PI000121" cod_persona="PI000122" cod_uff="SI000085" data="20110721" data_visto="20110721" nome_persona="Marrone Antonio" nome_uff="Archivio" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46" ora_visto="11:41:46" visto_da="Marrone Antonio (Archivio)"/> <assegnazione_cc cod_operatore="PI000121" cod_persona="3" cod_uff="00003" data="20110721" nome_persona="Verdi Luca" nome_uff="Smistamenti" operatore="Applicazione Client WS (Ufficio Protocollo KION)" ora="11:41:46"/> </storia> <?xw-meta Dbms="ExtraWay" DbmsVer="21.1.3.116" OrgNam="Kion s.p.a." OrgVer="3.2" Classif="1.0" ManGest="1.0" ManTec="0.0.4" DocType="" InsUser="clWS" InsTime="20110721114146" ModUser="clWS" ModTime="20110721114146"?> <?xw-crc key32=d1b0d1e4-94c10140?> </doc>
Per aggiungere degli allegati ad un documento che ne è privo, occorre invocare il metodo checkInContentFiles() (per i dettagli si rimanda al javadoc).
Il contenuto binario dei file da allegare deve essere inserito nella richiesta SOAP e per ogni file deve essere indicato il nome che verrà presentato all'utente al momento della visualizzazione del documento.
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
Nell'esempio vengono inseriti 2 allegati nel documento con id ”idUnit”, e di questi viene richiesta la conversione in pdf.
import org.apache.axis.client.Call; import javax.activation.DataHandler; import javax.activation.FileDataSource; ... ... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // *** aggiunta degli allegati al documento idUnit *** // meglio usare MIME (Call.ATTACHMENT_ENCAPSULATION_FORMAT_MIME) per l'incapsulamento // degli allegati nella richiesta SOAP dato che con DIME si possono avere degli errori // ("java.io.IOException: End of physical stream detected when XX more bytes expected.") // in fase di conteggio (Attachments.getAttachmentCount()) degli allegati da parte del // ricevente. ((TitulusSoapBindingStub)this.titulus)._setProperty(Call.ATTACHMENT_ENCAPSULATION_FORMAT, Call.ATTACHMENT_ENCAPSULATION_FORMAT_MIME); FileDataSource file1 = new FileDataSource(new File("Manuale_ACL.pdf")); FileDataSource file2 = new FileDataSource(new File("doc.txt")); ((TitulusSoapBindingStub)this.titulus).addAttachment(new DataHandler(file1)); ((TitulusSoapBindingStub)this.titulus).addAttachment(new DataHandler(file2)); String resp = this.titulus.checkInContentFiles(idUnit, new String[]{ "man_acl.pdf", "documento_xml.txt" }, null, true, false); log.debug("document now is:\r\n\n" + resp + "\n"); // clears request attachments ((TitulusSoapBindingStub)this.titulus).clearAttachments();
Per i file associati ad un documento è attivo il versioning: gli operatori autorizzati possono richiedere il check-out del file da aggiornare, per poi introdurre la nuova versione del file con un'operazione di check-in. Questa opzione è disponibile solo per documenti non protocollati o per bozze di documenti protocollati. Inoltre, il versioning non è possibile per le immagini.
Ogni versione di file viene incapsulata come elemento figlio dell’elemento (xw:file) corrispondente alla versione precedente:
<files> <xw:file convert="remove" name="XXX.txt" title="test_versions.txt"> <chkin cod_operatore="PI000056" data="20101028" operatore="TEST WS" ora="16:26:20"/> <chkout cod_operatore="PI000056" data="20101028" operatore="TEST WS" ora="16:26:21"/> <xw:file convert="remove" name="YYY.txt" title="test_versions1.txt"> <chkin cod_operatore="PI000056" data="20101028" operatore="TEST WS" ora="16:26:21"/> <chkout cod_operatore="PI000056" data="20101028" operatore="TEST WS" ora="16:26:21"/> ... <xw:file convert="remove" name="ZZZ.txt" title="test_versionsN.txt"> <chkin cod_operatore="PI000056" data="20101028" operatore="TEST WS" ora="16:26:22"/> </xw:file> </xw:file> </xw:file> </files>
I metodi messi a disposizione per il versioning sono:
Il numero massimo di versioni di un file accettate è 90 (nota: è possibile configurare Titulus in modo tale che accetti un numero massimo di versioni inferiore). Il superamento di questa soglia comporta un'eccezione in fase di check-in da intercettare lato client.
Di seguito si riporta un esempio in linguaggio Java, realizzato con la libreria Axis. Lo stub client usato (nel codice ”this.titulus”), è stato generato a partire dal wsdl del servizio, mediante il tool WSDL2Java.
Nell'esempio viene aggiunta una nuova versione dell'allegato con id ”attachID” nel documento ”idUnit”, e di questa viene richiesta la conversione in pdf.
Non sono state riportate l'estrazione dalla risposta SOAP dell'allegato restituito dal checkout, l'aggiornamento del file e la creazione del DataHandler (”attachDH”) per l'upload della nuova versione.
Queste operazioni sono state illustrate nei paragrafi Download file associati ed immagini e Aggiunta di allegati ad un documento.
import org.apache.axis.client.Call; import javax.activation.DataHandler; ... ... this.titulus.init(null, null, "test-ws", null, "xdocwaydoc-test", -1, -1); ... // *** aggiunta di una nuova versione dell'allegato con id "attachID" nel documento idUnit *** // checkout String docXML = this.titulus.checkOutContentFile(idUnit, attachID, true, false); System.out.println("document after checkout is:\r\n\n" + docXML + "\n"); // *********************************************************************************** // Estrazione dalla risposta SOAP dell'allegato restituito dal checkout, aggiornamento // del file e creazione del DataHandler ("attachDH") per l'upload della nuova versione // *********************************************************************************** ... // checkin // clears attachments of checkOutContentFile ((TitulusSoapBindingStub)this.titulus).clearAttachments(); // meglio usare MIME (Call.ATTACHMENT_ENCAPSULATION_FORMAT_MIME) per l'incapsulamento // degli allegati nella richiesta SOAP dato che con DIME si possono avere degli errori // ("java.io.IOException: End of physical stream detected when XX more bytes expected.") // in fase di conteggio (Attachments.getAttachmentCount()) degli allegati da parte del // ricevente. ((TitulusSoapBindingStub)this.titulus)._setProperty(Call.ATTACHMENT_ENCAPSULATION_FORMAT, Call.ATTACHMENT_ENCAPSULATION_FORMAT_MIME); ((TitulusSoapBindingStub)this.titulus).addAttachment(attachDH); docXML = titulus.checkInContentFiles(idUnit, new String[]{ "nuova_versione.txt" }, new String[]{ attachID }, true, false); // clears request attachments ((TitulusSoapBindingStub)titulus).clearAttachments(); System.out.println("document after checkin is:\r\n\n" + docXML + "\n");
Per modificare un documento è necessario caricare il documento bloccandolo attraverso il metodo loadDocument().
In seguito al caricamento con flag di lock attivo, qualora si intenda abbandonare il documento, è necessario sbloccarlo per mezzo del metodo unlockDocument().
Il salvataggio in modifica di un documento precedentemente caricato e bloccato, deve avvenire per mezzo del metodo saveModifiedDocument(). Notare che il codice xml passato come primo parametro deve avere come radice l'effettiva radice del documento (per es. “doc”) e non la radice della “busta” XML restituita dal caricamento del documento.
Alcuni attributi ed elementi non sono modificabili e le loro modifiche vengono ignorate all'atto del salvataggio del documento. Di seguito una sintesi degli XPath non modificabili:
/doc/@nrecord /doc/@tipo /doc/@num_prot /doc/@cod_amm_aoo /doc/storia /doc/rif_interni /doc/rif_esterni /doc/files /doc/immagini /doc/impronta /doc/minuta /doc/wflow /doc/repertorio
Per i documenti di protocollo, si aggiungono i seguenti percorsi fra quelli non modificabili:
/doc/@anno /doc/@data_prot /doc/oggetto /doc/allegato
La responsabilità di un documento viene assegnata in fase di registrazione dello stesso (si veda “Creare un nuovo documento”). In tale sede è necessario riportare gli estremi del responsabile all’interno dell’elemento /doc/rif_interni/rif_interno, impostando l’attributo diritto=”RPA”. Lo stesso dicasi per il responsabile della minuta (diritto=”RPAM”) e per i nominativi in copia conoscenza (diritto=”CC”).
Qualora in seguito alla registrazione si renda necessario il trasferimento del documento ad altro RPA, o l’aggiunta di nominativi fra i CC, si può far uso del metodo grantRight().
Ad esempio:
...
grantRight(<idIUnit>, “RPA”, “Ciampi Carlo Azeglio”, “Presidenza della Repubblica”,
“KONCENT”, true);
...
trasferisce la responsabilità del documento individuato da idUnit a “Carlo Azeglio
Ciampi”, inviando al nuovo RPA un'email di notifica dell'assegnazione di responsabilità.
Qualora si intenda rimuovere un nominativo dalle copie conoscenza di un documento, si può fare uso del metodo denyRight().
Entrambi i metodi (grantRight() e denyRight()) non richiedono il previo caricamento del documento (loadDocument()) ed il successivo salvataggio (saveDocument()), procedendo in autonomia a modificare i soli dati relativi a tali diritti nel documento.
È prevista la possibilità di aggiungere un post-it ad un documento già registrato. A tale scopo è stato previsto il metodo postIt() al quale è sufficiente trasmettere il numero fisico del documento ed il testo del post-it. Il metodo registra anche data, ora e nome dell’operatore che ha effettuato l’operazione.
È prevista la possibilità di annullare un documento già registrato. A tale scopo è stato previsto il metodo cancelDocument() al quale è sufficiente trasmettere il numero fisico del documento ed il motivo dell’annullamento. All’atto dell’annullamento vengono registrati anche data, ora e nome dell’operatore che ha effettuato l’operazione.
È possibile rimuovere un documento non protocollato e tutti i file ad esso associati per mezzo del metodo deleteDocument(). Non è possibile cancellare documenti protocollati.
È possibile inserire nel sistema un documento protocollato in versione bozza (/doc/@bozza=”si”) sul quale è possibile effettuare opportune operazioni di modifica fino al momento della registrazione ufficiale attraverso il metodo applyRegistrationToDraft().
Attraverso l'invocazione del metodo newFolder() è possibile creare un nuovo fascicolo. Di seguito un esempio della specifica XML da passare al metodo in questione:
<?xml version="1.0"?> <fascicolo> <oggetto>Emissione fattura per primo workflow venduto</oggetto> <classif cod="7/3"/> <rif_interni> <rif diritto="RPA" nome_persona="Carlo Azeglio" nome_uff="Presidenza"/> </rif_interni> </fascicolo>
Anche in tale caso, come nella registrazione di documenti, alcuni “campi” (classificazione da titolario ed estremi RPA) vengono valorizzati in automatico.
Per popolare un fascicolo con dei documenti è stato predisposto il metodo addInFolder(), mentre attraverso l'invocazione del metodo newSubFolder() è possibile creare dei sottofascicoli originando una vera è propria gerarchia.
La consultazione di una gerarchia di fascicoli (in forma sintetica) avviene per mezzo del metodo getFolderHierarchy(), mentre il metodo getFolderContent() consente di recuperare la lista dei documenti contenuti e collegati ad un fascicolo.
Attraverso l'invocazione del metodo getDesktop() si ottengono una serie di Result-Set che identificano l'insieme dei documenti che soddisfano opportuni criteri di ricerca (su base personale o ufficio di appartenenza): documenti di cui si è responsabili (RPA) o di responsabilità dell'ufficio di appartenenza (UOR), documenti di cui si è in copia conoscenza (CC o CDS) ed altri.
Invocando il metodo getWorkflowId() si può accedere al/ai workflow associato/i ad un documento e con il metodo getWorkflowAction() si ottengono le eventuali azioni disponibili.
Il metodo startWorkflow() avvia un flusso su un documento, mentre continueWorkflow() fa avanzare un workflow attivo.
È prevista una serie di funzionalità per l'amministrazione del database degli utenti (ACL) ed i relativi diritti. Per creare un nuovo utente si ricorre al metodo addUser(), mentre la creazione di un ufficio avviene attraverso l'invocazione del metodo addInternalStructure(). Da sottolineare che l'organizzazione interna degli uffici assume le sembianze di una vera e propria gerarchia. Di seguito un esempio di specifica XML per la creazione di un nuovo ufficio in relazione gerarchica di figliolanza con l'ufficio identificato dal codice “00001” (cod_padre=”00001”):
<?xml version="1.0"?> <struttura_interna cod_aoo="ENT" cod_amm="KONC" tipologia="Area" cod_padre="00001" cod_responsabile="1"> <nome>Unità organizzativa XYZ</nome> <indirizzo nazione="Italia" prov="BO" cap="40033" comune="Casalecchio di Reno"> Via Magnanelli, 2 </indirizzo> <email addr="email1@dom.it" /> <note>Alcune note...</note> </struttura_interna>
È possibile creare nuovi profili di utenza e modificarne di esistenti sfruttando i metodi addProfile() e modifyProfile().