Source: api/WmsMapService.js

Retour à la documentation
define([
        'dojo/_base/declare',
        'dojo/_base/array',
        'dojo/_base/lang',
        'spw/api/MapService',
        'esri/layers/WMSLayer',
        'esri/layers/WMSLayerInfo',
        'esri/layers/ImageParameters',
        'esri/tasks/IdentifyTask',
        'esri/geometry/Extent',
        'esri/SpatialReference',
        'esri/request',
        'esri/geometry/screenUtils',
        'dojo/_base/kernel',
        'spw/api/GeometryConverter',
        'esri/graphic',
        'spw/api/ProjectionManager',
        'esri/config',
        "dojo/Deferred"
    ],
    function(declare, array, lang, MapService, WMSLayer, WMSLayerInfo, ImageParameters, IdentifyTask,
             Extent, SpatialReference, esriRequest, screenUtils, f, GeometryConverter, Graphic,
             ProjectionManager, esriConfig, Deferred) {

        var oldGetCapabilities = WMSLayer.prototype._getCapabilities;
        var oldParseCapabilities = WMSLayer.prototype._getCapabilities;

        var getFullUrl = function(url) {
            var a = window.document.createElement('a');
            a.href = url;
            return a.cloneNode(false).href;
        };

        /*Patch WMSLayer to get scale from definition*/
        WMSLayer.prototype._getLayerInfo = function(a) {
            if (!a) return null;
            var b = new WMSLayerInfo;
            b.name = "";
            b.title = "";
            b.description = "";
            b.allExtents = [];
            b.spatialReferences = [];
            b.subLayers = [];
            if(!this._getTag("Layer", a)){
                //TODO ScaleHint min max
                b.maxScale = this._getTagValue("MinScaleDenominator", a) ? parseInt(this._getTagValue("MinScaleDenominator", a)) : 0;
                b.minScale = this._getTagValue("MaxScaleDenominator", a) ? parseInt(this._getTagValue("MaxScaleDenominator", a)) : 0;
            }
            var c = this._getTag("LatLonBoundingBox", a);
            c && (b.allExtents[0] = this._getExtent(c, 4326));
            var g = this._getTag("EX_GeographicBoundingBox",
                a),
                d;
            g && (d = new Extent(0, 0, 0, 0, new SpatialReference({
                wkid: 4326
            })), d.xmin = parseFloat(this._getTagValue("westBoundLongitude", g, 0)), d.ymin = parseFloat(this._getTagValue("southBoundLatitude", g, 0)), d.xmax = parseFloat(this._getTagValue("eastBoundLongitude", g, 0)), d.ymax = parseFloat(this._getTagValue("northBoundLatitude", g, 0)), b.allExtents[0] = d);
            !c && !g && (d = new Extent(-180, -90, 180, 90, new SpatialReference({
                wkid: 4326
            })), b.allExtents[0] = d);
            b.extent = b.allExtents[0];
            var f = -1 < array.indexOf(["1.0.0", "1.1.0", "1.1.1"], this.version) ? "SRS" : "CRS";
            array.forEach(a.childNodes,
                function(a) {
                    if ("Name" == a.nodeName) b.name = (a.text ? a.text : a.textContent) || "";
                    else if ("Title" == a.nodeName) b.title = (a.text ? a.text : a.textContent) || "";
                    else if ("Abstract" == a.nodeName) b.description = (a.text ? a.text : a.textContent) || "";
                    else if ("BoundingBox" == a.nodeName) {
                        var c = a.getAttribute(f);
                        c && 0 === c.indexOf("EPSG:") ? (c = parseInt(c.substring(5), 10), 0 !== c && !isNaN(c) && (a = "1.3.0" == this.version ? this._getExtent(a, c, this._useLatLong(c)) : this._getExtent(a, c), b.allExtents[c] = a, b.extent || (b.extent = a))) : c && 0 === c.indexOf("CRS:") ?
                            (c = parseInt(c.substring(4), 10), 0 !== c && !isNaN(c) && (this._CRS_TO_EPSG[c] && (c = this._CRS_TO_EPSG[c]), b.allExtents[c] = this._getExtent(a, c))) : (c = parseInt(c, 10), 0 !== c && !isNaN(c) && (b.allExtents[c] = this._getExtent(a, c)))
                    } else if (a.nodeName == f) a = (a.text ? a.text : a.textContent).split(" "), array.forEach(a, function(a) {
                        a = -1 < a.indexOf(":") ? parseInt(a.split(":")[1], 10) : parseInt(a, 10);
                        0 !== a && !isNaN(a) && (this._CRS_TO_EPSG[a] && (a = this._CRS_TO_EPSG[a]), -1 == array.indexOf(b.spatialReferences, a) && b.spatialReferences.push(a))
                    }, this);
                    else if ("Style" == a.nodeName) {
                        /*b.legends = [
                        {
                            "label": "Limite de bassin fluvial",
                            "url": "6599e5f863bf0cf5b38419be0432a598",
                            "imageData": "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAElJREFUOI1jYWBgYAhc8P8/AxXA+gRGRhZqGcbAAHEYC7UMgwHaG7g+gZGRFAPQg2wIennUwFEDh6WBlBZnQ8DL6xMYGalZBQAAbicWLzJpyqMAAAAASUVORK5CYII=",
                            "contentType": "image/png",
                            "height": 20,
                            "width": 20
                           }]*/
                        var titleTag = this._getTag("Title", a) ? this._getTag("Title", a).textContent : this._getTag("Name", a).textContent;
                        var styleName = this._getTag("Name", a).textContent;
                        var width, height;
                        if (a = this._getTag("LegendURL", a)){
                            width = a.getAttribute("width");
                            height = a.getAttribute("height");
                            if (a = this._getTag("OnlineResource", a)){
                                b.legendURL = a.getAttribute("xlink:href")
                            }
                        }
                        if(!b.legends){
                            b.legends = [];
                        }
                        b.legends.push({
                            "styleName": styleName,
                            "label": titleTag,
                            "url": b.legendURL + "&legend_options=forceLabels:on",
                            //"imageData": "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAElJREFUOI1jYWBgYAhc8P8/AxXA+gRGRhZqGcbAAHEYC7UMgwHaG7g+gZGRFAPQg2wIennUwFEDh6WBlBZnQ8DL6xMYGalZBQAAbicWLzJpyqMAAAAASUVORK5CYII=",
                            "contentType": "image/png",
                            "height": height ? height : 20,
                            "width": width ? width : 20
                        });
                    } else "Layer" === a.nodeName && b.subLayers.push(this._getLayerInfo(a))
                }, this);
            b.title = b.title || b.name;
            b.id = b.id || b.name;
            b.parentLayerId = -1;
            return b
        };
        WMSLayer.prototype._getCapabilities = function() {
            var a = this._url.query ? this._url.query : {};
            a.SERVICE = "WMS";
            a.REQUEST = "GetCapabilities";
            this.version && (a.VERSION = this.version);
            var b = this._url.path + "?",
                c;
            for (c in a) a.hasOwnProperty(c) && (b += "?" == b.substring(b.length - 1, b.length) ? "" : "\x26", b += c +
                "\x3d" + a[c]);
            var domain = (/(http[s]?:)?\/\/([^\/]*)/.exec(b))[2];
            esriConfig.defaults.io.corsEnabledServers && esriConfig.defaults.io.corsEnabledServers.indexOf(domain) == -1 && esriConfig.defaults.io.corsEnabledServers.push(domain);
            esriRequest({
                url: b,
                handleAs: "text",
                headers: {
                    "Content-Type": null
                },
                load: this._parseCapabilities,
                error: function() {
                    if(esriConfig.defaults.io.corsEnabledServers) {
                        var idx = esriConfig.defaults.io.corsEnabledServers.indexOf(domain);
                        if(idx > -1) {
                            esriConfig.defaults.io.corsEnabledServers.splice(idx, 1);
                        }
                    }

                    esriRequest({
                        url: b,
                        handleAs: "text",
                        headers: {
                            "Content-Type": null
                        },
                        load: this._parseCapabilities,
                        error: this._getCapabilitiesError
                    }, {
                        //usePost: !1,
                        useProxy: true//(getFullUrl(b).indexOf(window.location.hostname) < 0) // même les services WMS arcgis ne fonctionne pas sans le proxy...
                    })
                    //this._getCapabilitiesError(arguments);
                }.bind(this)
            }, {
                //usePost: !1,
                useProxy: false//(getFullUrl(b).indexOf(window.location.hostname) < 0) // même les services WMS arcgis ne fonctionne pas sans le proxy...
            })
        };

        var toXML = function(text){
            if(window.ActiveXObject)
            {
                var doc=new ActiveXObject('Microsoft.XMLDOM');
                doc.async='false';
                doc.loadXML(text);
            }
            else
            {
                var parser=new DOMParser();
                var doc=parser.parseFromString(text,'text/xml');
            }
            return doc;
        };

        WMSLayer.prototype._parseCapabilities = function(a) {
            if (a) {
                a = toXML(a);
                this.version = this._getAttributeValue("WMS_Capabilities", "version", a, null );
                this.version || (this.version = this._getAttributeValue("WMT_MS_Capabilities", "version", a, "1.3.0"));
                var b = this._getTag("Service", a);
                this.title = this._getTagValue("Title", b, "");
                this.title || (this.title = this._getTagValue("Name", b, ""));
                this.copyright = this._getTagValue("AccessConstraints",
                    b, "");
                this.description = this._getTagValue("Abstract", b, "");
                this.maxWidth = parseInt(this._getTagValue("MaxWidth", b, 5E3), 10);
                this.maxHeight = parseInt(this._getTagValue("MaxHeight", b, 5E3), 10);
                this.mapName = this._getTagValue("Title", a);
                if (b = this._getTag("Layer", a)) {
                    var c = this._getLayerInfo(b)
                        , g = 0
                        , d = null
                        , b = this._getTag("Capability", a);
                    array.forEach(b.childNodes, function(a) {
                        "Layer" == a.nodeName && (0 === g ? d = a : (1 === g && c.name && (c.name = "",
                            c.subLayers = [],
                            c.subLayers.push(this._getLayerInfo(d))),
                            c.subLayers.push(this._getLayerInfo(a))),
                            g++);
                        var fi = null;
                        if("Request" == a.nodeName && (fi = this._getTag("GetFeatureInfo", a))){
                            this.getFeatureInfoFormats = [];
                            array.forEach(fi.childNodes, function(n){ n.nodeName === "Format" && this.getFeatureInfoFormats.push(n.textContent); }, this);
                        }
                    }, this);
                    if (c) {
                        this.layerInfos =
                            c.subLayers;
                        if (!this.layerInfos || 0 === this.layerInfos.length)
                            this.layerInfos = [c];
                        this.extent = c.extent;
                        this.extent || (c.extent = new Extent(this.layerInfos[0].extent.toJson()),
                            this.extent = c.extent);
                        this.allExtents = c.allExtents;
                        if (!this.allExtents || !this.allExtents.length)
                            c.allExtents = [],
                                array.forEach(this.layerInfos[0].allExtents, function(a, b) {
                                    a && (c.allExtents[b] = new Extent(a.toJson()))
                                }),
                                this.allExtents = c.allExtents;
                        this.spatialReferences = c.spatialReferences;
                        if (!this.spatialReferences.length && 0 < this.layerInfos.length)
                            for (b =
                                     0; b < this.layerInfos.length; b++) {
                                var s = this.layerInfos[b];
                                this.spatialReferences = this.layerInfos[0].spatialReferences;
                                if (this.spatialReferences.length)
                                    break;
                                if (s.subLayers && 0 < s.subLayers.length) {
                                    var h;
                                    for (h = 0; h < s.subLayers.length && !(this.spatialReferences = s.subLayers[h].spatialReferences,
                                        this.spatialReferences.length); h++)
                                        ;
                                }
                                if (this.spatialReferences.length)
                                    break
                            }
                    }
                    this.getMapURL = this._getCapabilitiesURL;
                    if ((b = f.query("DCPType", this._getTag("GetMap", a))) && 0 < b.length)
                        if ((b = f.query("HTTP", b[0])) && 0 < b.length)
                            if ((b =
                                f.query("Get", b[0])) && 0 < b.length)
                                if (b = this._getAttributeValue("OnlineResource", "xlink:href", b[0], null ))
                                    b.indexOf("\x26") == b.length - 1 && (b = b.substring(0, b.length - 1)),
                                        this.getMapURL = this._stripParameters(b, ["service", "request"]);
                    this.getMapFormats = [];
                    0 === f.query("Operation", a).length ? array.forEach(f.query("Format", this._getTag("GetMap", a)), function(a) {
                        this.getMapFormats.push(a.text ? a.text : a.textContent)
                    }, this) : array.forEach(f.query("Operation", a), function(a) {
                        "GetMap" == a.getAttribute("name") && array.forEach(f.query("Format",
                            a), function(a) {
                            this.getMapFormats.push(a.text ? a.text : a.textContent)
                        }, this)
                    }, this);
                    array.some(this.getMapFormats, function(a) {
                        return -1 < a.indexOf(this.imageFormat)
                    }, this) || (this.imageFormat = this.getMapFormats[0]);
                    this._initLayer()
                } else
                    this._errorHandler(Error("esri.layers.WMSLayer: Response does not contain any layers."))
            } else
                this._errorHandler(Error("GetCapabilities request for " + this._getCapabilitiesURL + " failed. (Response is null.)"))
        };

        /**
         * @class spw.api.WmsMapService
         * @classdesc Service du viewer correspondant à un WMSLayer d'ESRI
         * @extends {spw.api.MapService}
         */
        var WmsMapService = declare('spw.api.WmsMapService', [MapService], /** @lends spw.api.WmsMapService.prototype */ {

            wmsParameters: null,

            constructor: function() {
                this._propertiesToKeep.push('wmsParameters');
                this._propertiesToKeep.push('copyright');

                this.wmsParameters = this.wmsParameters || {};
            },

            /**
             * Crée le layer Esri sur base de la configuration du MapService.
             */
            createMapLayer: function() {
                if(this.get('url').indexOf('|') > -1) {
                    var urlAndLayers = this.get('url').split('|');
                    this.set('url', urlAndLayers[0]);
                    this.get('wmsParameters').visibleLayers = urlAndLayers[1].split(",");
                }
                this.layer = this._createWmsLayer({
                    url: this.get('url'),
                    wmsParameters: this.get('wmsParameters'),
                    copyright: this.copyright
                });

                if(this.get('wmsParameters') && this.get('wmsParameters').resourcesInfo) {
                    // there isn't an event when the layer is loaded. Then we assume that it is loaded directly.
                    this.set('loaded', true);

                    this.emit(this.events.MapServiceLoaded, this);

                    this.layerLoaded({
                        layer: this.layer
                    });
                }
                else {
                    this.inherited(arguments);
                }
            },

            /**
             * Rafraichit la visibilité des couches du services.
             */
            refreshLayersVisibility: function() {
                if(this.get('layer') && this.get('layer').setVisibleLayers /*&& !this.get('layer').isInstanceOf(WMSLayer)*/){
                    var visibleLayersIds = [];

                    for (var key in this.mapServiceLayers) {
                        var layer = this.mapServiceLayers[key];
                        if (layer.visible && this.mapServiceLayers[key].get('subLayers').length == 0 && this.allParentsVisible(layer)) {
                            visibleLayersIds.push(layer.get('layerId'));
                        }
                    }

                    //if(visibleLayersIds.length > 0){
                    this.effectivelyUpdateLayersVisibility(visibleLayersIds);
                    // this.get('layer').setVisibleLayers(visibleLayersIds);
                    //}
                    /* les wmslayer ne prennent pas en charge le -1 :/
                    else {
                        this.get('layer').setVisibleLayers([-1]);
                    }*/

                    this.emit(this.events.MapServiceLayersVisibilityChanged, this);

                    if(this.spwMap){
                        this.spwMap.mapServiceVisibilityChanged(this);
                    }
                }
            },

            allParentsVisible: function(layer) {
                var par = layer.parentLayer;

                while(par) {
                    if(!par.visible) return false;
                    par = par.parentLayer;
                }

                return true;
            },

            _createWmsLayer: function(config){
                // The default behavior of the WMSLayer is to execute a WMS GetCapabilities request which requires using a proxy page. When a resourceInfo object is specified the GetCapabilities request is not executed.
                if(config.wmsParameters.resourceInfo) {
                    var layerInfos = config.wmsParameters.resourceInfo.layerInfos;

                    array.forEach(layerInfos, function(layerInfo, idx) {
                        lang.mixin(layerInfos[idx], new WMSLayerInfo(layerInfo));
                    });

                    if(config.wmsParameters.resourceInfo.extent){
                        var conf = config.wmsParameters.resourceInfo.extent;
                        config.wmsParameters.resourceInfo.extent = new Extent(conf.xmin, conf.ymin, conf.xmax, conf.ymax,
                            new SpatialReference({wkid:conf.wkid}));
                    }
                }

                config.wmsParameters.id = this.get('serviceId');

                var layer = new WMSLayer(config.url, config.wmsParameters);

                if(config.copyright) {
                    layer.copyright = config.copyright;
                }

                array.forEach(layer.layerInfos, lang.hitch(this, function(layerInfo) {
                    lang.mixin(layerInfo, {
                        id: layerInfo.name,
                        parentLayerId: -1,
                        defaultVisibility: layer.visibleLayers && layer.visibleLayers.indexOf(layerInfo.name) > -1,
                        minScale: 0,
                        maxScale: 0
                    });
                }));

                return layer;
            },

            getLayerExtent: function(layerId) {
                var def = new Deferred();
                def.resolve(this.layer.fullExtent);
                return def;
            },

            /**
             * Génère un nombre aléatoire entre 0 et 10000
             * @return un GUID
             */
            s4: function() {
                return Math.floor((1 + Math.random()) * 0x10000)
                    .toString(16)
                    .substring(1);
            },

            /**
             * Génère un GUID
             * @return le GUID généré
             */
            guid: function() {
                return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' +
                    this.s4() + '-' + this.s4() + this.s4() + this.s4();
            },

            /**
             * Prépare les couches du service WMS
             * @param les informations de la couche
             * @param le parent de la couche
             */
            prepareWMSLayerInfo: function(layersInfos, parent){
                if (this.wmsParameters.resourceInfo == null && this.wmsParameters.visibleLayers == null && parent == null) {
                    this.layer.setVisibleLayers(array.map(layersInfos, function(info) { return info.name; }));
                }

                array.forEach(layersInfos, lang.hitch(this, function(layerInfo) {

                    var layerToMix = {
                        id: layerInfo.name ? layerInfo.name : this.guid() + "",
                        parentLayerId: parent ? parent.id : -1,
                        defaultVisibility: this.layer.visibleLayers && this.layer.visibleLayers.indexOf(layerInfo.name) > -1,
                        minScale: layerInfo.minScale ? layerInfo.minScale : 0,
                        maxScale: layerInfo.maxScale ? layerInfo.maxScale : 0,
                        name: layerInfo.title ? layerInfo.title : layerInfo.name
                    }
                    lang.mixin(layerInfo, layerToMix);

                    this._mergeLayerInfo(layerInfo);

                    if(layerInfo.subLayers && layerInfo.subLayers.length > 0){
                        this.prepareWMSLayerInfo(layerInfo.subLayers, layerInfo);
                    }
                }));

            },

            /**
             * Effectue un carrottage sur le service
             * @param options les options d'identification
             * @param success fonction à appeler en cas de succès
             * @param error fonction à appeler en cas d'erreur
             */
            identify: function(options, success, error) {
                var map = this.spwMap ? this.spwMap.esriMap : this.layer._map;

                if (!options.mapPoint){
                    error && error(this);
                    return;
                }

                if (options.mapPoint && options.mapPoint.spatialReference) {
                    options.mapPoint = ProjectionManager.getInstance().transform(options.mapPoint.spatialReference.wkid, map.spatialReference.wkid, options.mapPoint);
                }

                var pt = screenUtils.toScreenPoint(map.extent, map.width, map.height, options.mapPoint);
                var format = (this.layer.getFeatureInfoFormats && this.layer.getFeatureInfoFormats.indexOf("application/geojson") != -1) ? "application/geojson" : ((this.layer.getFeatureInfoFormats && this.layer.getFeatureInfoFormats.indexOf("application/json-deprecated") != -1) ? "application/json" : "text/xml");

                var params = {
                    //REQUEST=GetFeatureInfo    R   Request name.
                    REQUEST: "GetFeatureInfo",
                    //VERSION=version*  R   Request version. Valid values are 1.0.0, 1.1.0, or 1.1.1.
                    VERSION: this.get('layer').version,
                    //SRS=EPSG:id_code* R   Spatial Reference System (SRS) identifier the map is returned in. Identifiers correspond to coordinate system ID codes found in the ArcXML Programmer’s Reference Guide.
                    SRS: "EPSG:" + map.spatialReference.wkid,
                    CRS: "EPSG:" + map.spatialReference.wkid,
                    //BBOX=minx,miny,maxx,maxy* R   Bounding box corners (lower left, upper right). Values must be in the units of the specified SRS.
                    BBOX: map.extent.xmin + "," + map.extent.ymin + "," + map.extent.xmax + "," + map.extent.ymax,
                    //WIDTH=output_width*   R   Width in pixels of resulting map image.
                    WIDTH: map.width,
                    //HEIGHT=output_height* R   Height in pixels of resulting map image.
                    HEIGHT: map.height,
                    //QUERY_LAYERS=layer_list   R   Comma-separated list of one or more map layers to be queried. Values in the list correspond to the layer <name> values in the Capabilities file. This name corresponds to the layer id in ArcXML.
                    //QUERY_LAYERS: options.layerIds.join(','),
                    //X=pixel_column    R   X coordinate in pixels of feature measured from upper left corner of the map.
                    X: Math.round(pt.x,0),
                    //Y=pixel_row
                    Y: Math.round(pt.y,0),
                    INFO_FORMAT: format,
                    FEATURE_COUNT: 20
                };

                var identifiableLayers = new Array();

                for(key in this.mapServiceLayers) {
                    if(this.mapServiceLayers[key].get('identifiable')
                        && this.mapServiceLayers[key].get('subLayers').length == 0
                        && this.mapServiceLayers[key].isVisible()
                        && this.mapServiceLayers[key].visibleAtScale(options.spwViewer ? options.spwViewer.get('spwMap').getCurrentScale() : this.spwMap.getCurrentScale())) {

                        identifiableLayers.push(this.mapServiceLayers[key].get('layerId'));
                    }
                }

                params.QUERY_LAYERS = identifiableLayers.join(',');
                params.LAYERS = identifiableLayers.join(',');

                esriRequest({
                    url: this.get('url'),
                    content: params,
                    handleAs: ((format === "application/geojson" || format === "application/json") ? "json" : "xml")
                }/*, {useProxy: true}*/).then(lang.hitch(this, function(data){
                    var cData = [];
                    if(format === "application/geojson" || format === "application/json"){
                        array.forEach(data.features, function(feature){
                            cData.push({
                                layerId: (feature.layerName ? feature.layerName : (feature.id && feature.id.indexOf(".") > -1 ? feature.id.split(".")[0] : this.layer.layerInfos[0].id)),
                                data: feature.properties,
                                feature: feature.geometry ? new Graphic(GeometryConverter.geoJSONToEsri(feature.geometry), null, feature.properties) : null
                            });
                        }, this);
                    } else {
                        if(data && data.childNodes && data.childNodes.length > 0){
                            if(data.childNodes[0].tagName === "FeatureInfoResponse"){
                                var fields = data.childNodes[0].getElementsByTagName("FIELDS");
                                array.forEach(fields, function(f){
                                    var d = {};
                                    array.forEach(f.attributes, function(a){
                                        d[a.name] = a.value;
                                    });
                                    cData.push(d);
                                });
                            } else if (data.childNodes[0].tagName === "wfs:FeatureCollection"){
                                array.forEach(data.childNodes[0].childNodes, function(n){
                                    if(n.nodeName === "gml:featureMember"){
                                        var properties = {};
                                        array.forEach(n.childNodes[0].childNodes, function(attr){
                                            if(attr.childNodes.length === 1 && attr.childNodes[0].nodeType === 3){
                                                properties[attr.nodeName.indexOf(":") > -1 ? attr.nodeName.split(":")[1] : attr.nodeName] = attr.textContent;
                                            }
                                        }, this);

                                        cData.push({
                                            layerId: (this.layer.layerInfos[0].id.indexOf(":") == -1) ? n.childNodes[0].nodeName.split(":")[1] : n.childNodes[0].nodeName,
                                            data: properties,
                                            feature: null
                                        });
                                    }
                                }, this);

                            } else {
                                console.error("Type de réponse GetFeatureInfo non supporté", data);
                            }
                        }
                    }
                    success(cData, this, cData);
                }), lang.hitch(this, function(err) {
                    error(err);
                }));
            },

            /**
             * Méthode appelée au chargement du service
             */
            layerLoaded: function(loadedEvent) {
                if(this.layers && this.layers.length > 0){
                    var newLayerInfos = [];
                    array.forEach(this.layers, lang.hitch(this, function(l){
                        array.forEach(this.layer.layerInfos, function(li){
                            if(l.layerId === li.name) {
                                lang.mixin(li, l);
                                newLayerInfos.push(li);
                            }
                        });
                    }));
                    if(newLayerInfos.length > 0){
                        this.layer.layerInfos = newLayerInfos;
                    }
                }

                if (this.layer.spatialReferences && this.layer.spatialReferences.indexOf(this.spwMap.spwViewer.get('spatialReference').wkid) < 0) {
                    this.layerError('Ce service n\'est pas compatible avec le système de projection du fond de plan actuel.');
                    return;
                }

                this.prepareWMSLayerInfo(loadedEvent.layer.layerInfos, null);


                if(!this.layer.visibleLayers || this.layer.visibleLayers.length === 0){
                    this.layer.setVisibleLayers(array.map(this.get('mapServiceLayers'), function(o){
                        return o.layerId;
                    }));
                }

                this._afterLayerLoaded();
            },

            /**
             * Méthode appelée après le chargement du fond de plan.
             */
            baseMapLayerLoaded: function(loadedEvent) {
                if(this.layers && this.layers.length > 0){
                    var newLayerInfos = [];
                    array.forEach(this.layers, lang.hitch(this, function(l){
                        array.forEach(this.layer.layerInfos, function(li){
                            if(l.layerId === li.name) {
                                lang.mixin(li, l);
                                newLayerInfos.push(li);
                            }
                        });
                    }));
                    if(newLayerInfos.length > 0){
                        this.layer.layerInfos = newLayerInfos;
                    }
                }

                if (this.layer.spatialReferences && this.layer.spatialReferences.indexOf(this.spwMap.spwViewer.get('spatialReference').wkid) < 0) {
                    this.layerError('Ce service n\'est pas compatible avec le système de projection du fond de plan actuel.');
                    return;
                }

                this.prepareWMSLayerInfo(loadedEvent.layer.layerInfos, null);

                if(!this.layer.visibleLayers || this.layer.visibleLayers.length === 0){
                    this.layer.setVisibleLayers(array.map(this.get('mapServiceLayers'), function(o){
                        return o.layerId;
                    }));
                }

                this.inherited(arguments);
            },

            /**
             * Charge la légende du service.
             */
            loadLegend: function() {
                this._requestLegend(this.get('url'))
            },

            _requestLegend: function(legendUrl) {
                var requestSublayersLegend =  function(layer){
                    if(layer.subLayers && layer.subLayers.length > 0){
                        array.forEach(layer.subLayers, lang.hitch(this, function(sub){
                            lang.hitch(this, requestSublayersLegend(sub));
                            this.mapServiceLayers[sub.id].set('legends', sub.legends);
                        }))
                    }
                    if(layer.id in this.mapServiceLayers){
                        this.mapServiceLayers[layer.id].set('legends', layer.legends);
                    }
                }.bind(this);
                array.forEach(this.layer.layerInfos, lang.hitch(this, function(li){
                    lang.hitch(this, requestSublayersLegend(li));

                    //WMS can have multiple style (= legends), only default is supported, index = 0
                    if(li.legends && li.legends.length > 1){
                        li.legends = [li.legends[0]];
                    }
                    this.mapServiceLayers[li.id].set('legends', li.legends);
                }));
                this.set('legendLoaded', true);
                this.emit(this.events.MapServiceLegendLoaded, this);
            }

        });

        return WmsMapService;

    });