geoportal-access-lib
Version:
French Geoportal resources access library
483 lines (443 loc) • 15.3 kB
JavaScript
import Logger from "../Utils/LoggerByDefault";
import RequestHeader from "./XLS/RequestHeader";
import Request from "./XLS/Request";
import AbstractService from "./XLS/AbstractService";
/**
* @classdesc
*
* standard OpenLS
* standard XLS
* (version 1.2)
*
* Réfs :
* - {@link http://schemas.opengis.net/ols/1.2/}
* - {@link http://www.opengeospatial.org/standards/ols}
* - {@link http://wxs.ign.fr/schemas/}
*
*
* Création du template XLS (avec gestion des namespaces)
* ------------------------
* ```
* balise xsd : element name="XLS" attribute name="version" [(attribute ref="lang")]
* ```
*
* Exemple :
* ```
* <XLS xmlns="http://www.opengis.net/xls" version="1.2">
* < (ref. OLS) />
* </XLS>
* ```
* ```
* <xls:XLS xmlns:xls="http://www.opengis.net/xls" version="1.2">
* <xls: (ref. OLS) />
* </xls:XLS>
* ```
*
* Création des templates OLS pour LocationUtilityService
* ------------------------------------------------------
*
* Exemple :
*
* ```
* <RequestHeader srsName="epsg:4326"/>
* <Request maximumResponses="26" methodName="GeocodeRequest" requestID="uid1349081498314_388" version="1.2">
* <GeocodeRequest>
* <Address countryCode="PositionOfInterest">
* <freeFormAddress>saint mandé</freeFormAddress>
* </Address>
* </GeocodeRequest>
* </Request>
* ```
* ```
* <RequestHeader sessionID="" />
* <Request methodName="ReverseGeocodeRequest" version="1.2" requestID="" maximumResponses="10">
* <ReverseGeocodeRequest>
* <Position>
* <gml:Point xmlns:gml="http://www.opengis.net/gml">
* <gml:pos>50.347775 3.205098</gml:pos>
* </gml:Point>
* </Position>
* <ReverseGeocodePreference>StreetAddress</ReverseGeocodePreference>
* </ReverseGeocodeRequest>
* </Request>
* ```
* ```
* Geocodage direct (balise xsd) :
* element ref="RequestHeader" [ (attribute name="clientName" attribute name="clientPassword" attribute name="sessionID" attribute name="srsName" attribute name="MSID") ]
* element name="Request" attribute name="methodName" attribute name="version" attribute name="requestID" [ attribute name="maximumResponses" ]
* element name="GeocodeRequest" attribute name="returnFreeForm"
* element ref="xls:Address"
* ```
* ```
* Geocodage inverse (balise xsd) :
* element ref="RequestHeader" [ (attribute name="clientName" attribute name="clientPassword" attribute name="sessionID" attribute name="srsName" attribute name="MSID") ]
* element name="Request" attribute name="methodName" attribute name="version" attribute name="requestID" [ attribute name="maximumResponses" ]
* element name="ReverseGeocodeRequest"
* element ref="xls:Position"
* element name="ReverseGeocodePreference" (enumeration)
* ```
*
* Il existe 3 sous ensembles d'objets :
* - RequestHeader
* - Request
* - ReverseGeocodeRequest, GeocodeRequest
*
* GeocodeRequest est composé d'un objet {@link Gp.Services.Geocode.Response.GeocodeLocation}.
* ReverseGeocodeRequest est composé d'un objet {@link Gp.Services.ReverseGeocode.Response.ReverseGeocodeLocation}.
*
* Les locations font appels aux objets suivants qui possèdent des attributs spécifiques
* en fonction du type de table de geocodage interrogé :
* - StreetAddress
* - CadastralParcel
* - PositionOfInterest
* - Administratif
*
*
* et des élements sous jacents tels que :
* - ReverseGeocodePreference -> tables de geocodages :
* - StreetAddress
* - CadastralParcel
* - PositionOfInterest
* - Administratif (une balise par table)
* - Position -> standard GML 3.2.1
* - Address -> cf. ci-dessous
*
* ```
* Position (balise xsd) :
* ex. <Position><gml:Point xmlns:gml="http://www.opengis.net/gml"><gml:pos>50.347775 3.205098</gml:pos></gml:Point></Position>
* ex. <Position><gml:CircleByCenterPoint xmlns:gml="http://www.opengis.net/gml"><gml:pos>48.85978570614691 2.2913572761128878</gml:pos><gml:radius>1000</gml:radius></gml:CircleByCenterPoint></Position>
* (au choix)
* element ref="gml:Point"
* element ref="gml:CircleByCenterPoint"
* element ref="gml:Polygon"
* element ref="gml:MultiPolygon"
* les autres elemennts ne sont pas implémentés (QoP, Speed, Direction, Time, ...)
*
* Address (balise xsd) :
* ex. <Address countryCode="StreetAddress"><freeFormAddress>1 r de paris saint denis</freeFormAddress></Address>
* attribute name="countryCode"
* element name="freeFormAddress"
* element ref="xls:Place"
* element ref="gml:Envelope"
* ou
* ex. <Address countryCode="StreetAddress"><StreetAddress><Street>1 rue Marconi</Street></StreetAddress><Place type="Municipality">Metz</Place><PostalCode>57000</PostalCode></Address>
* attribute name="countryCode"
* element ref="xls:StreetAddress"
* element ref="xls:PostalCode"
* element ref="xls:Place"
* element ref="gml:Envelope"
*
* Place (balise xsd) :
* ex. <Place type="Municipality">Metz</Place>
* attribute name="type"
* enumeration value="CountrySubdivision"
* enumeration value="CountrySecondarySubdivision"
* enumeration value="Municipality"
* enumeration value="MunicipalitySubdivision"
* enumeration value="choume-banchi-go"
* enumeration value="Qualite"
* enumeration value="Departement"
* enumeration value="Bbox"
* enumeration value="Commune"
* enumeration value="Territoire"
* enumeration value="Importance"
* enumeration value="Nature"
* (la liste n'est pas exhaustives...)
*
* StreetAddress (balise xsd) :
* ex. <StreetAddress><Street>1 rue Marconi</Street></StreetAddress>
* attribute name="locator"
* element name="xls:Building"
* element ref="xls:Street"
*
* Street (balise xsd) :
* ex. <Street>1 rue Marconi</Street>
* attribute name="officialName" (...)
*
* Building (balise xsd) :
* ex. <Building number="800"/>
* attribute name="number" attribute name="subdivision" attribute name="buildingName"
*
* PostalCode (balise xsd) :
* ex. <PostalCode>77182</PostalCode>
*
* ```
*
* Requête
* -------
*
* 2 modes de requête sur les services : GET ou POST.
*
* Le mode GET n'est que l'encodage du XML en param (qxml) de la requête (donc pas d'implementation particulière ?)
*
* Modèle de classes
* -----------------
*
* ```
* ________ XLS ____________
* / | \
* RequestHeader AbstractService Request
* ^
* ______|________________________
* (extends) / \ (extends)
* LocationUtilityService RouteService
* | |
* ___________|___________ (...)
* / \
* GeocodeRequest ReverseGeocodeRequest
* | |
* | _____|______
* | / \
* Address Preference Position
* |
* / \
* Place StreetAddress
* |
* / \
* Street Building
* ```
*
* @example
* // encapsule un objet 'LocationUtilityService'
* // dans une coquille XSL (avec/sans namespace)
* xsl = new XSL ();
* xsl.namespace = false;
* xsl.srsName = "epsg:4326";
* xsl.maximumResponses = 26;
* // methodName fournit par l'objet 'lus'
* // requestID est calculé
* xsl.setService (lus);
* xsl.build ();
* // out ->
* // <XLS xmlns="http://www.opengis.net/xls" version="1.2">
* // <RequestHeader srsName="epsg:4326"/>
* // <Request maximumResponses="26" methodName="GeocodeRequest" requestID="uid1349081498314_388" version="1.2">
* // < (ref. LocationUtilityService ou vide) />
* // </Request>
* // </XLS>
*
*
* @constructor
* @alias Gp.Formats.XLS
* @param {Object} options - options du constructeur
* @param {Object} options.srsName - identifiant du Systeme de Coordonnees
* @param {String} options.maximumResponses - nombre de reponses max d'une requete
* @param {Function} options.onsuccess - function callback success (TODO)
* @param {Function} options.onerror - function callback error (TODO)
*
* @private
*/
function XLS (options) {
this.logger = Logger.getLogger();
this.logger.trace("[Constructeur XLS()]");
if (!(this instanceof XLS)) {
throw new TypeError("XLS constructor cannot be called as a function.");
}
// options par defaut
this.options = {
srsName : "EPSG:4326",
maximumResponses : 25
};
// et on ajoute les options en paramètre aux options par défaut
for (var opt in options) {
if (options.hasOwnProperty(opt)) {
if (options[opt]) {
this.options[opt] = options[opt];
}
}
}
}
/**
* Version
*/
XLS.VERSION = "1.2";
XLS.prototype = {
/**
* @lends module:XLS#
*/
/**
* request (out)
* @type {String}
*/
requestString : null,
/**
* namespace
* Surcharge les balises XLS d'un prefixe.
* Par defaut, false
* @type {Boolean}
*/
namespace : false,
/**
* Objet Service
* LocationUtilityService ou RouteService
* @type {AbstractService}
*/
oService : null,
/**
* Constructeur (alias)
*/
constructor : XLS,
/**
* Template de la requête.
* substitution des valeurs suivantes :
* __VERSION__, __NAMESPACE__, __SCHEMALOCATION__
* __REQUESTHEADER__, __REQUEST__
*/
template : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<XLS version=\"__VERSION__\"\n" +
"__NAMESPACE__ \n" +
"__SCHEMALOCATION__>\n" +
"__REQUESTHEADER__\n" +
"__REQUEST__\n" +
"</XLS>\n",
/**
* Namespace par defaut.
*
* @returns {String} namespace
*/
namespaceByDefault : function () {
var ns = [
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
"xmlns:xls=\"http://www.opengis.net/xls\"",
"xmlns:gml=\"http://www.opengis.net/gml\""
];
return ns.join(" ");
},
/**
* Schemalocation par defaut
*
* @returns {String} schemaLocation
*/
schemaLocationByDefault : function () {
return "xsi:schemaLocation=\"http://www.opengis.net/xls http://schemas.opengis.net/ols/1.2/olsAll.xsd\"";
},
/**
* Setter Service
* Ajout d'un objet de type LocationUtilityService (LUS) ou RouteService
*
* @param {Object} oService - GeoceodeRequest / ReverseGeocodeRequest ou RouteRequest
*/
setService : function (oService) {
if (!oService) {
this.logger.trace("L'objet de type Service XSL n'est pas encore defini !?");
return;
}
if (oService instanceof AbstractService) {
this.oService = oService;
} else {
this.logger.error("L'objet n'est pas du type 'LocationUtilityService' ou 'RouteService' !?");
}
},
/**
* Getter Service
* Retourne un objet de type LocationUtilityService (LUS) ou RouteService
* ex. GeoceodeRequest / ReverseGeocodeRequest ou RouteRequest
*
* @returns {Object} service (LocationUtilityService|RouteService)
*/
getService : function () {
return this.oService;
}
};
/**
* Ajout d'un prefixe de namespace
*
* @todo impl. l'ajout de namespace
* @param {Object} ns - ex. {key:xls, url:http://www.opengis.net/xls}
* @param {String} request - requête
* @returns {String} requête
*/
XLS.prototype.addNamespace = function (ns, request) {
// INFO
// on recherche la clef dans les namespaces par defaut.
// si la clef n'existe pas dans les namespaceByDefault (), on l'ajoute.
// on surcharge toutes les balises, ex. XLS -> xls:XLS
// sauf celles qui sont déjà prefixées !
var keyNS = ns.key;
// var urlNS = ns.url; // TODO not yet implemented !
// recherche la clef dans les namespaces par defaut
var bFound = false;
var allNS = this.namespaceByDefault().split(" ");
for (var index = 0; index < allNS.length; index++) {
var element = allNS[index];
var map = element.split("=");
var key = map[0];
// var url = map[1]; // TODO not yet implemented !
if (key === "xmlns:" + keyNS) {
bFound = true;
break;
}
}
// TODO
// si on a une nouvelle clef, on l'ajoute...
if (!bFound) {
this.logger.warn("L'ajout d'un nouvel namespace n'est pas encore implémenté !");
return request;
}
// surcharge toutes les balises
var regex;
var subst;
// regex balise ouvrante
regex = /<(\w+[\s>])/g;
subst = "<" + keyNS + ":$1";
request = request.replace(regex, subst);
// regex balise fermante
regex = /<\/(\w+[\s>])/g;
subst = "</" + keyNS + ":$1";
request = request.replace(regex, subst);
this.logger.trace("namespace", request);
return request;
};
/**
* Construction de la requête
* @returns {String} requête
*/
XLS.prototype.build = function () {
// out ->
// <XLS xmlns="http://www.opengis.net/xls" version="1.2">
// <RequestHeader srsName="epsg:4326"/>
// <Request maximumResponses="26" methodName="GeocodeRequest" requestID="uid1349081498314_388" version="1.2">
// < (ref. LocationUtilityService ou vide) />
// </Request>
// </XLS>
// as t on un objet de type Service XLS à disposition ?
var bService = !!this.getService();
var template = "";
template = this.template;
template = template.replace(/__VERSION__/g, XLS.VERSION);
template = template.replace(/__NAMESPACE__/g, this.namespaceByDefault);
template = template.replace(/__SCHEMALOCATION__/g, this.schemaLocationByDefault);
// header
var oHeader = new RequestHeader({
srsName : this.options.srsName
});
template = template.replace(/__REQUESTHEADER__/g, oHeader.toString());
// request
var oRequest = new Request({
maximumResponses : this.options.maximumResponses,
version : XLS.VERSION, // FIXME même version ?
methodName : bService ? this.getService().CLASSTYPE : null
});
template = template.replace(/__REQUEST__/g, oRequest.toString());
// objet lus ou route
if (bService) { // INFO : clef __REQUESTSERVICE__ dispo dans l'objet 'Request'
template = template.replace(/<!-- __REQUESTSERVICE__ -->/g, this.getService().toString());
}
if (!template) {
this.logger.warn("traduction tmpl : empty request !?");
return;
}
// ajout d'un namespace
if (this.namespace) {
// ajout de xls par defaut
template = this.addNamespace({
key : "xls",
url : "http://www.opengis.net/xls"
}, template);
}
this.requestString = template;
this.logger.trace("traduction tmpl", template);
// on retourne qqchose !
return this.requestString;
};
export default XLS;