Source: api/DynamicMapService.js

Retour à la documentation
define([
        'dojo/_base/declare',
        'dojo/_base/array',
        'dojo/_base/lang',
        'spw/api/MapService',
        'spw/api/MapServiceFactory',
        'esri/layers/ArcGISDynamicMapServiceLayer',
        'esri/layers/ImageParameters',
        'esri/tasks/IdentifyTask',
        'esri/tasks/QueryTask',
        'esri/tasks/query',
        'esri/layers/LayerDrawingOptions',
        'esri/tasks/IdentifyParameters',
        'spw/api/ProjectionManager',
        'esri/layers/ArcGISMapServiceLayer',
        'esri/layers/LayerInfo',
        'esri/lang',
        'esri/geometry/Extent',
        'esri/SpatialReference',
        'spw/api/ConfigLoader',
        'spw/api/SpwViewer',
        'spw/api/Utils',
        "dojo/promise/all",
        "dojo/Deferred",
        "esri/request",
        "esri/tasks/RelationshipQuery",
        "esri/geometry/Point",
        "esri/geometry/screenUtils",
        "esri/graphic"
    ],
    function(declare, array, lang, MapService, MapServiceFactory, ArcGISDynamicMapServiceLayer, ImageParameters,
             IdentifyTask, QueryTask, Query, LayerDrawingOptions, IdentifyParameters, ProjectionManager,
             ArcGISMapServiceLayer, LayerInfo, esriLang, Extent, SpatialReference, ConfigLoader, SpwViewer, Utils,all,
             Deferred, xhr, RelationshipQuery, Point, ScreenUtils, Graphic) {

        ArcGISMapServiceLayer.prototype._initLayer = function(b, f) {
            try {
                this._findCredential();
                (this.credential && this.credential.ssl || b && b._ssl) && this._useSSL();
                this.description = b.description || b.serviceDescription;
                this.copyright = b.copyrightText;
                this.spatialReference = b.spatialReference && new SpatialReference(b.spatialReference);
                this.initialExtent = b.initialExtent && new Extent(b.initialExtent);
                this.fullExtent = b.fullExtent && new Extent(b.fullExtent);
                this.units = b.units;
                this.mapName = b.mapName;
                this.maxRecordCount = b.maxRecordCount;
                this.maxImageHeight = b.maxImageHeight;
                this.maxImageWidth = b.maxImageWidth;
                this.supportsDynamicLayers = b.supportsDynamicLayers;
                var m = this.layerInfos = [],
                    e = b.layers,
                    s = this._defaultVisibleLayers = [];
                array.forEach(e, function(a, b) {
                    m[b] = new LayerInfo(a);
                    a.defaultVisibility && s.push(a.id)
                });
                this.visibleLayers || (this.visibleLayers = s);
                this.version = b.currentVersion;
                this.version || (this.version = "capabilities" in b || "tables" in b ? 10 : "supportedImageFormatTypes" in b ? 9.31 : 9.3);
                this.capabilities = b.capabilities;
                esriLang.isDefined(b.minScale) && !this._hasMin && this.setMinScale(b.minScale);
                esriLang.isDefined(b.maxScale) && !this._hasMax && this.setMaxScale(b.maxScale)
            } catch (k) {
                this._errorHandler(k)
            }
        }
        /**
         * @class spw.api.ClusterMapService
         * @classdesc Service du viewer correspondant à un ArcGISDynamicMapServiceLayer d'ESRI
         * @extends {spw.api.MapService}
         */
        var DynamicMapService = declare('spw.api.DynamicMapService', [MapService], /** @lends spw.api.DynamicMapService.prototype */ {

            imageParameters: null,
            pending_relationship_query:0,

            /**
             * Crée le layer Esri sur base de la configuration du MapService.
             * @memberOf spw.api.MapService
             */
            createMapLayer: function() {
                this.layer = this._createDynamicLayer({
                    imageFormat: this.get('imageFormat'),
                    serviceId: this.get('serviceId'),
                    disableClientCache: this.get('disableClientCache'),
                    alpha: this.get('alpha'),
                    displayLevels: this.displayLevels,
                    url: this.get('url')
                });

                if(this.get('layerDrawingOptions')) {
                    var optionsArray = [];
                    var drawingOptions = new LayerDrawingOptions(this.get('layerDrawingOptions'));
                    optionsArray[0] = drawingOptions;
                    this.layer.setLayerDrawingOptions(optionsArray);
                }

                this.addClusterAndHeatLayers();

                this.inherited(arguments);
            },

            _createDynamicLayer: function(config) {
                var imageParameters = new ImageParameters();

                if (this.get('imageParameters')) {
                    var params = this.get('imageParameters');

                    if (params.layerOption == null && params.option) {
                        params.layerOption = ImageParameters[params.option]; // map nom <-> valeur
                        params.option = null;
                    }

                    lang.mixin(imageParameters, params);
                }

                if(config.imageFormat){
                    imageParameters.format = config.imageFormat;
                } else {
                    imageParameters.format = "png32";
                }

                if(this.get('layerDefinitions')) {
                    imageParameters.layerDefinitions = this.get('layerDefinitions');
                }
                var layerConfig = {
                    id: config.serviceId,
                    opacity: config.alpha / 100,
                    imageParameters: imageParameters
                };

                if(config.displayLevels) {
                    layerConfig.displayLevels = config.displayLevels;
                }

                var layer = new ArcGISDynamicMapServiceLayer(config.url, layerConfig);
                layer.setDisableClientCaching(config.disableClientCache);
                var aspect = require("dojo/aspect");
                aspect.after(layer, "_initLayer", function(){
                    console.log(arguments);
                }, true);

                return layer;
            },

            loadLayerInfos: function(layerId){
                return xhr({ url: this.get('url')+'/'+(layerId), content: {f:'json'}, handleAs: "json" });
            },

            // loadServiceInfos: function(){
            //     return xhr({ url: this.get('url'), content: {f:'json'}, handleAs: "json" });
            // },

            buildIdentifyParameters: function (options) {
                var identifyParams = new IdentifyParameters();

                options.ignoreFields = options.ignoreFields || [];
                options.ignoreFields = options.ignoreFields.concat(this.ignoreAttributes);
                options.ignoreFields = array.map(options.ignoreFields, function(f){ return f ? f.toUpperCase() : "";});

                identifyParams.tolerance = options.tolerance ? options.tolerance : 5;
                identifyParams.returnGeometry = options.returnGeometry;
                identifyParams.spatialReference = this.spwMap.get('esriMap').spatialReference;

                var identifiableLayers = new Array();
                for(key in this.mapServiceLayers) {
                    var layer = this.mapServiceLayers[key];
                    if(layer.shouldBeIdentified()) {
                        identifiableLayers.push(layer.get('layerId'));
                    }
                }
                if (identifiableLayers.length == 0) {
                    identifiableLayers = [-1];
                }
                identifyParams.layerIds = identifiableLayers;
                options.identifiableLayers = identifiableLayers;

                identifyParams.layerOption = options.layerOption ? options.layerOption : IdentifyParameters.LAYER_OPTION_VISIBLE;
                identifyParams.width = this.spwMap.get('esriMap').width;
                identifyParams.height = this.spwMap.get('esriMap').height;

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

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

                identifyParams.geometry = options.mapPoint || options.geometry;
                identifyParams.mapExtent = this.spwMap.get('esriMap').extent;
                identifyParams.layerDefinitions = this.get('layerDefinitions');

                return identifyParams;
            },



            fetchLayerInfo: function(options, def) {
                if(!this['layerInfoLoaded']){
                    options.identifiableLayers = [];
                    array.forEach(this.get('mapServiceLayers'), lang.hitch(this, function(layer){
                        options.identifiableLayers.push(layer.layerId);
                    }));
                    var getLayerInfoDefList = [];
                    if(options && options.identifiableLayers && options.identifiableLayers.length > 0){
                        array.forEach(options.identifiableLayers, lang.hitch(this, function(layerId){
                            getLayerInfoDefList.push(this.loadLayerInfos(layerId));
                        }));
                        all(getLayerInfoDefList).then(lang.hitch(this, function(allLayerInfo){
                            if(allLayerInfo && allLayerInfo.length > 0){
                                array.forEach(allLayerInfo, lang.hitch(this, function(layerInfo){
                                    if(this['layerInfoAsJson'] == null){
                                        this['layerInfoAsJson'] = {};
                                    }
                                    if(layerInfo.id != null){
                                        this['layerInfoAsJson'][layerInfo.id] = layerInfo;
                                        var currentLayer = this.mapServiceLayers[layerInfo.id];
                                        if(currentLayer){
                                            currentLayer.layerInfo = layerInfo;
                                            this.mergeLayerFields(currentLayer);
                                        }
                                    }
                                }))
                            }
                            def.resolve();
                        }))
                    }else{
                        //Pas de layers à identifier spécifiés
                        def.resolve();
                    }
                    this['layerInfoLoaded'] = true;
                }else{
                    def.resolve();
                }
            },

            mergeLayerFields: function(layer){
                if(layer && layer.layerInfo){
                    if(layer.fields){
                        if(this.restrictToFields){
                            array.forEach(layer.fields, function(f){
                                var fs = Utils.findInList(layer.layerInfo.fields, { name: f.name })[0];
                                fs && lang.mixin(lang.clone(fs), f);
                            });
                        } else {
                            array.forEach(layer.layerInfo.fields, lang.hitch(this, function(f){
                                var fs = Utils.findInList(layer.fields, { name: f.name })[0];
                                if(fs) {
                                    lang.mixin(fs, lang.mixin(lang.clone(f), fs));
                                } else {
                                    layer.fields.push(f);
                                }
                            }));
                        }
                    } else {
                        layer.fields = layer.layerInfo.fields;
                    }
                }
            },

            layersOffsetSymbol: {},
            findLayerdIdsWithoutResults: function(identifyParams, identifyResults) {
                var identifiedLayerIds = identifyParams.layerIds;
                var withoutResultsLayerIds = [];
                array.forEach(identifiedLayerIds, lang.hitch(this, function(layerId) {
                    var foundResult = array.some(identifyResults, lang.hitch(this, function(result) {
                        return result.layerId == layerId;
                    }));
                    if(!foundResult) {
                        withoutResultsLayerIds.push(layerId);
                    }
                }));
                withoutResultsLayerIds = array.filter(withoutResultsLayerIds, lang.hitch(this, function(layerId) {
                    var layerInfoAsJson = this.layerInfoAsJson[layerId];
                    var renderer = layerInfoAsJson.drawingInfo.renderer;
                    var offsetSymbols = renderer.symbol ?
                        [renderer.symbol] :
                        array.map(renderer.uniqueValueInfos, lang.hitch(this, function(symbol) {
                            return symbol.symbol;
                        }));
                    return array.some(offsetSymbols, lang.hitch(this, function(symbol) {
                        var xoffset = symbol.xoffset ? symbol.xoffset : 0;
                        var yoffset = symbol.yoffset ? symbol.yoffset : 0;
                        if(xoffset > 0 || yoffset > 0) {
                            this.layersOffsetSymbol[layerId] = this.layersOffsetSymbol[layerId] ? this.layersOffsetSymbol[layerId] : symbol;
                            return true;
                        }
                        return false;
                    }));
                }));
                return withoutResultsLayerIds;
            },



            retryOnLayersWithoutResults: function(withoutResultsLayerIds, options) {
                var promises = [];
                var retryPromise = new Deferred();
                array.forEach(withoutResultsLayerIds, lang.hitch(this, function(layerId) {
                    var identifyPromise = new Deferred();
                    var currentSymbol = this.layersOffsetSymbol[layerId];
                    var spwMap = this.get('spwMap');
                    var offsetx = currentSymbol.xoffset;
                    var offsety = currentSymbol.yoffset;

                    var offsetPoint = new Point(0, 0, new SpatialReference({wkid: spwMap.getSpatialReferenceSRID()}));
                    var extent = spwMap.esriMap.extent;
                    var width = spwMap.esriMap.width;
                    var height = spwMap.esriMap.height;

                    var offsetPointInPx = ScreenUtils.toScreenPoint(extent, width, height, offsetPoint);
                    offsetPointInPx.x += (-offsetx);
                    offsetPointInPx.y += (-offsety);
                    offsetPoint = ScreenUtils.toMapPoint(extent, width, height, offsetPointInPx);

                    var newIdentifyPoint = new Point(options.mapPoint.x, options.mapPoint.y, options.mapPoint.spatialReference);
                    newIdentifyPoint.x -= offsetPoint.x;
                    newIdentifyPoint.y -= offsetPoint.y;

                    // this.spwMap.get('esriMap').graphics.clear();
                    //
                    // var point1 = new Graphic(new Point(options.mapPoint.x, options.mapPoint.y, options.mapPoint.spatialReference), null);
                    // var point2 = new Graphic(new Point(newIdentifyPoint.x, newIdentifyPoint.y, newIdentifyPoint.spatialReference), null);
                    // this.spwMap.showFeature(point1);
                    // this.spwMap.showFeature(point2);

                    var tolerance = currentSymbol.height > currentSymbol.width ? currentSymbol.height : currentSymbol.width;
                    var offset = currentSymbol.xoffset > currentSymbol.yoffset ? currentSymbol.xoffset : currentSymbol.yoffset;
                    tolerance -= offset;

                    var newOptions = lang.mixin(
                        options,
                        {layerIds: [layerId], tolerance: tolerance,allowRetryOnOffsetSymbolLayers: false, mapPoint: newIdentifyPoint});
                    this.identify(
                        newOptions,
                        lang.hitch(this, function(res){
                            identifyPromise.resolve(res);
                        }),
                        lang.hitch(this, function(err) {
                            identifyPromise.reject();
                        }));
                    promises.push(identifyPromise);
                }));
                all(promises).then(lang.hitch(this, function(results) {
                    var allResults = [];
                    array.forEach(results, lang.hitch(this, function(res) {
                        allResults = allResults.concat(res);
                    }));
                    retryPromise.resolve(allResults);
                }));
                return retryPromise;
            },

            handleIdentifyResults: function(identifyResults, def, options, success, identifyParams, retryOnOffsetLayers) {
                var fetchLayerInfoDef = new Deferred();
                //Fetch layer info
                this.fetchLayerInfo(options, fetchLayerInfoDef);
                //When layer info are fetched
                fetchLayerInfoDef.then(lang.hitch(this, function(){
                    var withoutResultsLayerIds = [];
                    if(retryOnOffsetLayers && options.mapPoint) {
                        withoutResultsLayerIds = this.findLayerdIdsWithoutResults(identifyParams, identifyResults);
                        if (withoutResultsLayerIds.length > 0){
                            this.retryOnLayersWithoutResults(withoutResultsLayerIds, options).then(
                                lang.hitch(this, function(res) {
                                    var mergedResults = identifyResults.concat(res);
                                    this.transformResults(mergedResults, options, success, def);
                                }),
                                lang.hitch(this, function(err) {
                                    console.log('err:', err);
                                    this.transformResults(mergedResults, options, success, def);
                                })
                            )
                        } else {
                            this.transformResults(identifyResults, options, success, def);
                        }
                    } else {
                        this.transformResults(identifyResults, options, success, def);
                    }
                }))
            },

            transformResults: function(identifyResults, options, success, def) {
                var transformIdentifyResultsDef = [];
                array.forEach(identifyResults, lang.hitch(this, function(result){
                    transformIdentifyResultsDef.push(this.transformIdentifyResult(result, options));
                }));

                if(transformIdentifyResultsDef && transformIdentifyResultsDef.length > 0){
                    all(transformIdentifyResultsDef).then(lang.hitch(this, function(results){
                        if(success) {
                            success(identifyResults, this, results);
                        }
                        def.resolve(identifyResults, this, results);
                    }))
                }else{
                    if(success) {
                        success(identifyResults, this, []);
                    }
                    def.resolve(identifyResults, this, []);
                }
            },

            fieldMustBeShownInResults: function(field, options) {
                return options.ignoreFields.indexOf(field.name.toUpperCase()) == -1
                    && (field.identifiable == null || field.identifiable == true);
            },

            transformIdentifyResult: function(result, options) {
                var transformDef = new Deferred();
                result, options;
                if(options.ignoreFields == null){
                    options.ignoreFields = [];
                }

                var data = {};
                var spwLayer = this.mapServiceLayers[result.layerId];
                if(spwLayer){
                    var allConstructedFields = [];
                    if (spwLayer.fields) {
                        array.forEach(spwLayer.fields, lang.hitch(this, function(field){
                            result, options;
                            if(this.fieldMustBeShownInResults(field, options)){
                                var fieldValue = this.constructFieldValue(field, result);
                                allConstructedFields.push(fieldValue);
                            }
                        }));
                    } else {
                        array.forEach(Object.keys(result.feature.attributes), lang.hitch(this, function(key) {
                            var fieldValue = {key: key, value: result.feature.attributes[key]};
                            allConstructedFields.push(fieldValue);
                        }))
                    }

                    if(allConstructedFields.length > 0){
                        data['layerId'] = result.layerId;
                        data['data'] = {};
                        array.forEach(allConstructedFields, lang.hitch(this, function(attr){
                            data['data'][attr.key] = attr.value;
                        }));
                        // transformDef.resolve(data);
                    }else{
                        data['layerId'] = result.layerId;
                        // transformDef.resolve(data)
                    }
                    //Handle server side relationships
                    var def = this.handleTables(result, data);

                    def.then(lang.hitch(this, function(){
                        //Handle configurated relations in config file
                        this.handleConfigRelations(result, data, transformDef);
                    }))


                }else{
                    data['layerId'] = result.layerId;
                    transformDef.resolve(data)
                }
                return transformDef;
            },

            handleTables: function(identifyResult, data){
                var def = new Deferred();
                if(this.handleRelationships){
                    this.pending_relationship_query=0;
                    var result = identifyResult;
                    //Si le layerInfo est chargé est qu'il y a des relations
                    if(this['layerInfoAsJson']
                        && this['layerInfoAsJson'][identifyResult.layerId]
                        && this['layerInfoAsJson'][identifyResult.layerId].relationships
                        && this['layerInfoAsJson'][identifyResult.layerId].relationships.length > 0){

                        var relationshipDefList = [];
                        var recordedRelationships = [];
                        var relationships = this['layerInfoAsJson'][identifyResult.layerId].relationships;
                        //Pour toutes les relations du services

                        var tableInfoDefList = [];

                        var relationshipQueriesDef = [];

                        array.forEach(relationships, lang.hitch(this, function(relationship){
                            // Lire les infos de la table 'enfant' de la relation
                            var relationshipQuery = new RelationshipQuery();
                            relationshipQuery.outFields = ["*"];
                            relationshipQuery.relationshipId = relationship.id;
                            relationshipQuery.returnGeometry = true;
                            relationshipQuery.objectIds = [result.feature.attributes["OBJECTID"]];
                            // var relatedQueryTask = new QueryTask(this.url+"/"+result.layerId);

                            // relatedQueryTask.on("execute-relationship-query-complete", lang.hitch(this, function (relQueryResults) {
                            //     console.log('related result:', relQueryResults);
                            // }));
                            //
                            // relatedQueryTask.executeRelationshipQuery(relationshipQuery);

                            tableInfoDefList.push(this.loadLayerInfos(relationship.relatedTableId));
                        }));

                        all(tableInfoDefList).then(lang.hitch(this, function(relatedTableInfoResult){
                            for(var i =0; i < relatedTableInfoResult.length; i++){
                                var whereClause = this.buildWhereClauseForRelationship(relationships[i], identifyResult, relatedTableInfoResult);
                                //Si la where clause a bien été construite
                                if(whereClause != ""){
                                    relationshipDefList.push(this.query(relationships[i].relatedTableId, whereClause));
                                    recordedRelationships.push(relationships[i]);
                                }else{
                                    //Erreur lors de la création de la where clause, message d'erreur ?
                                }
                            }
                            //On construit la where clause
                            all(relationshipDefList).then(lang.hitch(this, function(relationshipQueryResults){
                                recordedRelationships;
                                for(var i = 0; i < relationshipQueryResults.length; i++){
                                    var relationshipResult = relationshipQueryResults[i];
                                    var keyField = recordedRelationships[i].keyField;
                                    var formatedRelationshipData = this.formatRelationshipData(relationshipResult);

                                    data.data[recordedRelationships[i].name] = [];
                                    for(var k in Object.keys(formatedRelationshipData)){
                                        if(k != 'contains'){
                                            data.data[recordedRelationships[i].name].push(formatedRelationshipData[k]);
                                        }
                                    }

                                    // if(data.data[attr]){
                                    //     if(!Array.isArray(data.data[attr])){
                                    //         data.data[attr] = [];
                                    //     }
                                    //     for(var k in Object.keys(formatedRelationshipData)){
                                    //         if(k != 'contains'){
                                    //             data.data[attr].push(formatedRelationshipData[k]);
                                    //         }
                                    //     }
                                    // }

                                }
                                def.resolve(data);
                            }))
                        }))
                        //DONE WITH BKA BUT DIDNT WORK
                        // //For each relationships of the service
                        // var relationships = this['layerInfoAsJson'][identifyResult.layerId].relationships;
                        // this.pending_relationship_query =relationships.length;
                        // array.forEach(relationships, lang.hitch(this, function(relationship){
                        //     var whereClause = this.buildWhereClauseForRelationship(relationship, identifyResult);
                        //     if(whereClause != ""){
                        //         var keyField = relationship.keyField;
                        //         this.query(relationship.relatedTableId, whereClause).then(lang.hitch(this,function(relationshipResult){
                        //             keyField
                        //             var formatedRelationshipData = this.formatRelationshipData(relationshipResult);
                        //             var attr = this.getAliasFromServer({name:keyField}, data);
                        //             if(data.data[attr]){
                        //                 data.data[attr] = formatedRelationshipData;
                        //             }
                        //             this.resolveTransformDefIfThereIsNoPendingQuery(def, data);
                        //         }),lang.hitch(this,function(){
                        //             this.resolveTransformDefIfThereIsNoPendingQuery(def, data);
                        //         }));
                        //     }else{
                        //         def.resolve(data);
                        //     }
                        // }));
                    }else{
                        def.resolve(data);
                    }
                }else{
                    def.resolve(data);
                }
                return def;
            },

            handleConfigRelations: function(identifyResult, data, transformDef){
                var layer = this.mapServiceLayers[identifyResult.layerId];
                if(layer && layer.fields && layer.fields.length > 0){
                    var manualRelations = [];
                    array.forEach(layer.fields, lang.hitch(this, function(field){
                        if(field.relations && field.relations.length > 0){
                            array.forEach(field.relations, lang.hitch(this, function(relation){
                                relation.fkProp = field.name;
                                manualRelations.push(relation);
                            }))
                        }
                    }))

                    //S'il y a des relations à gérer
                    if(manualRelations.length > 0){
                        //Pour toutes les relations
                        var relationshipsDefList = [];
                        var recordedRelation = [];
                        array.forEach(manualRelations, lang.hitch(this, function(relation){
                            //On construit le service qui va etre intérrogé dans le cadre de la relation
                            var relatedMapService = this.createServiceForRelation(relation);
                            //Si le service a bien été construit
                            if(relatedMapService){
                                var where = this.buildWhereClauseConfiguratedRelation(relation, identifyResult);
                                relationshipsDefList.push(relatedMapService.query(relation.layerId, where));
                                recordedRelation.push(relation);
                            }else{
                                //la relation n'est pas gérée, ajouter un message d'erreur ?
                            }
                        }))

                        all(relationshipsDefList).then(lang.hitch(this, function(relatedMapServiceQueryResuts){
                            recordedRelation;
                            for(var i = 0; i < relatedMapServiceQueryResuts.length; i++){
                                var queryResult = relatedMapServiceQueryResuts[i];
                                var relation = recordedRelation[i];
                                var formatedRelationshipData = this.formatRelationshipData(queryResult);
                                var attr = this.getAliasForField(relation.layerId, relation.fkProp);
                                if(data.data[attr]){
                                    data.data[attr] = formatedRelationshipData;
                                }
                            }
                            transformDef.resolve(data);
                        }))

                    }else{
                        transformDef.resolve(data);
                    }
                    //FAIT AVEC BKA, NE FONCTIONNAIT PAS: SOUCIS DE PROMISE NON RESOLUES
                    // if(manualRelations.length > 0){
                    //     this.pending_relationship_query = manualRelations.length;
                    //     array.forEach(manualRelations, lang.hitch(this, function(relation){
                    //         var relatedMapService =  this.createServiceForRelation(relation);
                    //         if(relatedMapService){
                    //             var where = this.buildWhereClauseConfiguratedRelation(relation, identifyResult);
                    //             relatedMapService.query(relation.layerId,where).then(lang.hitch(this, function(queryResult){
                    //                 var formatedRelationshipData = this.formatRelationshipData(queryResult);
                    //                 var attr = this.getAliasForField(relation.layerId, relation.fkProp);
                    //                 if(data.data[attr]){
                    //                     data.data[attr] = formatedRelationshipData;
                    //                 }
                    //                 this.resolveTransformDefIfThereIsNoPendingQuery(transformDef, data);
                    //             }))
                    //         }else{
                    //             this.resolveTransformDefIfThereIsNoPendingQuery(transformDef, data);
                    //         }
                    //     }))
                    // }else{
                    //     transformDef.resolve(data);
                    // }
                }else{
                    transformDef.resolve(data);
                }
            },

            resolveTransformDefIfThereIsNoPendingQuery: function(def, data){
                this.pending_relationship_query--;
                if(this.pending_relationship_query==0){
                    def.resolve(data);
                }
            },

            formatRelationshipData: function(relationshipResult){
                var data = [];
                var fields = relationshipResult.fields;
                if(relationshipResult.features && relationshipResult.features.length > 0){
                    array.forEach(relationshipResult.features, lang.hitch(this, function(feature){
                        fields;
                        relationshipResult;
                        if(feature.attributes){
                            var singleResult = {};
                            array.forEach(Object.keys(feature.attributes),lang.hitch(this, function(attr){
                                var alias = this.getAliasFromIdentiyResults(relationshipResult.fields, attr);
                                singleResult[alias] = feature.attributes[attr];
                            }))
                            data.push(singleResult);
                        }
                    }))
                }
                return data;
            },

            getAliasFromIdentiyResults: function(fieldsArray, attrName){
                var alias = attrName;
                if(fieldsArray && fieldsArray.length > 0){
                    array.forEach(fieldsArray, lang.hitch(this, function(field){
                        if(field.name == attrName){
                            alias = field.alias;
                        }
                    }))
                }
                return alias;
            },

            formatConfiguratedRelationshipData: function(relationshipResult){
                var data = [];
                if(relationshipResult && relationshipResult.length > 0){
                    array.forEach(relationshipResult, lang.hitch(this, function(relation){
                        if(relation.features && relation.features.length > 0){
                            array.forEach(relation.features, lang.hitch(this, function(feature){
                                if(feature.attributes){
                                    var singleResult = {};
                                    array.forEach(Object.keys(feature.attributes),lang.hitch(this, function(attr){
                                        singleResult[attr] = feature.attributes[attr];
                                    }))
                                    data.push(singleResult);
                                }
                            }))
                        }
                    }))
                }
                return data;
            },

            buildWhereClauseForRelationship: function (parentRelationship, identifyResult, childTableInfo) {

                var childRelationships = childTableInfo[0].relationships;

                if(childRelationships && childRelationships.length > 0){
                    var childKeyField = "";
                    var currentRelationship = childRelationships.find(
                        function(x){
                            return x.relatedTableId == identifyResult.layerId;
                        }
                    );
                    if(currentRelationship){
                        childKeyField = currentRelationship.keyField;
                    }

                    if(identifyResult && identifyResult.feature && identifyResult.feature.attributes){
                        var where = childKeyField + " = " +
                            identifyResult.feature.attributes[parentRelationship['keyField']];
                        return where;
                    }
                }


                return "";
            },

            query: function(layerId, whereClause){
                var query = new Query();
                query.where = whereClause;
                query.returnGeometry = true;
                query.outFields = ['*'];
                return new QueryTask(this.get('url')+'/'+layerId).execute(query);
            },

            buildWhereClauseConfiguratedRelation: function (relationship, identifyResult) {
                return ""+relationship.layerField+" = '" + identifyResult.feature.attributes[relationship.fkProp]+"'";
            },

            constructFieldValue: function(field, result) {
                var key = this.getAliasFromServer(field, result);
                return {key: field.alias ? field.alias : key, value: result.feature.attributes[key]}
            },


            getAliasForField: function(layerId, field){
                var layer = this.mapServiceLayers[layerId];
                if(layer && layer.fields){
                    var foundField = layer.fields.find(
                        function(x){
                            return x.name == field;
                        }
                    );
                    if(field){
                        return foundField.alias;
                    }else{
                        return field;
                    }
                }
            },




            /**
             * Identifie les données du service se situant à un certain endroit de la carte
             * @memberOf spw.api.MapService
             */
            identify: function(options, success, error) {
                var identifyParams = this.buildIdentifyParameters(options);
                var def = new Deferred();
                new IdentifyTask(this.get('url')).execute(identifyParams, lang.hitch(this, function(ir){
                    this.handleIdentifyResults(ir, def, options, success, identifyParams, options.allowRetryOnOffsetSymbolLayers);
                }), error);

                return def;
            },

            getAliasFromServer: function(field, result){
                if(this['layerInfoAsJson'] != null){
                    var layerInfo = this['layerInfoAsJson'][result.layerId];
                    if(layerInfo){
                        if (layerInfo.fields) {
                            var foundField = layerInfo.fields.find(
                                function(x){
                                    return x.name == field.name;
                                }
                            );
                            if(foundField){
                                return foundField.alias;
                            }else{
                                return field.alias;
                            }
                        } else {
                            return field.name;
                        }
                    }
                }else{
                    this.getLayerInfoAndSetLayerInfoAsJson(result.layerId);
                }
            },

            getLayerInfoAndSetLayerInfoAsJson: function(layerId) {
                var def = new Deferred();
                this.loadLayerInfos(layerId).then(lang.hitch(this,
                    function(res){
                        if(this['layerInfoAsJson'] == null){
                            this['layerInfoAsJson'] = [];
                        }
                        this['layerInfoAsJson'].push(res);
                        def.resolve(res);
                    }),
                    lang.hitch(this, function(err) {
                        def.reject();
                    })
                );
                return def;
            },

            getLayerExtent: function(layerId) {
                var def = new Deferred();
                if (this.layerInfoAsJson && this.layerInfoAsJson[layerId]) {
                    var extent = new Extent(this.layerInfoAsJson[layerId].extent);
                    def.resolve(extent);
                } else {
                    this.getLayerInfoAndSetLayerInfoAsJson(layerId).then(lang.hitch(this, function (res) {
                        def.resolve(new Extent(res.extent));
                    }))
                }
                return def;
            },

            createServiceForRelation: function(relation){
                var jsonService = ConfigLoader.getInstance().getService({'serviceId': relation.serviceId})[0];
                //si le service existe
                if(jsonService){
                    var mapService = this.spwMap.getMapServiceById(jsonService.serviceId);
                    if (mapService == null) {
                        lang.mixin(jsonService, {
                            spwMap: this.spwMap
                        });
                        mapService = require("spw/api/MapServiceFactory").createService(jsonService);
                        return mapService;
                    }
                } else {
                    console.log("Le service de la relation n'existe pas dans le catalogue", this);
                    return null;
                }
            },

            configuratedRelationQuery: function(relation, whereClause) {
                var query = new Query();
                query.where = whereClause;
                query.returnGeometry = true;
                query.outFields = ['*'];
                return new QueryTask(this.get('url')+'/'+relation.layerId).execute(query);
            },

//	         query: function(layerId, whereClause){
//                 var query = new Query();
//                 query.where = whereClause;
//                 query.returnGeometry = true;
//                query.outFields = ['*'];
//                return new QueryTask(this.get('url')+'/'+layerId).execute(query);
//             },

            // queryToService: function(relation){
            // 	var d = new Deferred();
            //      //rechercher le service de la relation dans la config
            //      var jsonService = ConfigLoader.getInstance().getService({'serviceId': relation.serviceId})[0];
            //
            //      //si le service existe
            //      if(jsonService){
            //          var mapService = this.spwMap.getMapServiceById(jsonService.serviceId);
            //          if (mapService == null) {
            //              lang.mixin(jsonService, {
            //                  spwMap: this.spwMap
            //              });
            //              mapService = require("spw/api/MapServiceFactory").createService(jsonService);
            //          }
            //          //construire la where clause
            //          var whereClause = relation.layerField  + ' = ' + result.feature.attributes[alias];
            //
            //          //interroger le service
            //          mapService.query(relation.serviceLayer, whereClause).then(lang.hitch(this, function(qr){
            //              //traiter le résultat
            //              this.handleSubqueryResult(qr, r, field, counter);
            //              d.resolve(r);
            //          }));
            //      } else {
            //          console.log("Le service de la relation n'existe pas dans le catalogue", this);
            //      }
            //      return d;
            //  },


            // handleTables: function(layerInfo, res, r, def){
            //     //initialiser le tableau contenant les tables dans le résultat
            //     r['_table'] = [], defList = [];
            //     //pour chaque table
            //     array.forEach(layerInfo.tables, lang.hitch(this, function(table){
            //     	defList.push(this.loadLayerInfos(table.id).then(lang.hitch(this, function(info){
            //             //intérroger le service de la table
            // 		if(info.relationships && info.relationships.length > 0){
            //
            //                 var defList = [];
            //
            //                 array.forEach(info.relationships, lang.hitch(this, function(relation){
            // 		        defList.push(this.relatedQueryToTable(info, r, def, table, res, info.relationships[0].keyField));
            //                 }));
            //
            //                 all(defList, lang.hitch(this, function() {
            //                     return defList;
            //                 }));
            //
            // 			// return this.relatedQueryToTable(info, r, def, table, res, info.relationships[0].keyField);
            // 		}
            //         })));
            //     }));
            //     if(defList && defList.length > 0){
            //         all(defList, function(){
            //         });
            //     } else {
            //     	def.resolve({layerId: res.layerId, data: r});
            //     }
            // },

            // relatedQueryToTable: function(info, r, def, table, res, keyfield){
            //     //si le service possède des relations
            //     if(info.relationships != null && info.relationships.length > 0){
            //         //intérroger le service sur base de la FK 'ID_SITE_SPW'
            //
            //         return this.relatedQuery(table.id, res.feature.attributes[keyfield], keyfield)
            //             .then(lang.hitch(this, function(answer){
            //                 //pousser le résultat de la query dans r
            //                 answer['_displayPaneName'] = answer.displayFieldName;
            //                 r['_table'].push(answer);
            //                 var data = {layerId: res.layerId, data: r};
            //                 def.resolve(data);
            //             }))
            //     } else {
            //     	var d = new Defered();
            //     	d.resolve();
            //     	return d;
            //     }
            // },



            // getServerAliasForField:function(layerInfo, fieldName) {
            //     var returnValue = null;
            //     if(layerInfo && layerInfo.fields && layerInfo.fields.length > 0){
            //         array.some(layerInfo.fields, lang.hitch(this, function(field){
            //             if(field.name == fieldName){
            //                 returnValue = field.alias;
            //                 return true;
            //             }
            //         }))
            //     }
            //     return returnValue;
            // },

            // queryToService: function(field, relationSize, counter, relation, result, alias, r, def){
            //     //rechercher le service de la relation dans la config
            //     var jsonService = ConfigLoader.getInstance().getService({'serviceId': relation.serviceId})[0];
            //
            //     //si le service existe
            //     if(jsonService){
            //         var mapService = this.spwMap.getMapServiceById(jsonService.serviceId);
            //         if (mapService == null) {
            //             lang.mixin(jsonService, {
            //                 spwMap: this.spwMap
            //             });
            //             mapService = require("spw/api/MapServiceFactory").createService(jsonService);
            //         }
            //         //construire la where clause
            //         var whereClause = relation.layerField  + ' = ' + result.feature.attributes[alias];
            //         //interroger le service
            //         var d = new Deferred();
            //         mapService.query(relation.serviceLayer, whereClause).then(lang.hitch(this, function(qr){
            //             //traiter le résultat
            //             this.handleSubqueryResult(qr, r, field, counter);
            //             d.resolve(r);
            //         }));
            //         return d;
            //     } else {
            //         console.log("Le service de la relation n'existe pas dans le catalogue", this);
            //     }
            // },

            // var data = [], defList = [];
            // array.forEach(identifyResults, lang.hitch(this, function(result){
            //     var d = this.transformIdentifyResult(result, options).then(function(r){
            //         if(r instanceof Array){
            //             array.forEach(r, lang.hitch(this, function(d){
            //                 data.push(d);
            //             }))
            //         }else{
            //             data.push(r);
            //         }
            //
            //     });
            //     defList.push(d);
            // }));
            //
            // if(defList && defList.length){
            //     all(defList).then(lang.hitch(this, function(defs){
            //         if(success) success(identifyResults, this, data);
            //         def.resolve(identifyResults, this, data);
            //     }));
            // } else {
            //     if(success) success(identifyResults, this, data);
            //     def.resolve(identifyResults, this, data);
            // }

            // constructFieldValue:function(field, layerInfo, r, result, options, counter, def){
            //     var defered = new Deferred();
            //     var alias = field.alias ? field.alias :  this.getAliasFieldNameFromFieldsArray(field.name, layerInfo.fields);
            //     //si le field a des relations
            //     var _result = result;
            //     var _layerInfo = layerInfo;
            //     if(field.relations){
            //         r['_relationship'] = [], defs = [];
            //         var relationSize = field.relations.length;
            //         array.forEach(field.relations, lang.hitch(this, function(relation, idx){
            //             //construire le service et l'intérroger
            //             defs.push(this.queryToService(field, relationSize, idx, relation, _result, alias, r, def))
            //         }));
            //         all(array.filter(defs, function(d){ return d; })).then(function(){
            //
            //             array.forEach(_layerInfo.fields, lang.hitch(this, function(serviceField){
            //                 field, r;
            //                 if(serviceField.name == field.name){
            //                     r[serviceField.alias] = field['relations'];
            //                     r[serviceField.alias] = _result.feature.attributes[serviceField.alias]
            //                     r['Relations:'] = r['_relationship'];
            //                 }else{
            //                     r[serviceField.alias] = _result.feature.attributes[serviceField.alias];
            //                 }
            //             }))
            //             delete r['_relationship'];
            //             var data = {layerId: _result.layerId, data:r};
            //             defered.resolve(data);
            //         });
            //     } else {
            //         r[alias] = _result.feature.attributes[this.getServerAliasForField(layerInfo,field.name)];
            //         var data = {layerId: _result.layerId, data: r};
            //         defered.resolve(data);
            //     }
            //
            //     if (options.ignoreFields && options.ignoreFields.indexOf(field.name) > -1) {
            //         return;
            //     }
            //     return defered;
            // },

            // transformIdentifyResult: function (result, options) {
            //     var def = new Deferred(), r = {};
            //     var spwLayer = this.mapServiceLayers[result.layerId];
            //
            //     var res = result;
            //
            //     /*si fields définis dans la config*/
            //     if(spwLayer && spwLayer.fields){
            //         //charge les infos du layer
            //         this.loadLayerInfos(result.layerId).then(lang.hitch(this, function(layerInfo){
            //             //pour chaque field,
            //             layerInfo;
            //             var counter = 0;
            //             var data = {};
            //             var defs = [];
            //             array.forEach(spwLayer.fields, lang.hitch(this, function(field){
            //                 defs.push(this.constructFieldValue(field, layerInfo, r, res, options, counter, def));
            //                 // this.constructFieldValue(field, layerInfo, r, res, options, counter, def);
            //             }));
            //             all(defs).then(lang.hitch(this, function(e){
            //                 def.resolve(e);
            //             }))
            //         }));
            //     } else {
            //         //si fields n'est pas définis
            //         //lire les informations du service
            //         this.loadServiceInfos().then(lang.hitch(this, function(layerInfo){
            //             //si le layer possède des tables
            //             for (var key in result.feature.attributes) {
            //                 if (options.ignoreFields && options.ignoreFields.indexOf(key) > -1) continue;
            //                 r[key] = result.feature.attributes[key];
            //             }
            //
            //             if(layerInfo.tables && layerInfo.tables.length > 0){
            //                 this.handleTables(layerInfo, res, r, def);
            //             } else {
            //                 var data = {layerId: result.layerId, data: r};
            //                 def.resolve(data);
            //             }
            //         }));
            //     }
            //     return def;
            // },

            // handleSubqueryResult: function(qr, r, field,counter){
            //     qr._displayPaneName = field.relations[counter].displayPaneName;
            //     r['_relationship'].push(qr);
            // },

            // getAliasFieldNameFromFieldsArray: function(name, fields){
            //     for(var key in fields){
            //         if(fields[key].name === name){
            //             return fields[key].alias;
            //         }
            //     }
            //     return name;
            // },
            //
            // relatedQuery: function(layerId, objectId, keyfield) {
            //     var whereClause = keyfield +" = " + objectId;
            //     var query = new Query();
            //     query.where = whereClause;
            //     query.returnGeometry = true;
            //     query.outFields = ['*'];
            //     query.relationParam = layerId;
            //     return new QueryTask(this.get('url')+'/'+layerId).execute(query);
            // },

            /**
             * Appelé lorsque le layer principal est chargé avec succés.
             * @param loadedEvent
             */
            layerLoaded: function(loadedEvent) {
                if (this.get('imageParameters') == null) {
                    array.forEach(loadedEvent.layer.layerInfos, lang.hitch(this, function(layerInfo) {
                        this._mergeLayerInfo(layerInfo);
                    }));

                    this._afterLayerLoaded();
                }
            },



            baseMapLayerLoaded: function(loadedEvent) {
                if(this.copyright){
                    this.layer.copyright = this.copyright;
                }
                else {
                    this.layer.copyright = this.layer.copyright;
                }

                if(this.maxScale != null && this.maxScale > -1) {
                    this.layer.maxScale=this.maxScale;
                }

                if(this.minScale != null && this.minScale > -1) {
                    this.layer.minScale=this.minScale;
                }

                if (this.get('imageParameters') == null) {
                    array.forEach(loadedEvent.layer.layerInfos, lang.hitch(this, function (layerInfo) {
                        this._mergeLayerInfo(layerInfo);
                    }));

                    this.refreshLayersVisibility();
                }
            }

        });

        return DynamicMapService;

    });