Accesso Diretto Risorse (DAR)
In Geoweb la funzionalità DAR (Direct Access Resource), introdotta con la versione 4.6.5, permette di implementare l'accesso automatico diretto ad una qualsiasi risorsa, tramite link URL.
Definizione di Risorsa
E’ una qualsiasi tipo di scheda (o componente di UI) apribile tramite le api javascript di Geoweb. Esempi:
- gwClassList, lista di classe, eventualmente prefiltrata
- gwClassDetail, dettaglio di classe
- layout2D, scheda mappa con uno o più oggetti selezionati, e con eventuali filtri sui layer
- …
- combinazioni di risorse: lista+dettaglio, etc..
In questo documento si parla esclusivamente di risorse erogabili nell'ambito del gwProject.
Altri tipi di risorsa, per esempio documenti ospitati nei documentali, possono essere scaricati tramite link diretto, costruendolo secondo le specifiche api.
Casi d'uso
L'ambito di utilizzo principale, è per generare url che puntano a determinate risorse da utilizzare nella creazione automatica di email e notifiche utente. Di recente la funzionalità DAR è stata anche utilizzata come base per il funzionamento del widget indirectLocalizationWidget.
Alla luce delle future implementazioni si suggerisce di predisporre l'infrastruttura delle tabelle DAR in ogni nuova implementazione di Prodotto/Progetto. Per i porting di vecchie installazioni alla versione 4.6.x si dovrà invece valutare caso per caso
Descrizione funzionamento
L'apertura della risorsa viene materialmente effettuata tramite l'invocazione di una function javascript, disponibile nel namespace globale. La function viene eseguita al momento opportuno, durante le fasi di apertura del progetto. Il nome della funzione, i parametri con cui essa deve essere invocata, e il progetto di riferimento sono racchiusi in un oggetto di tipo DAR, che viene persistito sul database, e a cui si fa riferimento tramite un id criptato.
Parametro dar
L'apertura di una data risorsa è attuata tramite l'introduzione di un nuovo parametro: dar, opzionale, da aggiungere nel queryString dell'url del gwProject. dar rappresenta l'identificativo criptato dell'oggetto DAR censito sul database (Es: 'dar=sqsUQ14rLb4nknbNMUmOyNvIG76xmxkeYJfhKcp0Abc').
Esempio url:
http://localhost:8081/webclient/project/base_ut.html?group=TESTER_GROUP&preventCache=1686735011463&dar=sqsUQ14rLb4nknbNMUmOyNvIG76xmxkeYJfhKcp0Abc
Generazione URL
L'url di progetto può essere generato tramite l'apposito service DirectAccessResourceService, esposto nei .groovy come darService. Questo espone tutta una serie di metodi di utilità. Il metodo più generale per censire un DAR dal groovy, ed ottenerne il relativo url è:
public String generateDARFromDARParts(String functionName, String jsonParam, String gwProjectName, Map<String,Object> queryParameterMap)
Utilizzabile cosi:
String functionName = "alert"; def params = "alert message"; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDARFromDARParts(functionName, params, gwProjectName, queryParameterMap);
String functionName = "openGwClassDetail"; def itemId = 19; def gwClassName = "utc"; def gwClassDetailOptions = [:]; gwClassDetailOptions.openingDetailMode = "tab"; Map<String,Object> params = [itemId, gwClassName, gwClassDetailOptions]; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = [:]; queryParameterMap.group = "group"; queryParameterMap.gwp = "vIG76xmxkeYJfhKcp0AbcsqsUQ14rLb4nknbNMUm"; String url = services.darService.generateDARFromDARParts(functionName, params, gwProjectName, queryParameterMap);
In generale si specifica la funzione da eseguire, i relativi parametri ed il progetto di contesto. Inoltre si possono specificare una mappa di ulteriori parametri che si desidera vadano nell'url per utilizzare altre funzionalità del framework, come:
- imposizione oggetto in sessione
- imposizione gruppo (scelto in automatico, se assente)
- imposizione ambito (scelto in automatico, se assente)
Parametri funzione
Venendo i parametri riversati in automatico al momento dell'invocazione delle function, sono validi tutti i parametri supportati dalla funzione medesima. Ne deriva che, utilizzando come function una api js specifica, se ne possono utilizzare con successo anche tutti i relativi parametri.
I parametri verranno semopre passati come array alle funzioni. nel caso il parametro in ingresso sia una mappa, verrà incapsulato in automatico come primo elemento di un array. Questo anche perchè alcune api js preesistenti prevedevano più parametri (es: openGwClassDetail()) Cosi viene garantita la massima flessibilità. L'unica accortezza è nel caso, si utilizzi una function il cui primo parametro ammesso è a sua volta un array, è quello di pre-incapsularlo in un altro array, seguito dagli eventuali altri:
metodi specializzati
Esistono dei metodi specializzati per generare url per i casi più comuni. Questi settano in automatico il functionName e calcolano in automatico il path di navigazione sui tre livelli (vedi sotto). Elenco:
//apertura lista public String generateDAROpenGwClassListTab(Map<String,Object> params, String gwProjectName, Map<String,Object> queryParameterMap) //apertura scheda lista+dettaglio public String generateDAROpenGwClassListTabAndGwClassDetail(Map<String,Object> params, String gwProjectName, Map<String,Object> queryParameterMap) //esecuzione leafItemAction public String generateDARExecuteLeafItemAction(Map<String,Object> params, String gwProjectName, Map<String,Object> queryParameterMap) //apertura scheda Layout2D public String generateDAROpenLayout2DTab(Map<String,Object> params, String gwProjectName, Map<String,Object> queryParameterMap) //apertura scheda report html public String generateDAROpenGwHtmlReport(Map<String,Object> params, String gwProjectName, Map<String,Object> queryParameterMap) //generazione del solo url public String buildURL(DAR dar, Map<String,Object> queryParameterMap)
Questi metodi hanno come controparte javascript i seguenti metodi predefiniti che, oltre a ricalcare la api js di base, si occupano anche di provare a selezionare il path di navigazione sui tre livelli di menu.
- function openGwClassListTabDAR(params)
- function openGwClassListTabAndGwClassDetailDAR(params)
- function openGwClassListTabAndGwClassDetailFloatingPaneDAR(params)
- function openGwClassListTabAndGwClassDetailDialogDAR(params)
- function openGwClassListTabAndGwClassDetailTabDAR(params)
- function executeLeafItemActionDAR(params)
- function openLayout2DTabDAR(params)
- function openGwHtmlReportDAR(params)
altri metodi
Altri metodi, di carattere generale. Non dovrebbero servire nei groovy, ma si elencano per completezza.
public Integer insertDAR(DAR dar) public Integer updateDAR(DAR dar) public Integer deleteDAR(DAR dar) public DAR selectById(Integer darId) public DAR selectByIdEnc(String darIdEnc) public ArrayList<DAR> selectAll() public ArrayList<DAR> selectAllByGwProject(String gwProjectName) public ArrayList<DAR> selectAllByFunctionName(String functionName) public String generateDARFromDARParts(String functionName, String jsonParam, String gwProjectName) public String generateDARFromDARParts(String functionName, String jsonParam, String gwProjectName, Map<String,Object> queryParameterMap) { public String generateDAR(DAR dar) public String generateDAR(DAR dar, Map<String,Object> queryParameterMap)
Esempi di utilizzo comune (generazione url da groovy)
Apertura scheda gwClassList
String gwProjectName = "gwProjectName"; Map<String,Object> params = [:]; params.gwClassName = "utc"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenGwClassListTab(params, gwProjectName, queryParameterMap);
String gwProjectName = "gwProjectName"; Map<String,Object> params = [:]; params.gwClassName = "utc"; params.staticFilters= [[condition: "AND", columnName: "field", operator: "=", value: "a"]]; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenGwClassListTab(params, gwProjectName, queryParameterMap);
Apertura scheda gwClassList + gwClassDetail
apertura tab
Map<String,Object> params = [:]; params.gwClassName = "utc"; params.itemId= "19"; def gwClassListOptions = [:]; params.gwClassListOptions = gwClassListOptions ; def gwClassDetailOptions = [openingDetailMode: "tab"]; params.gwClassDetailOptions = gwClassDetailOptions ; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenGwClassListTabAndGwClassDetail(params, gwProjectName, queryParameterMap);
Map<String,Object> params = [:]; params.gwClassName = "utc"; params.itemId= "19"; def gwClassListOptions = [staticFilters: [[condition: "AND", columnName: "field", operator: "=", value: "a"]] ]; params.gwClassListOptions = gwClassListOptions ; def gwClassDetailOptions = [openingDetailMode: "floatingPane", detailLayoutName: "textbox", hideTopToolbar: true]; params.gwClassDetailOptions = gwClassDetailOptions ; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenGwClassListTabAndGwClassDetail(params, gwProjectName, queryParameterMap);
Apertura scheda Layout2D
mappa cartografica
Map<String,Object> params = [:]; params.gwMapName = "sites"; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenLayout2DTab(params, gwProjectName, queryParameterMap);
planimetria, filtrata, e selezione multipla in mappa
Map<String,Object> params = [:]; params.gwMapName = "mappa_asset"; params.drawingSetId= 12345; params.classNameToItemIdListMap= [asm_asset: [456, 789]]; params.geometryColumn = "mainGeom"; params.saveMapSelection = true; gwLayerNameToStaticFiltersMap = [asset: [[ … operato: "=", value: "ACTIVE"]]]; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenLayout2DTab(params, gwProjectName, queryParameterMap);
Apertura scheda reportHTML
Map<String,Object> params = [:]; params.reportUrl = "reportUrl"; params.gwClassName = "gwClassName"; params.reportParameters = [p1: "v1", p2: 2, p3: true]; params.updateOnChangeInGwClassNameList = "gwClassName1,gwClassName2"; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDAROpenGwHtmlReport(params, gwProjectName, queryParameterMap);
Apertura scheda da leafItem gwAction
A volte una risorsa è aperta tramite gwAction configurata nell'xml di progetto. Per usare i medesimi meccanismi è previsto l'apposito metodo esposto. Non è previsto il passaggio di parametri alla gwAction di classe (in quanto autoconsistente). Nel caso fosse necessario il passaggio di parametri sarebbe opportuno creare una function custom ed invocare l'api generale nel groovy.
Map<String,Object> params = [:]; params.gwClassName = "gwClassName "; params.gwActionName = "gwActionName "; String gwProjectName = "base_ut"; Map<String,Object> queryParameterMap = null; String url = services.darService.generateDARExecuteLeafItemAction(params, gwProjectName, queryParameterMap);
Caso generale
Qualora fosse necessario implementare comportamenti fuori dallo standard nell'atto di erogare una risorsa i passaggi da seguire sarebbero i seguenti:
- individuare una function js predefinita che venga definita nel DAR. In caso contrario definirla in un plugin di prodotto/commessa
- generare il DAR utilizzando l'api java generale
Selezione automatica 3-level menu
Ove possibile, qualora la risorsa richiesta sia dichiarata nella struttura dell'xml di progetto, verrà coerentemente selezionato il path di navigazione dei 3 livelli di menu.
Questo avviene tramite un controllo di matching fra la tipologia di scheda ed gli eventuali parametri aggiuntivi. Più parametri saranno aggiunti e più restrittivo diventerà il criterio di matching.
Per esempio dato un url, con dar generato tramite generateDAROpenGwClassListTab(), senza definire ulteriori parametri per la gwClassList, verrà selezionata in automatico, se trovata, la prima voce di menu che avrà gwClassList per leafItem type e il cui parametro gwClassName sarà il medesimo referenziato dal dar.
Specificare ulteriori parametri per la gwClassList nel dar, causerà l'aggiunta di ulteriori criteri nella ricerca nella struttura dell'xml di progetto.
Ci potrebbero essere casi in cui i parametri del dar, potrebbero essere definiti in più punti della struttura xml di progetto. Per esempio dar generati con generateDAROpenGwClassListTab() senza parametri e più voci leafItem gwClassList con differenti filtri statici nell'xml di progetto. In questo caso è utile utilizzare il parametro navCoords, che forza la selezione sui tre livelli di menu, evitando l'autoretrieve del path, che selezionerebbe la prima voce corrispondente ai pochi criteri.
Da notare che la risorsa verrà aperta sempre e solo utilizzando i parametri specificati nel DAR, e non gli ulteriori eventualmente specificati nell'xml di progetto.
Note selezione automatica 3-level menu
La selezione è supportata per le azioni gwAction presenti nell'xml di progetto [java generateDARExecuteLeafItemAction()+js executeLeafItemActionDAR()]. Per altre azioni generiche, non verrà fatta la selezione automatica a meno che non si forzi il parametro navCoords, nel primo o nell'ultimo (per flessibilità di utilizzo) oggetto dell'array di parametri con cui viene invocata la funzione
Integrazione con altri sviluppi
Questa funzionalità si lega a sviluppi paralleli, come quello del sistema di eventi e notifiche. In particolare si vorrebbe permettere all’utente di accedere direttamente la risorsa oggetto della notifica, tramite url. Fin da ora potrebbe già essere configurato per una più potente e diretta navigazione fra le risorse delle funzioni
configuration.properties
L’url verrà costruito sulla base di un base url, recuperato dal configuration.properties dal nuovo parametro introdotto per l’occasione: baseUrl.
################################################################## # B A S E U R L ################################################################## baseUrl=http://localhost:8081/webclient
Nozioni Tecniche Aggiuntive
Modello dati
A supporto della nuova funzionalità è prevista la creazione di una nuova tabella sullo schema dati: gw_dar.
Dettaglio campi:
- dar_id: integer, required, chiave primaria per la tabella e identificativo della dar
- function_name, string, required. Nome della funzione, disponibile nel namespace (direttamente nel framework o da qualche plugin), contenente il codice necessario per l’apertura della risorsa (tipicamente un’invocazione diretta delle api javascript esposte)
- json_param, string, optional, default null. Stringa in formato JSON contenente eventuali parametri di ingresso da fornire alla function js. Qui andrebbe anche un parametro, opzionale, che se configurato può essere usato per replicare l’apertura, previa navigazione, da parte di una scheda configurata nell’xml di progetto (in sua assenza si tenterebbe comunque di ricostruire il path di navigazione, in maniera automatica, ma non sempre funzionante):
- navCoords: Integer[], contenente gli indici delle voci di menu rispettivamente del 1st, del 2nd e del 3rd level menu. Per esempio [2,0,1]
- gw_project_name, string, required. Name del gwProject su cui dovrà essere eseguita la function. Introdotto per motivi di sicurezza: al momento dell’esecuzione della function verrà eseguito un check di consistenza del projectName.
- dar_id_enc: string, auto-calcolato sulla base di dar_id, con chiave simmetrica (AES/CBC/PKCS5PADDING). Viene fatta anche la codifica URL. Minima lunghezza: 43 char, che può crescere coerentemente con le dimensioni del dar_id da cifrare
- dar_url: string, auto-calcolato sulla base di gw_project_name, di dar_id_enc e degli altri eventuali valori da inserire nel queryString dell’URL.
- dar_date: date, autocalcolato sulla data computazione del dar_url
script Oracle
CREATE TABLE "xxx_data"."gw_dar" ( "dar_id" NUMBER(*,0) NOT NULL ENABLE, "function_name" VARCHAR2(400 BYTE) NOT NULL ENABLE, "json_param" VARCHAR2(4000 BYTE) NOT NULL ENABLE, "gw_project_name" VARCHAR2(250 BYTE) NOT NULL ENABLE, "dar_id_enc" VARCHAR2(400 BYTE), "dar_url" VARCHAR2(4000 BYTE), "dar_date" DATE, CONSTRAINT "GWdar_PKEY" PRIMARY KEY ("dar_id") );
script Postgres
CREATE TABLE IF NOT EXISTS xxx_data.gw_dar ( dar_id INTEGER NOT NULL, function_name CHARACTER VARYING COLLATE pg_catalog."default" NOT NULL, json_param CHARACTER VARYING COLLATE pg_catalog."default" NOT NULL, gw_project_name CHARACTER VARYING COLLATE pg_catalog."default" NOT NULL, dar_id_enc CHARACTER VARYING COLLATE pg_catalog."default", dar_url CHARACTER VARYING COLLATE pg_catalog."default", dar_date TIMESTAMP WITHOUT TIME zone, CONSTRAINT gw_dar_pkey PRIMARY KEY (dar_id) ) WITH ( OIDS = FALSE ) TABLESPACE pg_default; ALTER TABLE xxx_data.gw_dar OWNER TO xxx_data;
script MS Sqlserver
CREATE TABLE [xxx_data].[gw_dar] ( [dar_id] [INT]IDENTITY(1,1) NOT NULL, [function_name] [VARCHAR](400), [json_param] [VARCHAR](MAX), [gw_project_name] [VARCHAR](250), [dar_id_enc] [VARCHAR](400), [dar_url] [VARCHAR](MAX), [dar_date] [datetime], CONSTRAINT [gw_dar_pkey] PRIMARY KEY (dar_id) );
Metadati gwClass gw_dar
Metadati utilizzati per l'ambiente di test ed utili per la gestione della anagrafica DAR. Tema DAR e classe gw_dar (.zip)