Source: api/ConfigLoader.js

Retour à la documentation
define(["dojo/_base/declare", "dojo/DeferredList", "dojo/_base/config", "dojo/topic", "dojo/request/xhr",
        "dojo/_base/lang", "spw/api/MessageManager", "dojo/_base/array", "spw/api/Utils","dojo/i18n!./nls/ConfigLoader",
        "spw/api/StateManager", "dojo/_base/window", "spw/api/ProjectionManager", "dojo/sniff", "dojo/dom-class"],
        function (declare, DeferredList, config, topic, xhr, lang, MessageManager, array, Utils,
                labels, StateManager, win, ProjectionManager, has, domClass) {

    if (!String.prototype.endsWith) {
        String.prototype.endsWith = function(searchString, position) {
            var subjectString = this.toString();
            if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
                position = subjectString.length;
            }
            position -= searchString.length;
            var lastIndex = subjectString.lastIndexOf(searchString, position);
            return lastIndex !== -1 && lastIndex === position;
        };
    }

    var ConfigLoader = null;
    ConfigLoader = declare(null, /** @lends spw.api.ConfigLoader.prototype */{

        /**
         * Url de base commune des fichiers de configuration.
         * @type string
         */
        configBaseUrl: null,

        /**
         * Variable contenant la configuration des contextes.
         * @type Object
         */
        _contextConfig: null,

        /**
         * Variable contenant la configuration du viewer.
         * @type Object
         */
        _viewerConfig: null,

        /**
         * Variable contenant la configuration des widgets.
         * @type Object
         */
        _widgetsConfig: null,

        /**
         * Variable contenant la configuration des fonds de plan.
         * @type Object
         */
        _baseMapConfig: null,

        /**
         * Variable contenant la configuration du catalogue.
         * @type Object
         */
        _catalogConfig: null,

        /**
         * Objet dictionnaire contenant le mapping clé/valeur des objets de configuration.
         * @property viewer
         * @property baseMap
         * @property catalog
         * @property widget
         * @property context
         * @type Object
         */
        _dictionnary: null,

        labels: labels,

        currentContext: 'default',

        placementNode: null,

        defaultBaseMaps: {
            "ORTHO": {
                "baseMapName": "Vue aérienne",
                "baseMapId": "ORTHO",
                "services": [{
                    "serviceId": "b3",
                    "label": "2009 / 2010",
                    "type": "AGS_TILED",
                    "url": "//geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_LAST/MapServer"
                }],
                "activateTransparency": true,
                "alpha": 100,
                "activateBlackAndWhite": "filter",
                "metadataUrl": "/catalogue/385d8e9c-2c01-41c7-a38c-911f746c8877.html",
                "blackAndWhiteByDefault": false,
                "optionalServices": [],
                "selected": false,
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/FondPhoto_100.png"
            },
            "ANNOTATION": {
                "serviceId": "b31",
                "label": "Annotation",
                "type": "AGS_TILED",
                "url": "//geoservices.wallonie.be/arcgis/rest/services/DONNEES_BASE/FOND_PLAN_ANNOTATIONS_RW/MapServer",
                "checked": true
            },
            "RELIEF": {
                "label": "Relief",
                "type": "AGS_DYNAMIC",
                "url": "//geoservices.wallonie.be/arcgis/rest/services/RELIEF/WALLONIE_MNS_2013_2014_HILLSHADE/MapServer",
                "alpha": 45,
                "checked": false
            },
            "ROUTES": {
                "label": "Réseau routier",
                "type": "AGS_DYNAMIC",
                "url": "//geoservices.wallonie.be/arcgis/rest/services/MOBILITE/RES_ROUTIER_REGIONAL/MapServer",
                "checked": false,
                "layers":[
                    {"layerId":0, "defaultVisibility": false},
                    {"layerId":1, "defaultVisibility": true},
                    {"layerId":2, "defaultVisibility": true},
                    {"layerId":3, "defaultVisibility": true}
                ]
            },
            "BATIMENTS": {
                "label": "Bâtiments",
                "type": "AGS_DYNAMIC",
                "url": "//geoservices.wallonie.be/arcgis/rest/services/TOPOGRAPHIE/PICC_VDIFF/MapServer",
                "imageFormat": "png32",
                "checked": true,
                "layers":[
                    {"layerId":0, "defaultVisibility": false},
                    {"layerId":1, "defaultVisibility": true},
                    {"layerId":2, "defaultVisibility": false},
                    {"layerId":3, "defaultVisibility": false},
                    {"layerId":4, "defaultVisibility": false},
                    {"layerId":5, "defaultVisibility": false},
                    {"layerId":6, "defaultVisibility": false},
                    {"layerId":7, "defaultVisibility": false},
                    {"layerId":8, "defaultVisibility": true},
                    {"layerId":9, "defaultVisibility": false},
                    {"layerId":10, "defaultVisibility": false},
                    {"layerId":11, "defaultVisibility": true},
                    {"layerId":12, "defaultVisibility": false},
                    {"layerId":13, "defaultVisibility": false},
                    {"layerId":14, "defaultVisibility": false},
                    {"layerId":15, "defaultVisibility": false},
                    {"layerId":16, "defaultVisibility": false},
                    {"layerId":17, "defaultVisibility": false},
                    {"layerId":18, "defaultVisibility": false},
                    {"layerId":19, "defaultVisibility": false},
                    {"layerId":20, "defaultVisibility": false},
                    {"layerId":21, "defaultVisibility": false},
                    {"layerId":22, "defaultVisibility": false},
                    {"layerId":23, "defaultVisibility": false},
                    {"layerId":24, "defaultVisibility": false},
                    {"layerId":25, "defaultVisibility": false},
                    {"layerId":26, "defaultVisibility": false},
                    {"layerId":27, "defaultVisibility": false}
                ]
            },
            "CARTOWEB": {
                "baseMapId": "CartoWeb",
                "baseMapName": "CartoWeb.be",
                "srid": 3812,
                "activateTransparency": true,
                "activateBlackAndWhite": "filter",
                "services": [{
                    "serviceId": "CartoWeb",
                    "label": "CartoWeb.be",
                    "type": "WMTS",
                    "resampling": true,
                    "url": "http://www.ngi.be/cartoweb",
                    "copyright": "<a href='http://www.ngi.be/FR/FR6.shtm' target='_blank'>IGN</a>",
                    "srid": 3812,
                    "wmtsParameters": {
                        "resampling": true
                    }
                }],
                "optionalServices": [],
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/IGN.png",
                "metadataUrl": "/catalogue/fa70cc95-83d9-476b-a88e-f38c4f6600da.html",
                "selected": false,
                "lods": [{"level":1,"levelValue":"1","scale":2000000,"resolution":529.1666,"startTileRow":0,"startTileCol":0,"endTileRow":16,"endTileCol":16},{"level":2,"levelValue":"2","scale":800000,"resolution":211.6666,"startTileRow":0,"startTileCol":0,"endTileRow":40,"endTileCol":40},{"level":3,"levelValue":"3","scale":500000,"resolution":132.2919312505292,"startTileRow":0,"startTileCol":0,"endTileRow":64,"endTileCol":64},{"level":4,"levelValue":"4","scale":250000,"resolution":66.1459656252646,"startTileRow":0,"startTileCol":0,"endTileRow":127,"endTileCol":127},{"level":5,"levelValue":"5","scale":100000,"resolution":26.458386250105836,"startTileRow":0,"startTileCol":0,"endTileRow":320,"endTileCol":320},{"level":6,"levelValue":"6","scale":50000,"resolution":13.229193125052918,"startTileRow":0,"startTileCol":0,"endTileRow":640,"endTileCol":640},{"level":7,"levelValue":"7","scale":25000,"resolution":6.614596562526459,"startTileRow":0,"startTileCol":0,"endTileRow":1279,"endTileCol":1279},{"level":8,"levelValue":"8","scale":10000,"resolution":2.6458386250105836,"startTileRow":0,"startTileCol":0,"endTileRow":3200,"endTileCol":3200},{"level":9,"levelValue":"9","scale":5000,"resolution":1.3229193125052918,"startTileRow":0,"startTileCol":0,"endTileRow":6400,"endTileCol":6400},{"level":10,"levelValue":"10","scale":2500,"resolution":0.6614596562526459,"startTileRow":0,"startTileCol":0,"endTileRow":12799,"endTileCol":12799}]
            },
            "OSM": {
                "baseMapId": "Osm",
                "baseMapName": "OpenStreetMap",
                "srid": 3857,
                "activateTransparency": true,
                "activateBlackAndWhite": "filter",
                "services": [{
                    "serviceId": "Osm",
                    "label": "OpenStreetMap",
                    "type": "OSM"
                }],
                "metadataUrl": "https://www.openstreetmap.org",
                "optionalServices": [],
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/OSM.png",
                "lods": [{"level":8,"resolution":611.49622628138,"scale":2311162.217155},{"level":9,"resolution":305.748113140558,"scale":1155581.108577},{"level":10,"resolution":152.874056570411,"scale":577790.554289},{"level":11,"resolution":76.4370282850732,"scale":288895.277144},{"level":12,"resolution":38.2185141425366,"scale":144447.638572},{"level":13,"resolution":19.1092570712683,"scale":72223.819286},{"level":14,"resolution":9.55462853563415,"scale":36111.909643},{"level":15,"resolution":4.77731426794937,"scale":18055.954822},{"level":16,"resolution":2.38865713397468,"scale":9027.977411},{"level":17,"resolution":1.19432856685505,"scale":4513.988705},{"level":18,"resolution":0.597164283559817,"scale":2256.994353},{"level":19,"resolution":0.298582141647617,"scale":1128.497176}]
            },
            "CIRCULATION": {
                "label": "Circulation",
                "type": "WEB_TILED",
                "srid": 3857,
                "url": "https://c.be-mobile.biz/d/public/BENELUX_20140901_0/3/LOS/${level}/${col}/${row}.png",
                "checked": false
            },
            "VOYAGEDANSLETEMPS": {
                "baseMapName": "Voyage dans le temps",
                "activateTransparency": true,
                "activateBlackAndWhite": false,
                "blackAndWhiteByDefault": false,
                "type": "TIMER",
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/FondVoyageTemps.png",
                "services": [
                    {
                        "serviceId": "FERRAIS_TIMER",
                        "ruleLabel": "1777",
                        "type": "AGS_DYNAMIC",
                        "url": "http://webgisdgo4.spw.wallonie.be/ArcGIS/rest/services/DGO4/FERRARIS/MapServer",
                        "description": "Cartes de Ferraris 1777",
                        "selected": true,
                        "metadataUrl": "/catalogue/b8b9e555-a4d1-49bf-940d-31bbbf7613fc.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTempsFerraris.png"
                    },
                    {
                        "serviceId": "VDML_TIMER",
                        "ruleLabel": "1850",
                        "type": "AGS_DYNAMIC",
                        "url": "http://webgisdgo4.spw.wallonie.be/ArcGIS/rest/services/DGO4/VDML/MapServer",
                        "description": "Carte Vandermaelen 1850",
                        "metadataUrl": "/catalogue/67ed5145-72be-499b-8a95-c94711f344f1.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTempsVDM.png"

                    },
                    {
                        "serviceId": "ORTHO_TIMER_1971",
                        "ruleLabel": "1971",
                        "type": "AGS_DYNAMIC",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_1971/MapServer",
                        "description": "Orthophotos 1971",
                        "metadataUrl": "/catalogue/3059d00d-9666-4a90-b606-88bbd861dd83.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps1971.png"
                    },
                    {
                        "serviceId": "ORTHO_TIMER_1994",
                        "ruleLabel": "1994-00",
                        "type": "AGS_DYNAMIC",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_1994_2000/MapServer",
                        "description": "Orthophotos 1994-2000",
                        "metadataUrl": "/catalogue/899d2df8-a16d-4798-acc4-19d3fd1a5e20.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps1994.png"
                    }, {
                        "serviceId": "ORTHO_TIMER_2006",
                        "ruleLabel": "2006-07",
                        "type": "AGS_DYNAMIC",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_2006_2007/MapServer",
                        "description": "Orthophotos 2006-2007",
                        "metadataUrl": "/catalogue/e26fe111-7d7d-434e-bca1-71f7b5d0e4fb.html" ,
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps2006.png"
                    },
                    {
                        "serviceId": "ORTHO_TIMER_2009",
                        "ruleLabel": "2009-10",
                        "type": "AGS_TILED",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_2009_2010/MapServer",
                        "description": "Orthophotos 2009-2010",
                        "metadataUrl": "/catalogue/034a86cd-3879-4ed5-8e56-28e301acc86b.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps2009.png"
                    }, {
                        "serviceId": "ORTHO_TIMER_2012",
                        "ruleLabel": "2012-13",
                        "type": "AGS_TILED",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_2012_2013/MapServer",
                        "description": "Orthophotos 2012-2013",
                        "metadataUrl": "/catalogue/f16124b7-41ed-42fe-9442-73b32708d60a.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps2012.png"
                    },
                    {
                        "serviceId": "ORTHO_TIMER_2015",
                        "ruleLabel": "2015",
                        "type": "AGS_TILED",
                        "url": "http://geoservices.wallonie.be/arcgis/rest/services/IMAGERIE/ORTHO_2015/MapServer",
                        "description": "Orthophotos 2015",
                        "metadataUrl": "/catalogue/e5e03556-80b2-4e80-86c6-6e70ae8de191.html",
                        "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/VoyageTemps2015.png"
                    }],
                "lods":[{"level":0,"resolution":396.87579375158754,"scale":1500000},{"level":1,"resolution":330.72982812632296,"scale":1250000},{"level":2,"resolution":264.5838625010584,"scale":1000000},{"level":3,"resolution":198.43789687579377,"scale":750000},{"level":4,"resolution":132.2919312505292,"scale":500000},{"level":5,"resolution":66.1459656252646,"scale":250000},{"level":6,"resolution":26.458386250105836,"scale":100000},{"level":7,"resolution":19.843789687579378,"scale":75000},{"level":8,"resolution":13.229193125052918,"scale":50000},{"level":9,"resolution":6.614596562526459,"scale":25000},{"level":10,"resolution":3.9687579375158752,"scale":15000},{"level":11,"resolution":2.6458386250105836,"scale":10000},{"level":12,"resolution":1.3229193125052918,"scale":5000},{"level":13,"resolution":0.6614596562526459,"scale":2500},{"level":14,"resolution":0.26458386250105836,"scale":1000},{"level":15,"resolution":0.13229193125052918,"scale":500},{"level":16,"resolution":0.06614596562526459,"scale":250}]
            },
            "PLAN": {
                "baseMapName": "Plan",
                "services": [{
                    "serviceId": "b1",
                    "label": "Fond de plan",
                    "type": "AGS_TILED",
                    "url": "//geoservices.wallonie.be/arcgis/rest/services/DONNEES_BASE/FOND_PLAN_CARTE_RW/MapServer",
                    "resampling": true
                }],
                "activateTransparency": true,
                "alpha": 100,
                "activateBlackAndWhite": "filter",
                "blackAndWhiteByDefault": false,
                "optionalServices": [],
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/FondCarte_100.png"
            },
            "GOOGLE": {
                "baseMapName": "Google",
                "baseMapId": "idGoogle",
                "activateTransparency": true,
                "srid": 3857,
                "services": [
                    {
                        "serviceId": "g1",
                        "label": "Google",
                        "type": "GMAP_LAYER",
                        "copyright":"<img src='images/Google_2015_logo.png' alt='logo_google' style='width: 57px; position: absolute; right: 5px; top: -25px;'/>Données cartographiques ©2016 Google",
                        "srid": 3857,
                        "proxyUrl": (require("dojo/_base/config").geoviewerApiUrl + "/proxygoogle.jsp")
                    }
                ],
                "lods": [{"level":0,"resolution":156543.033928,"scale":591657527.591555},{"level":1,"resolution":78271.5169639999,"scale":295828763.795777},{"level":2,"resolution":39135.7584820001,"scale":147914381.897889},{"level":3,"resolution":19567.8792409999,"scale":73957190.948944},{"level":4,"resolution":9783.93962049996,"scale":36978595.474472},{"level":5,"resolution":4891.96981024998,"scale":18489297.737236},{"level":6,"resolution":2445.98490512499,"scale":9244648.868618},{"level":7,"resolution":1222.99245256249,"scale":4622324.434309},{"level":8,"resolution":611.49622628138,"scale":2311162.217155},{"level":9,"resolution":305.748113140558,"scale":1155581.108577},{"level":10,"resolution":152.874056570411,"scale":577790.554289},{"level":11,"resolution":76.4370282850732,"scale":288895.277144},{"level":12,"resolution":38.2185141425366,"scale":144447.638572},{"level":13,"resolution":19.1092570712683,"scale":72223.819286},{"level":14,"resolution":9.55462853563415,"scale":36111.909643},{"level":15,"resolution":4.77731426794937,"scale":18055.954822},{"level":16,"resolution":2.38865713397468,"scale":9027.977411},{"level":17,"resolution":1.19432856685505,"scale":4513.988705},{"level":18,"resolution":0.597164283559817,"scale":2256.994353},{"level":19,"resolution":0.298582141647617,"scale":1128.497176},{"level":20,"resolution":0.149291070823808,"scale":564.248588}],
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/FondGoogle_100.png"
            },
            "AUCUN": {
                "baseMapName": "Aucun",
                "baseMapId": "IdNone",
                "activateTransparency": false,
                "services": [{
                    "serviceId": "b4",
                    "label": "LIMITE REGIONS",
                    "type": "AGS_DYNAMIC",
                    "url": "//geoservices.wallonie.be/arcgis/rest/services/IGN/LIMITE_REGION/MapServer"
                }],
                "imagePath": "http://geoportail.wallonie.be/files/GeoViewer/Main/images/galleryThumbnails/FondNone.png"
            }
        },

        /**
         * Le constructeur ne doit pas être appelé directement. ConfigLoader est une classe statique et doit être accédée via la méthode {@link spw.api.ConfigLoader.getInstance getInstance}.
         * @classdesc Charge et manipule les configurations du Viewer.
         * @constructs
         */
        constructor: function(config) {
            this._dictionnary = {};
            this.placementNode = config && config.placementNode ? config.placementNode : win.body();
            MessageManager.getInstance({placementNode: this.placementNode});
        },

        /**
         * Charge les configurations pour un contexte donné
         * @param {String} context le code du contexte à charger
         */
        load: function(context, opts) {
            opts = opts || {};

            if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Phone/i.test(navigator.userAgent)) {
                window.document.dojoClick = false; // pour faire fonctionner le click sur android notamment
                domClass.add(document.body, 'geoviewerMobile');
                if (!opts.noMobileSupport) {
                    if(/Mobile/i.test(navigator.userAgent) && !/ipad/i.test(navigator.userAgent)) { // phone
                        context = context + '_m';
                    }
                    else {
                        context = context + '_t';
                    }

                    this.backToNormal = true;
                }
            }

            this.currentContext = context;

            
            if(typeof(config.configBasePath) != 'undefined')
            {
                this.configBaseUrl = config.configBasePath;
                if(config.configBasePath[config.configBasePath.length-1] != '/'){
                    this.configBaseUrl = this.configBaseUrl + "/";
                }
            } 
            else if(typeof(config.configObjects) != 'undefined' 
            	&& typeof(config.viewerConfigPath) == 'undefined'
        		&& typeof(config.baseMapConfigPath) == 'undefined'
    			&& typeof(config.catalogConfigPath) == 'undefined'
            	&& typeof(config.contextsConfigPath) == 'undefined'
        		&& typeof(config.widgetsConfigPath) == 'undefined')
            {
                var results = [[true,{response:config.configObjects.viewer, success:true}], [true,{response:config.configObjects.baseMap, success:true}], [true,{response:config.configObjects.catalog, success:true}], [true,{response:config.configObjects.context, success:true}], [true,{response:config.configObjects.widgets, success:true}]];
                this.filesLoaded(results);
                return;
            }
            else 
            {
                this.configBaseUrl = "config/!{CTX}!/!{LOCALE}!/";
            }

            var patternCtx = new RegExp('!{CTX}!', 'gi');
            if(patternCtx.test(this.configBaseUrl)){
                this.configBaseUrl = this.configBaseUrl.replace(patternCtx, this.currentContext);
            }
            var patternLocale = new RegExp('!{LOCALE}!', 'gi');
            if(patternLocale.test(this.configBaseUrl)){
                this.configBaseUrl = this.configBaseUrl.replace(patternLocale, config.locale);
            }

            var filesToLoad = [
               (typeof(config.viewerConfigPath) == 'undefined') ? this.loadConfigFile("viewer.json") : this.loadFile(config.viewerConfigPath),
               (typeof(config.baseMapConfigPath) == 'undefined') ? this.loadConfigFile("baseMap.json") : this.loadFile(config.baseMapConfigPath),
               (typeof(config.catalogConfigPath) == 'undefined') ? this.loadConfigFile("catalog.json") : this.loadFile(config.catalogConfigPath),
               (typeof(config.contextsConfigPath) == 'undefined') ? this.loadConfigFile("contexts.json") : this.loadFile(config.contextsConfigPath),
               (typeof(config.widgetsConfigPath) == 'undefined') ? this.loadConfigFile("widgets.json") : this.loadFile(config.widgetsConfigPath)
            ];

            var defList = new DeferredList(filesToLoad);
            defList.then(lang.hitch(this, this.filesLoaded));
        },

        filesLoaded: function(results){
            //if false, display error
            var curidx = 0;
            var ok = array.every(results, lang.hitch(this, function(result, idx) {
                curidx = idx;
                return result[1].success;
            }));

            if (!ok) {
                if (this.backToNormal) {
                    this.backToNormal = false;

                    this.load(this.currentContext.substring(0, this.currentContext.length - 2), {
                        noMobileSupport: true
                    });
                }
                else {
                    MessageManager.getInstance().displayLoadingError(
                        results[curidx][1].response,
                        this._viewerConfig ? this._viewerConfig.errorMailToAdress : null,
                        this._viewerConfig ? this._viewerConfig.errorMailSubject : null,
                        results[curidx][1].error
                    );
                }
                return;
            }
            else {
                this._dictionnary["viewer"] = this._viewerConfig = this.mergeConfig(ConfigLoader.configTypes.VIEWER,results[0][1].response);
                this._dictionnary["baseMap"] = this._baseMapConfig = this.mergeConfig(ConfigLoader.configTypes.BASEMAP, results[1][1].response);
                this._dictionnary["catalog"] = this._catalogConfig = this.mergeConfig(ConfigLoader.configTypes.CATALOG,results[2][1].response);
                this._dictionnary["context"] = this._contextConfig = this.mergeConfig(ConfigLoader.configTypes.CONTEXTS,results[3][1].response);
                this._dictionnary["widgets"] = this._widgetsConfig = this.mergeConfig(ConfigLoader.configTypes.WIDGETS,results[4][1].response);
            }

            if(this._baseMapConfig != null && this._baseMapConfig.length < 1){
                MessageManager.getInstance().displayLoadingError("Au minimum une baseMap doit être définie dans le fichier baseMap.json pour pouvoir initialiser la carte.", this._viewerConfig ? this._viewerConfig.errorMailToAdress : null,this._viewerConfig ? this._viewerConfig.errorMailSubject : null);
            }

            this.configureFromURL();
        },

        configureFromURL: function() {

            // anciennes méthodes (compatibilité) (#BSS et #MSS)
            this.retroConfigureMapServicesFromURL(StateManager.getInstance().getStateFromURL(StateManager.RETRO_MAP_SERVICES_ID));
            this.retroConfigureBaseMapFromURL(StateManager.getInstance().getStateFromURL(StateManager.RETRO_BASEMAP_ID));

            // create the new group with additionnal map services
            var group = {
                "code": "ADDITIONAL_SERVICES",
                "label": this.labels.additionalServicesGroupLabel,
                "mapServices": []
            };

            // #SHARE
            this.configureMapServicesFromShare(StateManager.getInstance().getStateFromURL('SHARE'), group);

            // #MAP_SERVICES
            this.configureMapServicesFromURL(StateManager.getInstance().getStateFromURL(StateManager.MAP_SERVICES_ID), group);

            // #PANIER ou #panier
            this.configureMapServicesFromURL(StateManager.getInstance().getStateFromURL(StateManager.PANIER_ID), group, true);
            this.configureMapServicesFromURL(StateManager.getInstance().getStateFromURL(StateManager.PANIER_ID.toLowerCase()), group, true);

            // #BASEMAPS
            this.configureBaseMapFromURL(StateManager.getInstance().getStateFromURL(StateManager.BASEMAP_ID));

            // #ADU...
            this.addMapServicesFromURL(group);

            // on clean l'URL
            // Utils.rua('SHARE');
            Utils.rua(StateManager.MAP_SERVICES_ID);
            Utils.rua(StateManager.PANIER_ID);
            Utils.rua(StateManager.PANIER_ID.toLowerCase());
            Utils.rua(StateManager.BASEMAP_ID);

            // si certains services ont été ajoutés au nouveau group, on l'ajoute au catalogue
            if (group.mapServices.length != 0) {
                this._dictionnary["catalog"].push(group);
            }
        },

        configureMapServicesFromShare: function(urlString, group) {
            // Utils.sua('SHARE', urlString);
            if (!urlString) {
                return;
            }

            // on récupère le token en essayant d'enlever des caractères pourris
            var token = unescape(urlString).replace(/[\u200B-\u200D\uFEFF]/gim, '');

            var shareServletUrl = this._dictionnary["viewer"].shareServlet || (dojo.config.geoviewerApiUrl + "/ShareServlet");

            // récupération de la config pour le token
            xhr(shareServletUrl + "?method=view&token=" + token, {
                handleAs : "json",
                sync: true
            }).then(lang.hitch(this, function(resp) {
                if (resp.success === false) {
                    console.error('Impossible de récupérer les informations de partage...token invalide ?');
                    return;
                }

                // on récupère les infos
                var basemaps = resp.basemaps;
                var services = resp.services;
                var bbox = resp.bbox;

                // pour savoir si le même srid est utilisé
                var srid = resp.srid;
                var viewerSrid = +(this._dictionnary["viewer"].spatialReference);

                if (!isNaN(srid)) {
                    srid = +srid;
                }
                else {
                    srid = viewerSrid;
                }

                // on ajoute les service au groupe ou on modifie ceux de la config
                if(basemaps) {
                	this._configureBasemapsFromJson(basemaps, group, true);
                	var bms = JSON.parse(decodeURIComponent(basemaps));
                	var found = array.some(bms, lang.hitch(this, function(baseMapServiceState) {
                		return array.some(this._dictionnary['baseMap'], lang.hitch(this, function(baseMap) {
                             return array.some(baseMap.services, lang.hitch(this, function(service) {
                                 return baseMapServiceState.serviceId == service.serviceId;
                             }));
                		}));
                	}));
            		if(!found){
                        MessageManager.getInstance().notifyError("Le fond de plan sélectionné n'est plus disponible, veuillez re-générer le lien de partage.");
            		}
                }

                if(services)
                	this._configureMapServicesFromJson(services, group);

                var urlBbox = Utils.gua('BBOX');
                // si bbox définie dans le share ET que pas de BBOX défini dans l'URL
                if (bbox && urlBbox == '') {
                    // et si srid différent
                    if (srid !== viewerSrid) {
                        // il faut projeter la bbox
                        var vals = bbox.split(',');
                        var floats = array.map(vals, function(v) { return parseFloat(v); });

                        var min = ProjectionManager.getInstance().projectPoint(srid, viewerSrid, vals[0], vals[2]);
                        var max = ProjectionManager.getInstance().projectPoint(srid, viewerSrid, vals[1], vals[3]);

                        bbox = min.x + ',' + max.x + ',' + min.y + ',' + max.y;
                    }
                    Utils.sua('BBOX', bbox);
                }
                if (Utils.gua('ADR') || Utils.gua('COOR')) {
                    Utils.rua('BBOX');
                }

            }), lang.hitch(this, function(err) {
                console.error(err);
            }));
        },

        _configureMapServicesFromJson: function(json, group, overrideUrlParams) {
            // on parse l'array de services
            var aServices = JSON.parse(decodeURIComponent(json));

            if (aServices == null) {
                console.error('wrong json parameter "' + json + '"');
                return;
            }

            // on parcourt ensuite les différents services
            array.forEach(aServices, lang.hitch(this, function(service) {
                if (service.storage == null) {
                    // parcourir tout le catalogue pour trouver la config et la surcharger
                    var found = array.some(this._dictionnary["catalog"], lang.hitch(this, function(g) {
                        var services = this.getServicesFromGroup(g);

                        return array.some(services, lang.hitch(this, function(mapService, idx){
                            // on a trouvé un service dans la config existante
                            if (mapService.serviceId === service.serviceId) {

                                // faut-il le supprimer ?
                                if (service.deleted) {
                                    services[idx].toLoad = false;
                                    services[idx].visible = false;
                                    return true;
                                }

                                // est-ce que la config de l'URL est prioritaire ou l'inverse ?
                                if (overrideUrlParams == null || !overrideUrlParams) {
                                	var obj = { toLoad: true };

                                	if(service.alpha) obj.alpha = service.alpha;
                                	obj.visible = service.visible;
                                	if(service.order) obj.order = service.order;

                                    obj.type = mapService.type || service.type;
                                    obj.url = mapService.url || service.url;
                                    obj.label = mapService.label || service.label;

                                    if (mapService.identifiable == null && service.identifiable == null) {
                                        obj.identifiable = true;
                                    }
                                    else {
                                        obj.identifiable = mapService.identifiable || service.identifiable;
                                    }

                                    services[idx] = lang.mixin(mapService, obj);
                                }
                                else {
                                    services[idx] = lang.mixin(services[idx], service);
                                    services[idx].toLoad = true;
                                    services[idx].identifiable = true;
                                }

                                // on parcourt ensuite chaque layers du service
                                array.forEach(service.layers, function(l) {
                                    // et on recherche chaque layer parmi les layers du service de la config
                                    var ok = array.some(mapService.layers, function(ml, idx2) {
                                        if (ml.layerId === l.layerId) { // trouvé
                                            // lequel est prioritaire ?
                                            if (overrideUrlParams == null || !overrideUrlParams) {
                                                mapService.layers[idx2] = lang.mixin(ml, l);
                                            }
                                            else {
                                                mapService.layers[idx2] = lang.mixin(l, ml);
                                            }

                                            return true;
                                        }

                                        return false;
                                    });

                                    // si on a pas trouvé ce layer dans la config, il faut l'ajouter
                                    if (!ok) {
                                        mapService.layers = mapService.layers || [];
                                        mapService.layers.push(l);
                                    }
                                });

                                return true;
                            }

                            return false;
                        }));
                    }));

                    if(service.url && service.url.indexOf('||') > -1){
                    	try {
                    		service.visibleLayersIds = JSON.parse(service.url.split('||')[1]);
                    		service.url = service.url.split('||')[0];
                    	} catch(err){ console.log(err);}
                    }
                    if(service.url && service.url.endsWith("#")){
                    	service.url = service.url.substring(0, service.url.length-1);
                    }
                    // si le service n'a pas été trouvé dans la config, il faut l'ajouter au nouveau groupe
                    if (!found) {
                    	//si ce dernier n'est pas déjà présent dans ce nouveau groupe
                    	if(!array.some(group.mapServices, function(mp){ return mp.serviceId == service.serviceId; })){
                            group.mapServices.push(lang.mixin({
                                toLoad: true,
                                visible: true,
                                identifiable: true
                            }, service));
                    	}
                    }
                }
                else {
                    // si le service est stocké quelque part, il faut le récupérer de ce stockage
                    switch (service.storage) {
                        case 'local': // localStorage
                            this._loadServiceFromLocalStorage(service.serviceId, group.mapServices);
                            break;

                        default:
                            console.error('unknown storage method : ' + service.storage);
                    }
                }
            }));
        },

        configureMapServicesFromURL: function(urlString, group, overrideUrlParams) {
            if (!urlString) {
                return;
            }

            this._configureMapServicesFromJson(urlString, group, overrideUrlParams);
        },

        _configureBasemapsFromJson: function(json, group, resetOptionnals) {
            var aBasemaps = JSON.parse(decodeURIComponent(json));

            if (aBasemaps == null) {
                console.error('wrong url parameter "' + urlString + '"')
                return;
            }

            if (aBasemaps.length === 0) {
                return;
            }

            // on déselectionne tout
            array.forEach(this._dictionnary["baseMap"], lang.hitch(this,function(baseMap){
                baseMap.selected = false;
            }));

            var idsChecked = []; // pour connaître ceux déjà check

            // ON PARCOURT CHAQUE FOND DE PLAN PROVENANT DU SHARE
            array.forEach(aBasemaps, lang.hitch(this, function(baseMapServiceState) {
                var blackAndWhite = false;
                var blackAndWhiteType = false;

                // NOIR & BLANC DOIT IL ETRE ACTIVE ?
                if (baseMapServiceState.serviceId) {
                    if (baseMapServiceState.serviceId.indexOf('black-and-white-') >= 0) {
                        blackAndWhite = true;
                        blackAndWhiteType = true;
                        // l'activation se base sur le serviceId
                        baseMapServiceState.serviceId = baseMapServiceState.serviceId.replace('black-and-white-', '');
                    }
                    else if (baseMapServiceState.grayscale) {
                        blackAndWhite = true;
                        blackAndWhiteType = 'filter';
                    } else {
                        blackAndWhiteType = baseMapServiceState.activateBlackAndWhite;
                    }
                }

                var resetBaseMapSelected = null;

                // ON PARCOURT ENSUITE LA CONFIG (baseMaps.json)
                array.some(this._dictionnary['baseMap'], lang.hitch(this, function(baseMap) {
                    var maxAlpha = 0; // maxAlpha parmi les services actifs

                    //SI LE BASEMAP DU SHARE CORRESPOND AU BASEMAP DE LA CONFIG
                    if (baseMapServiceState.baseMapId && baseMapServiceState.baseMapId == baseMap.baseMapId) {
                        //ON MERGE LES DEUX CONFIGS, AVEC PRIORITE SUR CELLE PROVENANT DU SHARE
                        lang.mixin(baseMap, baseMapServiceState);
                        //ON SELECTIONNE LE FDP
                        if (baseMapServiceState.selected) {
                            resetBaseMapSelected = baseMap;
                        }
                    }
                    else {
                        // SINON, ON PARCOURT CHAQUE SERVICES DU BASEMAP DE LA CONFIG
                        var found = array.some(baseMap.services, lang.hitch(this, function(service) {
                            // tant qu'on a pas trouvé le service qui nous intéresse, on boucle
                            if (baseMapServiceState.serviceId !== service.serviceId) {
                                return false;
                            }

                            baseMap.selected = true;
                            // on active le noir&blanc par défaut
                            baseMap.blackAndWhiteByDefault = blackAndWhite;
                            baseMap.activateBlackAndWhite = blackAndWhiteType;
                            // override de l'alpha
                            baseMap.alpha = baseMapServiceState.alpha;

                            service.grayscale = baseMapServiceState.grayscale;

                            // si voyage dans le temps, l'alpha du service se base sur l'alphaTimer
                            if (baseMap.type === 'TIMER') {
                                service.alphaTimer = baseMapServiceState.alphaTimer;
                                service.alpha = Math.abs(baseMapServiceState.alphaTimer * baseMap.alpha);

                                if (maxAlpha < Math.abs(baseMapServiceState.alphaTimer)) {
                                    service.selected = true;
                                    maxAlpha = Math.abs(baseMapServiceState.alphaTimer);
                                }
                                else {
                                    service.selected = false;
                                }
                            }
                            else {
                                // sinon, il vaut l'alpha du fond de plan
                                service.alpha = baseMapServiceState.alpha;
                            }
                            
                        	if(resetOptionnals) {
                        		array.forEach(baseMap.optionalServices, lang.hitch(this, function(os) {
                        		    if (!os._force) {
                                        os.checked = false;
                                    }
                        		}));
                        	}


                            return true;
                        }));

                        // SI ON A TROUVE LE SERVICE, ON A PLUS RIEN A FAIRE
                        if (found) {
                            return true;
                        }

                        // SINON, ON RECHERCHE PARMI LES SERVICES OPTIONNELS
                        return array.some(baseMap.optionalServices, lang.hitch(this, function(os) {
                            // est-ce le service qui nous intéresse ?
                            if (os.serviceId !== baseMapServiceState.serviceId) {
                                // il faut déchecker le service s'il ne correspond pas si on l'a pas check nous-même auparavant dans cette fonction !
                                if (idsChecked.indexOf(os.serviceId) < 0) {
                                   // os.checked = false;
                                }
                                return false;
                            }

                            // sinon, on modifie l'alpha et on check le service
                            // os.alpha = baseMapServiceState.alpha;
                            os.checked = baseMapServiceState.checked;
                            os._force = true;
                            // pour savoir s'il faut uncheck ou pas le service si, plus tard, on retombe dessus
                            idsChecked.push(os.serviceId);
                        }));
                    }

                }));


                if (resetBaseMapSelected) {
                    array.some(this._dictionnary['baseMap'], lang.hitch(this, function(baseMap) {
                        if (baseMap !== resetBaseMapSelected) {
                            baseMap.checked = false;
                        }
                    }));
                }

//                if(this._dictionnary['baseMap'] && this._dictionnary['baseMap'].length > 0){
//                    var basemapFound = array.some(this._dictionnary['baseMap'], lang.hitch(this, function(configuredBaseMap){
//                        if(configuredBaseMap.baseMapId == baseMapServiceState.serviceId){
//                            return true;
//                        }
//                    }));
//                    if(!basemapFound){
//                        MessageManager.getInstance().notifyError("Le fond de plan sélectionné n'est plus disponible, veuillez re-générer le lien de partage.");
//                    }
//                }
            }));
        },

        configureBaseMapFromURL: function(urlString) {
            if (!urlString) {
                return;
            }

            this._configureBasemapsFromJson(urlString);
        },

        _loadServiceFromLocalStorage: function(id, msArray) {
            var service = JSON.parse(localStorage.getItem(id));

            if (service == null) {
                console.error('Service ' + id + ' not stored in local storage');
                return;
            }

            msArray.push(lang.mixin({}, service));
        },

        /**
         * Ajoute le(s) service(s) AGS définis dans l'url à la configuration courante.
         */
        addMapServicesFromURL: function(group) {
            // Add AGS dynamic layer from URL
            var agsDynUrls = Utils.gua("ADU") || Utils.gup("ADU") || Utils.gup("agsDynUrls");
            if(agsDynUrls != null && agsDynUrls != "") {
                var urls = agsDynUrls.split(";");

                for(var i=0;i<urls.length;i++) {
                    var url = urls[i];
                    var layers = url.split('||');

                    if (layers.length > 1) {
                        url = layers[0];
                        try {
                            layers = JSON.parse(layers[1]);
                        }
                        catch (e) {
                            console.error(e);
                            layers = null;
                        }
                    }
                    else {
                        layers = null
                    }

                    if (url.endsWith("#")){
                        url = url.substring(0, url.length - 1);
                    }

                    var name = url.substring(0, urls[i].indexOf("/MapServer"));

                    name = name.substring(name.lastIndexOf("/") + 1);

                    group.mapServices.push({
                        "serviceId": ""+(new Date().getTime() + i),
                        "label": name,
                        "type": "AGS_DYNAMIC",
                        "url": url,
                        "hasLegend": true,
                        "alpha": 100,
                        "toLoad": true,
                        "visible": true,
                        "identifiable": true,
                        "visibleLayersIds": layers,
                        "openLayersLegend": !!layers
                    });
                }
            }

            // Add AGS tiled layer from URL
            var agsTiledUrls = Utils.gua("ATU");
            if(agsTiledUrls != null && agsTiledUrls != ""){
                var urls = agsTiledUrls.split(";");

                for(var i=0;i<urls.length;i++) {
                    var url = urls[i];
                    var layers = url.split('||');

                    if (layers.length > 1) {
                        url = layers[0];
                        try {
                            layers = JSON.parse(layers[1]);
                        }
                        catch (e) {
                            console.error(e);
                            layers = null;
                        }
                    }
                    else {
                        layers = null
                    }

                    if (url.endsWith("#")) {
                        url = url.substring(0, url.length - 1);
                    }

                    var name = url.substring(0, urls[i].indexOf("/MapServer"));

                    name = name.substring(name.lastIndexOf("/") + 1);

                    group.mapServices.push({
                        "serviceId": ""+(new Date().getTime() + i),
                        "label": name,
                        "type": "AGS_TILED",
                        "url": url,
                        "hasLegend": true,
                        "alpha": 100,
                        "toLoad": true,
                        "visible": true,
                        "identifiable": true,
                        "visibleLayersIds": layers,
                        "openLayersLegend": !!layers
                    });
                }
            }

            // Add WMS layer from URL
            var wmsUrlsAndVisibleLayers = Utils.gua("WMS");
            if(wmsUrlsAndVisibleLayers != null && wmsUrlsAndVisibleLayers != ""){
                var urlsAndVisibleLayers = wmsUrlsAndVisibleLayers.split(";");

                for(var i=0;i<urlsAndVisibleLayers.length;i++) {

                    var urlAndVisibleLayers = urlsAndVisibleLayers[i].split("|");

                    var url = urlAndVisibleLayers[0];
                    var visibleLayers = typeof urlAndVisibleLayers[1] != 'undefined' ? urlAndVisibleLayers[1].split(",") : [];

                    var name = url.substring(0, url.lastIndexOf("/"));
                    name = name.substring(name.lastIndexOf("/") + 1);
                    group.mapServices.push({
                        "serviceId": ""+(new Date().getTime() + i),
                        "label": name,
                        "type": "WMS",
                        "url": url,
                        "toLoad":true,
                        "hasLegend": true,
                        "identifiable": true,
                        "visible":true,
                        "wmsParameters": {
                            "visibleLayers":visibleLayers,
                            "format":"png",
                            "transparent": true
                        }
                    });
                }
            }
        },

        /**
         * Adapte la configuration courante du catalogue avec les informations (share) contenue dans l'url.
         * @param {String} mapServicesStatesString chaine de configuration de l'état des services
         */
        retroConfigureMapServicesFromURL: function(mapServicesStatesString){

            if(mapServicesStatesString) {

                array.forEach(this._dictionnary["catalog"], lang.hitch(this, function(group) {
                    var services = this.getServicesFromGroup(group);
                    array.forEach(services,lang.hitch(this,function(service){
                        service.toLoad = false;
                    }));
                }));

                var mapServicesStates = mapServicesStatesString.split(";");

                array.forEach(mapServicesStates, lang.hitch(this, function(mapServiceState){
                    var mapServiceInfos = mapServiceState.split(",");

                    if(mapServiceInfos[0]){
                        array.forEach(this._dictionnary["catalog"], lang.hitch(this, function(group) {
                            var services = this.getServicesFromGroup(group);

                            array.forEach(services,lang.hitch(this,function(mapService){
                                if(mapServiceInfos[0] == mapService.serviceId){
                                    mapService.toLoad = true;

                                    if(mapServiceInfos[1] && mapServiceInfos[1] == "true"){
                                        mapService.visible = true;
                                    }
                                    else{
                                        mapService.visible = false;
                                    }

                                    if(mapServiceInfos[2]){
                                        mapService.alpha = mapServiceInfos[2];
                                    }

                                    if(mapServiceInfos[3]){
                                        var mapServiceLayersStates = mapServiceInfos[3].split("|");

                                        array.forEach(mapServiceLayersStates, lang.hitch(this, function(mapServiceLayerState){

                                            var mapServiceLayerInfos = mapServiceLayerState.split(":");

                                            if(mapServiceLayerInfos[0] && mapServiceLayerInfos[1]){
                                                var found = false;

                                                if(mapService.layers){
                                                    for(var j=0;j<mapService.layers.length;j++){
                                                        if(mapService.layers[j].layerId == mapServiceLayerInfos[0]){

                                                        if(mapServiceLayerInfos[1] == "true"){
                                                                mapService.layers[j].defaultVisibility = true;
                                                            }
                                                            else{
                                                                mapService.layers[j].defaultVisibility = false;
                                                            }
                                                            found = true;
                                                            break;
                                                        }
                                                    }
                                                }
                                                else{
                                                    mapService.layers = new Array();
                                                }

                                                if(!found){
                                                    if(mapServiceLayerInfos[1] == "true"){
                                                        mapService.layers.push({"layerId": mapServiceLayerInfos[0],"defaultVisibility":true});
                                                    }
                                                    else{
                                                        mapService.layers.push({"layerId": mapServiceLayerInfos[0],"defaultVisibility":false});
                                                    }
                                                }
                                            }
                                        }));
                                    }
                                }
                            }));
                        }));
                    }
                }));

                this._dictionnary["catalog"].push(localGroup);
            }
        },

        /**
         * Récupère les services d'un groupe de service dans la configuration du catalogue.
         * @param {String} serviceGroup le code du groupe de services.
         * @returns {Array} Les services contenu dans le groupe.
         */
        getServicesFromGroup: function(serviceGroup) {
            var services = [];

            if(serviceGroup.mapServices){
                services = services.concat(serviceGroup.mapServices);
            }
            if(serviceGroup.groups){
                array.forEach(serviceGroup.groups,lang.hitch(this,function(group){
                    services = services.concat(this.getServicesFromGroup(group));
                }));
            }
            return services;
        },

        /**
         * Adapte la configuration courante des baseMaps avec les informations (share) contenue dans l'url.
         * @param {String} baseMapStateString chaine de configuration de l'état des fonds de plan
         */
        retroConfigureBaseMapFromURL: function(baseMapStateString){

            if(baseMapStateString){

                var baseMapServicesState = baseMapStateString.split(";");

                array.forEach(this._dictionnary["baseMap"], lang.hitch(this,function(baseMap){
                    baseMap.selected = false;
                }));

                array.forEach(baseMapServicesState, lang.hitch(this,function(baseMapServiceState){
                    var baseMapServiceInfos = baseMapServiceState.split("|");

                    var blackAndWhite = false;

                    if(baseMapServiceInfos[0]){

                        if(baseMapServiceInfos[0].search("black-and-white-") != -1){
                            blackAndWhite = true;
                            baseMapServiceInfos[0] = baseMapServiceInfos[0].replace("black-and-white-","");
                        }

                        array.forEach(this._dictionnary["baseMap"], lang.hitch(this,function(baseMap){

                            array.forEach(baseMap.services, lang.hitch(this,function(service){
                                if(baseMapServiceInfos[0] == service.serviceId){
                                    baseMap.selected = true;
                                    
                                    baseMap.blackAndWhiteByDefault = blackAndWhite;
                                    
                                    if(baseMapServiceInfos[1]) {
                                        baseMap.alpha = baseMapServiceInfos[1];
                                    }

                                    array.forEach(baseMap.optionalServices, lang.hitch(this,function(optionalService){

                                        optionalService.checked = false;
                                        array.forEach(baseMapServicesState, lang.hitch(this,function(baseMapServiceState){
                                            var baseMapServiceInfos = baseMapServiceState.split("|");

                                            if(baseMapServiceInfos[0].search("black-and-white-") != -1){
                                                baseMapServiceInfos[0] = baseMapServiceInfos[0].replace("black-and-white-","");
                                            }

                                            if(baseMapServiceInfos[0] == optionalService.serviceId){
                                                optionalService.checked = true;
                                                if(baseMapServiceInfos[1])
                                                    optionalService.alpha = baseMapServiceInfos[1];
                                            }
                                        }));
                                    }));
                                }
                            }));
                        }));
                    }
                }));
            }
        },

        /**
         * Charge un fichier de configuration sur base de son nom.
         * @param {String} fileName - Nom du fichier
         * @returns {Deffered} Objet Deffered de Dojo pour le XHR de chargement du fichier.
         */
        loadConfigFile: function (fileName){
            return this.loadFile(this.configBaseUrl + fileName);
        },

        /**
         * Charge un fichier sur base de son url.
         * @param {String} url du fichier à charger.
         * @returns {Deffered} Objet Deffered de Dojo pour le XHR de chargement du fichier.
         */
        loadFile: function(url, failed){
            return xhr(url + "?ts="+new Date().getTime(), { handleAs : "json", sync: true }).then(
                lang.hitch(this, function(json) {
                    if(json && json.length){
                        for(var idx = 0; idx < json.length; idx++){
                            var item = json[idx];
                            if(item.remote){
                                this.loadFile(item.remote).then(lang.hitch(this, function(file){
                                    if(file && file.success){
                                        var arr = json.slice(0, idx);
                                        array.forEach(file.response, function(_item){ arr.push(_item);});
                                        json = arr.concat(json.slice(idx+1, json.length));
                                    }
                                }));
                            }
                        }
                    } else if(json && json.remote){
                        this.loadFile(json.remote).then(lang.hitch(this, function(file){
                            if(file && file.success){
                                json = file.response;
                            }
                        }));
                    }
                    return {success: true, response: json};
                }),
                lang.hitch(this, function(err){
                    console.debug("loadConfigFile() error", err);
                    var message = "Erreur inconnue";
                    if(err.response.status == 404){
                        if (this.backToNormal === true || failed === true) {
                            message = "Le contexte n'est pas valide ou la configuration du fichier \"" + url + "\" pour la langue \"" + config.locale + "\" n'existe pas.";
                        }
                        else {
                            return this.loadFile((require("dojo/_base/config").geoviewerApiUrl + "/DefaultConfig?") + url.split('/').pop(), true);
                        }
                    }
                    else {
                        message = "Erreur de syntaxe dans le fichier : " + url;
                    }
                    return {success: false, response: message, error: (err ? err.error ? err.error.stack : err : null)};
                })
            );
        },

        /**
         * Fusionne un tableau d'objet json de configuration sur base d'une propriété clé da la configuration
         * @param {Array.<Object>} list Tableau d'objets json d'une configuration
         * @param objectIdentifier clé de configuration sur laquelle est effectuée la comparaison pour la fusion.
         * @returns {Array.<Object>} Tableau d'objet json fusionnés.
         */
        _jsonObjectsMerge: function(list, objectIdentifier){
            var jsonMerged = new Array();
            if(!list || !list.length){
                return jsonMerged;
            }
            array.forEach(list, function(element){
                var queryObject = {}; queryObject[objectIdentifier] = element[objectIdentifier];

                if(typeof(element[objectIdentifier]) == 'undefined'){
                    jsonMerged.push(element);
                }
                else if(Utils.findInList(jsonMerged, queryObject).length == 0){
                    var sameObjects = Utils.findInList(list, queryObject);
                    if(sameObjects.length > 0){
                        var newObject = {};
                        for(var i=0; i<sameObjects.length; i++){
                            lang.mixin(newObject, sameObjects[i]);
                        }
                        jsonMerged.push(newObject);
                    }
                }
            });
            return jsonMerged;
        },

        /**
         * Fusionne les différents objets de configuration.
         * @param {String} fileConfigType le type d'objet à fusionner.
         * @param {Array.<Object>} json les objets de configuration à fusionner.
         * @returns {Object} l'objet json de configuration fusionné.
         */
        mergeConfig: function(fileConfigType,json){
            var jsonMerged = null;

            switch(fileConfigType){
            case ConfigLoader.configTypes.BASEMAP:
                jsonMerged = this._jsonObjectsMerge(json, "baseMapId");

                array.forEach(jsonMerged, lang.hitch(this, function(baseMap, idx) {

                    if (typeof baseMap === 'string') {
                        var splitted = baseMap.split('_');

                        if (this.defaultBaseMaps[splitted[0]]) {
                            var newCfg = lang.clone(this.defaultBaseMaps[splitted[0]]);

                            for (var i = 1; i < splitted.length && this.defaultBaseMaps[splitted[i]]; ++i) {
                                var optionalService = lang.clone(this.defaultBaseMaps[splitted[i]]);
                                optionalService.serviceId = splitted[0] + i;
                                newCfg.optionalServices = newCfg.optionalServices || [];
                                newCfg.optionalServices.push(optionalService);
                            }

                            jsonMerged[idx] = newCfg;
                        }
                    }

                }));
                break;
            case ConfigLoader.configTypes.CATALOG:
                jsonMerged = this._jsonObjectsMerge(json, "code");
                break;
            case ConfigLoader.configTypes.CONTEXTS:
                jsonMerged = this._jsonObjectsMerge(json, "name");
                break;
            case ConfigLoader.configTypes.VIEWER:
                jsonMerged = new Array();
                if(json && json.length){
                    array.forEach(json,lang.hitch(this,function(viewerConfig){
                        jsonMerged = lang.mixin(viewerConfig,jsonMerged);
                    }));
                }
                else{
                    jsonMerged = json;
                }
                break;
            case ConfigLoader.configTypes.WIDGETS:
                jsonMerged = new Array();
                if(json && json.length > 0){
                    array.forEach(json, function(element){
                        if(element && element.config && element.config.widgetId){
                            var alreadyMerged = [];
                            array.forEach(jsonMerged, function(merged){
                                if(merged && merged.config && merged.config.widgetId && element.config.widgetId == merged.config.widgetId){
                                    alreadyMerged.push(merged);
                                }
                            });
                            if(alreadyMerged && alreadyMerged.length == 0)
                            {
                                var sameObjects = [];
                                array.forEach(json, function(merged){
                                    if(merged && merged.config && merged.config.widgetId && element.config.widgetId == merged.config.widgetId){
                                        sameObjects.push(merged);
                                    }
                                });
                                if(sameObjects && sameObjects.length > 0){
                                    var newObject = {};
                                    for(var i=0; i<sameObjects.length; i++){
                                        if(sameObjects[i])
                                            lang.mixin(newObject, sameObjects[i]);
                                    }
                                    jsonMerged.push(newObject);
                                } else {
                                    jsonMerged.push(element);
                                }
                            }
                        }
                        else {
                            jsonMerged.push(element);
                        }
                    });
                }
                break;
            }

            return jsonMerged;
        },

        /**
         * Récupère une copie d'un objet de configuration sur base de sa clé.
         * @param {string} configKey clé de l'objet de configuration : context ; baseMap ; catalog ; widgets ; viewer.
         * @returns {Object} l'objet json de configuration.
         */
        get: function(configKey){
            return lang.clone(this._dictionnary[configKey]);
        },

        /**
         * Récupère un/plusieurs contexte(s) définit dans la configuration 'context'.
         * @param {Object} queryObject Association clé-valeur permettant la comparaison des objets.
         * @returns {Array.<Object>} Le(s) contexte(s) correspondant au queryObject.
         */
        getContext: function(queryObject){
            return Utils.findInList(this._contextConfig, queryObject);
        },

        /**
         * Récupère un/plusieurs service(s) définit dans la configuration 'catalog'.
         * @param {Object} queryObject Association clé-valeur permettant la comparaison des objets.
         * @returns {Array.<Object>} Le(s) service(s) correspondant au queryObject.
         */
        getService: function(queryObject){
            var serviceGroups = Utils.findInList(this._catalogConfig);
            var services = [];
            array.forEach(serviceGroups, function(group){ services = services.concat(group.mapServices); });
            return lang.clone(Utils.findInList(services, queryObject));
        },
        
        getServicesAsArray: function(queryObject, groups){
            var serviceGroups = groups || Utils.findInList(this._catalogConfig);
            var services = [];
            array.forEach(serviceGroups, lang.hitch(this, function(group){
            	if(group.mapServices){
                	services = services.concat(group.mapServices);
            	}
            	if(group.groups){
        			services = services.concat(this.getServicesAsArray(queryObject, group.groups));
            	}
            }));
            return lang.clone(Utils.findInList(services, queryObject));
        }
    });

    var _INSTANCE = null;
    /**
     * Permet de récupérer l'instance du ConfigLoader
     * @method getInstance
     * @memberof spw.api.ConfigLoader
     * @returns spw.api.ConfigLoader
     */
    ConfigLoader.getInstance = function(config){
        if(_INSTANCE == null){
            _INSTANCE = new ConfigLoader(config);
        }
        return _INSTANCE;
    };

    ConfigLoader.events = {
        /**
         * Evènement déclenché lorsque les configuration sont chargées.
         *
         * @event spw.api.ConfigLoader#CONFIG_LOADED
         */
        "CONFIG_LOADED":"CONFIG_LOADER:CONFIG_LOADED"
    };

    ConfigLoader.configTypes = {
            "BASEMAP" : "BASEMAP",
            "CATALOG" : "CATALOG",
            "CONTEXTS" : "CONTEXTS",
            "VIEWER" : "VIEWER",
            "WIDGETS" : "WIDGETS"
    };

    return ConfigLoader;
});