Source: api/Utils.js

Retour à la documentation
/**
 * @class spw.api.Utils
 * @classdesc Elément UI définissant la barre d'outil standard du viewer.
 */
define(["dojo/_base/declare", "dojo/_base/array", "dojo/_base/lang",
        "dojo/promise/all", "dojo/Deferred", "dojo/on", "spw/api/ProjectionManager",
        "esri/tasks/IdentifyTask", "esri/tasks/IdentifyParameters", "spw/api/GeometryUtils",
        "spw/api/MessageManager", "spw/libs/shp", "esri/request"],
    /** @lends spw.api.Utils.prototype */
    function (declare, array, lang, all, Deferred, on, ProjectionManager, IdentifyTask,
              IdentifyParameters, GeometryUtils, MessageManager, shp, request) {
        var Utils = declare("spw.api.Utils", null, {});

        /**
         * Génère un id unique
         */
        Utils.guid = function () {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        };

        /**
         * Récupère un paramètre d'url
         * @memberof spw.api.Utils
         * @param {String} name le nom de paramètre.
         * @param {String} url URL dans laquelle chercher.
         * @returns {String} La valeur du paramètre trouvé. Si pas trouvé, retourne "".
         */
        Utils.gup = function (name, url) {
            name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\?&]" + name + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(url || window.location.href);
            if (results == null)
                return "";
            else
                return results[1];
        };

        /**
         * Crée un paramètre d'url. Attention, cette fonction provoque un rechargement de la page.
         * @memberof spw.api.Utils
         * @param {String} name le nom de paramètre.
         * @param {String} value la valeur du paramètre.
         */
        Utils.sup = function (name, value) {
            var hashToKeep = window.location.hash.toString();
            var currentUrl = window.location.href.toString().substring(0, window.location.href.toString().indexOf("#", 0));
            var modifiedUrl = currentUrl;

            if (currentUrl.indexOf("&" + name + "=") != -1 || currentUrl.indexOf("?" + name + "=") != -1) {
                var paramStartIndex = currentUrl.indexOf(name + "=");
                var paramEndIndex = currentUrl.indexOf("&", paramStartIndex);
                modifiedUrl = currentUrl.substr(0, paramStartIndex - 1);
                if (paramEndIndex != -1) {
                    modifiedUrl += ("?" + currentUrl.substr(paramEndIndex + 1));
                }
            }
            var paramSeparator = "&";
            if (modifiedUrl.indexOf("?") == -1) {
                paramSeparator = "?";
            }
            modifiedUrl += (paramSeparator + name + "=" + value);

            window.location.href = modifiedUrl + hashToKeep;
        };

        /**
         * Ajoute une variable d'anchor à partir d'une chaine de caractère.
         * @memberof spw.api.Utils
         * @param {String} key le nom de paramètre.
         * @param {String} value la valeur du paramètre.
         * @param {String} strSource la chaine de caractère source.
         * @returns {String} une nouvelle chaine de caractère contenant la paramètre ajouté.
         */
        Utils.addAnchor = function (key, value, strSource) {
            var currentHash = strSource;
            var modifiedHash = currentHash;

            if (currentHash.indexOf("#" + key + "=") != -1) {
                var paramStartIndex = currentHash.indexOf("#" + key + "=");
                var paramEndIndex = currentHash.indexOf("#", paramStartIndex + 1);
                modifiedHash = currentHash.substr(0, paramStartIndex);
                if (paramEndIndex != -1) {
                    modifiedHash += currentHash.substr(paramEndIndex);
                }
            }
            modifiedHash += ("#" + key + "=" + value);
            return modifiedHash;
        };

        /**
         * Récupère la valeur d'un paramètre d'anchor dans une chaine de caractère.
         * @memberof spw.api.Utils
         * @param {String} key le nom de paramètre.
         * @param {String} strSource la chaine de caractère source.
         * @returns {String} La valeur du paramètre trouvé. Si pas trouvé, retourne "".
         */
        Utils.getAnchor = function (key, strSource) {
            key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]").replace(/\|/gim, '\\|');
            var regexS = "[\\#]" + key + "=(((?!\#[^#^=]*=).)*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(strSource);
            if (results == null)
                return "";
            else
                return results[1];
        };

        /**
         * Retire un paramètre d'anchor d'une chaine de caractère source.
         * @memberof spw.api.Utils
         * @param {String} key le nom de paramètre.
         * @param {String} strSource la chaine de caractère source.
         * @returns {String} la nouvelle chaine de caractère constituée.
         */
        Utils.removeAnchor = function (key, strSource) {
            key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\#]" + key + "=(((?!\#[a-zA-Z0-9]*=).)*)";
            var regex = new RegExp(regexS);
            var result = strSource.replace(regex, "");
            if (!result)
                return "";
            else
                return result;
        };

        /**
         * Retire un paramètre d'anchor de l'url.
         * @memberof spw.api.Utils
         * @param name le nom de paramètre.
         */
        Utils.rua = function (name) {
            if (window.location.hash.toString()) {
                var modifiedHash = Utils.removeAnchor(name, window.location.hash.toString());
                window.location.hash = modifiedHash;
                window.location.assign(window.location);
            }
        };

        /**
         * Récupère un paramètre d'anchor de l'url.
         * @memberof spw.api.Utils
         * @param name le nom de paramètre.
         * @returns {String} La valeur du paramètre trouvé. Si pas trouvé, retourne "".
         */
        Utils.gua = function (name) {
            return Utils.getAnchor(name, window.location.hash.toString());
        };

        /**
         * Ajoute une variable d'anchor dans l'url.
         * @memberof spw.api.Utils
         * @param {String} name le nom de paramètre.
         * @param {String} value la valeur du paramètre.
         */
        Utils.sua = function (name, value) {
            var modifiedHash = Utils.addAnchor(name, value, window.location.hash.toString());
            window.location.hash = modifiedHash;
            window.location.assign(window.location);
        };

        /**
         * Retire les accents d'une chaine de caractère.
         * @memberof spw.api.Utils
         * @param {String} s la chaine de caractère.
         * @return {String} la nouvelle chaine de caractère sans accents.
         */
        Utils.removeAccent = function (s) {
            if (s == null || typeof s.toLowerCase == 'undefined') {
                return s;
            }
            var r = s.toLowerCase();
            r = r.replace(new RegExp("\\s", 'g'), "");
            r = r.replace(new RegExp("[àáâãäå]", 'g'), "a");
            r = r.replace(new RegExp("æ", 'g'), "ae");
            r = r.replace(new RegExp("ç", 'g'), "c");
            r = r.replace(new RegExp("[èéêë]", 'g'), "e");
            r = r.replace(new RegExp("[ìíîï]", 'g'), "i");
            r = r.replace(new RegExp("ñ", 'g'), "n");
            r = r.replace(new RegExp("[òóôõö]", 'g'), "o");
            r = r.replace(new RegExp("œ", 'g'), "oe");
            r = r.replace(new RegExp("[ùúûü]", 'g'), "u");
            r = r.replace(new RegExp("[ýÿ]", 'g'), "y");
            r = r.replace(new RegExp("\\W", 'g'), "");
            return r;
        };

        Utils.cleanUrl = function () {
            return window.location.href.replace(window.location.hash, '');
        };

        /**
         * Retourne l'élement DOM qui est la cible d'un évènement DOM.
         * @memberof spw.api.Utils
         * @param {Object} eventObject l'objet DOMEvent
         * @returns {Object} le DOMElement cible de l'évènement.
         */
        Utils.getEventTarget = function (eventObject) {
            var targ = {};
            if (!eventObject) {
                eventObject = window.event;
            }
            if (eventObject.target) {
                targ = eventObject.target;
            }
            else if (eventObject.srcElement) {
                targ = eventObject.srcElement;
            }
            if (targ.nodeType == 3) {
                targ = targ.parentNode;
            }
            return targ;
        };

        /**
         * Fusionne un template avec un objet Feature (Graphic).
         * @memberof spw.api.Utils
         * @param {String} template le template
         * @param {Object} objet feature contenant des attributs.
         * @returns {String} le template fusionné avec les valeurs attributaires.
         */
        Utils.mergeTemplateWithFeature = function (template, feature) {
            var regExp = new RegExp("\\$\\{.[^\\}]+\\}");
            while (regExp.test(template)) {
                var matches = regExp.exec(template);
                for (var i = 0; i < matches.length; i++) {
                    var prop = matches[i].substring(2, matches[i].length - 1);
                    template = template.replace(matches[i], feature.attributes[prop]);
                }
            }
            return template;
        };

        /**
         * Récupère un sous-ensemble d'élément dans un tableau sur base d'un objet query.
         * @memberof spw.api.Utils
         * @param {Array.<Object>} list la liste des éléments dans lesquels effectuer la recherche.
         * @param {Object} queryObject un object javascript standard contenant des combinaisons clé-valeurs sur lesquels effectuer la commparaison avec les éléments dans la liste.
         * @param {Array.<Object>} la liste de éléments correspondants.
         */
        Utils.findInList = function (list, queryObject) {
            if (!list || !list.length > 0) return [];

            var matchedElements = [];
            array.forEach(list, function (element) {
                var queryObjectValid = true;
                if (queryObject) {
                    for (var prop in queryObject) {
                        if (element[prop] !== queryObject[prop]) {
                            queryObjectValid = false;
                            break;
                        }
                    }
                }
                if (queryObjectValid) {
                    matchedElements.push(element);
                }
            });
            return matchedElements;
        };

        /**
         * Récupère un sous-ensemble d'élément dans un objet sur base d'un objet query.
         * @memberof spw.api.Utils
         * @param {Object} list l'objet dans lequel effectuer la recherche.
         * @param {Object} queryObject un object javascript standard contenant des combinaisons clé-valeurs sur lesquels effectuer la comparaison avec les épropriété de l'objet.
         * @param {Array.<Object>} la liste de éléments correspondants.
         */
        Utils.findInObject = function (list, queryObject) {
            var matchedElements = [];
            var element = null;
            var queryObjectValid = null;

            for (var key in list) {
                if (!list.hasOwnProperty(key)) {
                    continue;
                }

                element = list[key];
                queryObjectValid = true;

                if (queryObject) {
                    for (var prop in queryObject) {
                        if (queryObject.hasOwnProperty(prop)) {
                            var toCmp = queryObject[prop];

                            if (lang.isArray(toCmp)) {
                                if (toCmp.indexOf(element[prop]) < 0) {
                                    queryObjectValid = false;
                                }
                            }
                            else {
                                queryObjectValid = (element[prop] === toCmp);
                            }
                            break;
                        }
                    }
                }

                if (queryObjectValid) {
                    matchedElements.push(element);
                }
            }

            return matchedElements;
        };

        /**
         * Vérifie si deux objets sont égaux (si toutes leurs propriétés possèdent la même valeur respective).
         * @memberof spw.api.Utils
         * @param x le premier objet.
         * @param y le second objet.
         * @return true si les objets sont identiques, false si les objets sont différents
         */
        Utils.objectsEquals = function (x, y) {
            if (x && y) {
                for (var p in y) {
                    if (typeof(y[p]) !== typeof(x[p])) return false;
                    if ((y[p] === null) !== (x[p] === null)) return false;
                    switch (typeof(y[p])) {
                        case 'undefined':
                            if (typeof(x[p]) != 'undefined') return false;
                            break;
                        case 'object':
                            return Utils.objectsEquals(x[p], y[p]);
                            break;
                        default:
                            if (y[p] !== x[p]) return false;
                    }
                }
                return true;
            }
            else {
                return false;
            }
        };

        /**
         * Converti une image depuis une URL vers sa représentation en base64.
         * @param url l'url de l'image à convertir
         * @param outputFormat le format de l'image désiré
         * @param callback la méthode à appelé une fois la conversion effectuée
         */
        Utils.imgToBase64 = function (url, outputFormat, callback) {
            var img = new Image();
            img.crossOrigin = 'anonymous';
            img.onload = function () {
                var canvas = document.createElement('CANVAS');
                var ctx = canvas.getContext('2d');
                var dataURL;
                canvas.height = this.height;
                canvas.width = this.width;
                ctx.drawImage(this, 0, 0);
                dataURL = canvas.toDataURL(outputFormat);
                callback(dataURL);
                canvas = null;
            };
            img.src = url;
        };

        /**
         * Permet de déterminé le séparateur utilisé dans un CSV
         * @param {string} string une chaine de caractère provenant d'un CSV
         * @return le dit séparateur
         */
        Utils.getSeparator = function(string) {
            var separators = [",", "      ", ";", "|"];
            var maxSeparatorLength = 0;
            var maxSeparatorValue = "";
            array.forEach(separators, function (separator) {
                var length = string.split(separator).length;
                if (length > maxSeparatorLength) {
                    maxSeparatorLength = length;
                    maxSeparatorValue = separator;
                }
            });
            return maxSeparatorValue;
        },


            Utils.jsonToCSV = function(jsonObjects) {
                var json = jsonObjects;
                var fields = Object.keys(json[0])
                var replacer = function(key, value) { return value === null ? '' : value }
                var csv = json.map(function(row){
                    return fields.map(function(fieldName){
                        return JSON.stringify(row[fieldName], replacer)
                    }).join(';')
                });
                csv.unshift(fields.join(';'));
                var stringCSV = '';
                array.forEach(csv, lang.hitch(this, function(row) {
                    stringCSV += row + '\n';
                }));
                return stringCSV;
            },


            /**
             * Convertit un string au format CSV vers le format JSON
             * @param {string} csvString la chaine de caractère à convertir
             * @return un objet JSON correspondant au CSV
             */
            Utils.csvToJson = function (csvString) {
                var delimiter = csvString.indexOf('\r') < 0 ? '\n' : '\r\n';

                var lines = csvString.split(delimiter), json = [];
                var sep = Utils.getSeparator(lines[0]);

                if (lines && lines.length > 0) {
                    var fields = lines[0].split(sep);

                    for (var i = 1; i < lines.length; i++) {
                        var struct = {}, lFields = lines[i].split(sep);
                        if (lines[i].length > 0) {
                            array.forEach(fields, function (f, idx) {
                                struct[f] = lFields[idx];
                            });
                            json.push(struct);
                        }
                    }
                }
                return json;
            };

        /**
         * Formate une distance en mètres vers son équivalent en kilomètres si elle est supérieure à 1000 mètres
         * @param {number} distance la distance à formatter
         * @return la distance formatée
         */
        Utils.toDistanceString = function (distance) {
            if (distance > 1) {
                return (Math.round(distance * 100) / 100) + " km";
            }
            else {
                return Math.round((distance * 1000)) + " m";
            }
        };


        /**
         * Formate une mesure de temps en format string
         * @param {number} duree la durée à formatter
         * @return la durée formatée
         */
        Utils.toDureeString = function (duree, locale) {
            locale = locale.toLowerCase();
            var secs = duree * 60;
            var hours = Math.floor(secs / (60 * 60));

            var divisor_for_minutes = secs % (60 * 60);
            var minutes = Math.floor(divisor_for_minutes / 60);

            var divisor_for_seconds = divisor_for_minutes % 60;
            var seconds = Math.ceil(divisor_for_seconds);

            var ret = "";
            if (hours != 0) {
                ret += hours;
                if (hours > 1) {
                    ret += " " + (locale == "fr" ? "heures" : "Stunden") + " ";
                }
                else {
                    ret += " " + (locale == "fr" ? "heure" : "Stunde") + " ";
                }
            }
            if (minutes != 0 || hours != 0) {
                ret += minutes;
                if (minutes > 1) {
                    ret += " " + (locale == "fr" ? "minutes" : "Minuten") + " ";
                }
                else {
                    ret += " " + (locale == "fr" ? "minute" : "Minute") + " ";
                }
            }
            if (seconds != 0 && hours == 0) {
                ret += seconds;
                if (seconds > 1) {
                    ret += " " + (locale == "fr" ? "secondes" : "Sekunden");
                }
                else {
                    ret += " " + (locale == "fr" ? "seconde" : "Sekunde");
                }
            }
            return ret;
        };


        /**
         * Formatte les légendes d'une liste de services pour les envoyer au template JASPER
         * @param servicesToPrint la liste des services cartos dont il faut imprimer la légende
         * @param spwViewer la référence au SpwViewer
         * @return une liste contenant la légende des services formatée pour être compréhensible par le template JASPER
         */
        Utils.getPrintableLegendForServices = function(servicesToPrint, spwViewer){
            var globalDef = new Deferred();
            var data = [];

            if(!servicesToPrint || servicesToPrint.length <= 0){
                globalDef.resolve({Data: data});
                return globalDef;
            }
            Utils.loadLegends(servicesToPrint).then(lang.hitch(this, function(){
                array.forEach(servicesToPrint, lang.hitch(this, function(serv){
                    data.push({
                        label: serv.label,
                        level: 0,
                        symbol:''
                    });
                    if(serv.mapServiceLayers){
                        Utils.reorderLegendData(serv.mapServiceLayers, 1, data);
                    }
                }));
                Utils.changeUrlToImageData(data, spwViewer).then(lang.hitch(this, function(){
                    globalDef.resolve({Data:data});
                }));
            }));
            return globalDef;
        };

        /**
         * Ordonne la légende des services sur base de l'ordre des services sur la carte
         * @param layers la distance à formatter
         * @param {number} level le niveau de la donnée dans le template JASPER
         * @param data la liste des données formatées pour le template JASPER
         * @return la distance formattée
         */
        Utils.reorderLegendData = function(layers, level, data){
            if(layers){
                var keys = Object.keys(layers);
                array.forEach(keys, lang.hitch(this, function(k){
                    var layer = layers[k];
                    if (layer.get('inTOC')) {
                        data.push({
                            level: level,
                            label: layer.name,
                            symbol: ''
                        });
                        if(layer.legends){
                            array.forEach(layer.legends, lang.hitch(this, function(legend){
                                data.push({
                                    level: level+1,
                                    label: legend.label,
                                    symbol: legend.url.indexOf('http') > -1 ? legend.url : legend.imageData
                                })
                            }));
                        }
                        if(layer.subLayers){
                            Utils.reorderLegendData(layer.subLayers, level+1, data);
                        }
                    }
                }))
            }
        };

        /**
         * Convertit les images des services WMS en base64
         * @param data la liste des légendes formatées pour le template JASPER
         * @param spwViewer la référence au SpwViewer
         */
        Utils.changeUrlToImageData = function(data, spwViewer){
            var transformPictureDefs = [], def = new Deferred();
            array.forEach(data, lang.hitch(this, function(d){
                if(d.symbol.indexOf('http') > -1) {
                    var def = new Deferred(); transformPictureDefs.push(def);
                    var img = new Image();
                    img.crossOrigin = 'Anonymous';
                    img.onload = lang.hitch(this, function(){
                        var canvas = document.createElement('CANVAS'), ctx = canvas.getContext('2d'), dataURL;
                        canvas.height = img.height;
                        canvas.width = img.width;
                        ctx.drawImage(img, 0, 0);
                        dataURL = canvas.toDataURL('image/png');
                        d.symbol = Utils.getBase64dataFromUrl(dataURL);
                        canvas = null;
                        def.resolve();
                    });
                    img.onerror = lang.hitch(this, function(){
                        //white pixel image: couldn't load legend image
                        d.symbol = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=';
                        def.resolve();
                    });
                    img.src = spwViewer.get('proxyPageUrl') + '?' + d.symbol;
                }
            }));

            if(transformPictureDefs.length > 0) {
                all(transformPictureDefs).then(function () {
                    def.resolve();
                });
            } else {
                def.resolve();
            }
            return def;
        };

        /**
         * Charge la légende d'un service
         * @param servicesToPrint le service dont il faut charger la légende
         */
        Utils.loadLegends = function(servicesToPrint){
            var loadLegendPromises = [], def = new Deferred();
            array.forEach(servicesToPrint, lang.hitch(this, function(serv){
                var def = new Deferred();
                loadLegendPromises.push(def);
                if (!serv.get('legendLoaded')) {
                    on.once(serv, serv.events.MapServiceLegendLoaded, lang.hitch(this, function(){
                        def.resolve();
                    }));
                    serv.loadLegend();
                }
                else {
                    def.resolve();
                }
            }));
            if(loadLegendPromises.length > 0) {
                all(loadLegendPromises).then(lang.hitch(this, function() {
                    def.resolve();
                }));
            } else {
                def.resolve();
            }
            return def;
        };


        /**
         * Identifie les services et convertit les résultats au format JASPER
         * @param spwViewer la référence au SpwViewer
         * @param reportParams les paramètres du rapport JASPER
         * @param {boolean} printLegend définit s'il faut imprimer la légende ou pas
         */
        Utils.identifyResultsToReportFormat = function (spwViewer, reportParams, printLegend) {

            printLegend = printLegend != null ? printLegend : true;

            var globalDef = new Deferred();

            var Data = {
                Data: []
            };
            var Properties = {};
            var promise = new Deferred();
            var mapServices = spwViewer.get('spwMap').getMapServices({
                isBaseMap: false,
                visible: true
            });
            var legPromises = array.map(mapServices, lang.hitch(this, function(mapService){
                var p = new Deferred();

                if(printLegend){
                    Data.Data.push({
                        level: 0,
                        label: mapService.get('label'),
                        symbol: ""
                    });
                }


                var loopThroughLayers = function() {
                    var loopThroughLayersPromises = [];
                    array.forEach(mapService.get('mapServiceLayers'), lang.hitch(this, function(subLayer){
                        if(!subLayer.parentLayer) {
                            var def = new Deferred();
                            loopThroughLayersPromises.push(def);
                            Utils.recurseLayers(subLayer, 1).then(lang.hitch(this, function(res){
                                Data.Data = Data.Data.concat(res);
                                def.resolve();
                            }))
                        }
                    }));
                    if(loopThroughLayersPromises.length > 0){
                        all(loopThroughLayersPromises).then(lang.hitch(this, function(e){
                            p.resolve();
                        }))
                    }else{
                        p.resolve();
                    }
                }.bind(this);

                if(printLegend){
                    if (!mapService.get('legendLoaded')) {
                        on.once(mapService, mapService.events.MapServiceLegendLoaded, lang.hitch(this, loopThroughLayers));
                        mapService.loadLegend();
                    }
                    else {
                        loopThroughLayers();
                    }
                }else{
                    p.resolve();
                }

                return p;
            }));
            all(legPromises).then(lang.hitch(this, function() {
                promise.resolve();
            }));
            promise.then(lang.hitch(this, function() {
                var promises = [];

                for (var key in reportParams) {
                    var templateData = {};

                    if (reportParams.hasOwnProperty(key)) {
                        var p = new Deferred();
                        promises.push(p);

                        var value = templateData[key] || reportParams[key];

                        if ((/\.(gif|jpg|jpeg|tiff|png)$/i).test(value)) {
                            var splitted = value.split('.');
                            var ext = splitted[splitted.length - 1];

                            (function (tmp, k) {
                                Utils.imgToBase64(value, ext, function (image) {
                                    Properties[k] = image.substring(image.indexOf(",") + 1);
                                    tmp.resolve();
                                });
                            })(p, key);
                        }
                        else {
                            Properties[key] = value;
                            p.resolve();
                        }
                    }
                }
                globalDef.resolve(Data);
            }));
            return globalDef;
        };

        /**
         * Parcourt tous les sous layers du service afin de télécharger les légendes correspondates
         * @param layer le service dont il faut télécharger la légende
         * @param level le niveau JASPER de la donnée
         */
        Utils.recurseLayers = function(layer, level){
            var recurseLayerDef = new Deferred();
            if(layer.subLayers && layer.subLayers.length > 0){
                var l = [];
                var promises = [];
                array.forEach(layer.subLayers, lang.hitch(this, function(subLayer){
                    var def = new Deferred();
                    promises.push(def);
                    Utils.recurseLayers(subLayer, level + 1).then(lang.hitch(this, function(res){
                        l = l.concat(res);
                        def.resolve();
                    }))
                }));
                if(promises.length > 0){
                    all(promises).then(lang.hitch(this, function(){
                        recurseLayerDef.resolve(l);
                    }))
                }else{
                    recurseLayerDef.resolve(l);
                }
                return recurseLayerDef;
            } else {
                var legs = [{level:level, label:layer.get('name'),symbol:""}];
                var promises = [];
                array.forEach(layer.get('legends'), lang.hitch(this, function(leg){
                    var def = new Deferred();
                    promises.push(def);
                    if(leg.url.indexOf('http') > -1){
                        var img = new Image();
                        img.crossOrigin = 'Anonymous';
                        img.onload = lang.hitch(this, function(){
                            var canvas = document.createElement('CANVAS'),
                                ctx = canvas.getContext('2d'), dataURL;
                            canvas.height = img.height;
                            canvas.width = img.width;
                            ctx.drawImage(img, 0, 0);
                            dataURL = canvas.toDataURL('image/png');
                            leg.imageData = Utils.getBase64dataFromUrl(dataURL);
                            canvas = null;
                            legs.push({
                                level:level+1,
                                label:(leg.label ? leg.label : layer.get('name')),
                                symbol: leg.imageData
                            });
                            def.resolve();
                        });
                        img.src = 'proxy.jsp?'+leg.url;
                    }else{
                        legs.push({
                            level:level+1,
                            label:(leg.label ? leg.label : layer.get('name')),
                            symbol: leg.imageData
                        });
                        def.resolve();
                    }
                }));

                if(promises.length > 0){
                    all(promises).then(lang.hitch(this, function(res){
                        recurseLayerDef.resolve(legs);
                    }))
                }else{
                    recurseLayerDef.resolve(legs);
                }

                return recurseLayerDef;
            }
        };

        /**
         * Convertit une url d'image en représentation base64
         * @param url l'URL de la photo à convertir
         * @return la base64 de l'image
         */
        Utils.getBase64dataFromUrl = function(url){
            if(url && url.indexOf('base64,')>-1){
                return url.substr(url.indexOf('base64,')+7);
            }
        };

        /**
         * Construit une liste d'objet à envoyer au template JASPER pour construire le rapport
         * @param globalIdentifyResults les résultats du carrottage à convertir
         * @param Data les paramètres à appliquer au rapport
         * @return un tableau contenant les résultats formatés et l'objet Data
         */
        Utils.buildRapportResults = function(globalIdentifyResults, Data) {
            var _currentReportResults = [];
            if(globalIdentifyResults){
                globalIdentifyResults.forEach(lang.hitch(this, function(data){
                    if(data.results && data.results.length > 0){
                        _currentReportResults.push({level: -1, label: data.service.label, value: ""});
                        data.results.forEach(lang.hitch(this, function(result, idx){
                            var layerName = result.layerName != null ? result.layerName : data.service.mapServiceLayers[result.layerId].name;
                            _currentReportResults.push({level: -2, label: layerName, value: ""});
                            for(var key in data.data[idx].data){
                                var v = data.data[idx].data[key];
                                _currentReportResults.push({level: -3, label: key, value: v});
                            }
                        }))
                    }
                }))
            }

            if(_currentReportResults.length > 0) {
                if (_currentReportResults && _currentReportResults.length > 0) {
                    _currentReportResults.push({
                        level: -3,
                        label: 'break',
                        value: ''
                    })
                    Data.Data = _currentReportResults.concat(Data.Data);
                }
            }
            return [_currentReportResults, Data];
        };

        /**
         * Récupère l'adresse correspondant à une géométrie donnée
         * @param evt le MapEvent ESRI
         * @param geolocalisationApiUrl l'URL de l'API de géolocalisaiton à utiliser
         * @param geolocalisationSRID le SRID de la référence spatiale de l'API de géolocalisation
         * @return une promesse contenant le résultat de la requête
         */
        Utils.getAddress = function(evt, geocodeApiUrl, geolocalisationSRID){
            var def = new Deferred();
//            require([geolocalisationApiUrl], lang.hitch(this, function(){
//                if(typeof(spwGeolocalisation) != "undefined"){
//                    var pt = Utils.getPoint(evt, geolocalisationSRID);
//                    spwGeolocalisation.getNearestPosition(pt.x, pt.y, lang.hitch(this, function(data) {
//                        def.resolve(data);
//                    }), lang.hitch(this, function(request, status, error) {
//                        def.reject({request: request, status: status, error: error});
//                    }));
//                } else {
//                    def.reject(null);
//                }
//            }));
            var pt = Utils.getPoint(evt, geolocalisationSRID);
            request({
                url: geocodeApiUrl + "/revgeocode",
                handleAs: 'json',
                headers: {
                    'Content-Type': null
                },
                content: {
                    x: pt.x,
                    y: pt.y,
                    crs: "EPSG:" + geolocalisationSRID
                }
            }).then(lang.hitch(this, function(response) {
                def.resolve(response);
            }));
            return def;
        };

        /**
         * Récupère l'altitude d'une géométrie donnée
         * @param identifyParams les paramètres d'identification
         * @param altitudeServiceUrl l'URL du service d'altitude à utiliser
         * @return une promesse contenant le résultat de la requête
         */
        Utils.getAltitude = function(identifyParams, altitudeServiceUrl){
            return new IdentifyTask(altitudeServiceUrl).execute(identifyParams);
        };

        /**
         * Récupère l'altitude d'une géométrie donnée
         * @param evt le MapEvent ESRI
         * @param cadmapApiUrl l'URL de l'API de parcelles cadastrales
         * @param cadmapSRID le SRID de l'API de parcelles cadatrales
         * @return une promesse contenant le résultat de la requête
         */
        Utils.getCadastre = function(evt, cadmapApiUrl, cadmapSRID){
            var def = new Deferred();
            require([cadmapApiUrl], lang.hitch(this, function(){
                if(typeof(spwCadmap) != "undefined"){
                    var pt = Utils.getPoint(evt, cadmapSRID);
                    spwCadmap.getShapeParcelleByXY(pt.x, pt.y,
                        lang.hitch(this, function(data){
                            if(data){
                                def.resolve(data);
                            } else {
                                def.reject();
                            }
                        }),
                        lang.hitch(this, function(request, status, error){
                            def.reject();
                        }));
                } else {
                    def.reject();
                }
            }));
            return def;
        };

        /**
         * Récupère les parcelles cadastrales se trouvant sous une géométrie
         * @param geometry la géométrie pour laquelle on effectue la recherche
         * @param spwViewer la référence à SpwViewer
         * @return une promesse contenant le résultat de la requête
         */
        Utils.getCadastralParcellesFromPolygon = function(geometry, spwViewer) {
            var identifyParams = new IdentifyParameters();
            identifyParams.tolerance = 1;
            identifyParams.spatialReference = geometry.mapPoint ? geometry.mapPoint.spatialReference : geometry.geometry.spatialReference;
            identifyParams.width = spwViewer.get('spwMap').get('esriMap').width;
            identifyParams.height = spwViewer.get('spwMap').get('esriMap').height;
            identifyParams.geometry = geometry.geometry;
            identifyParams.mapExtent = spwViewer.get('spwMap').get('esriMap').extent;

            return new IdentifyTask('//geoservices.wallonie.be/arcgis/rest/services/PLAN_REGLEMENT/CADMAP_PARCELLES/MapServer').execute(identifyParams);
        };

        /**
         * Récupère un point sur base d'un MapEvent ESRI (le centroïde si la géométrie est un polygone)
         * @param geometry la géométrie pour laquelle on effectue la recherche
         * @param srid le SRID de la référence spatiale dans laquelle on veut récupérer le point
         * @return le point
         */
        Utils.getPoint = function(evt, srid) {
            var pt = null;

            if (evt.mapPoint) {
                pt = evt.mapPoint;
            }
            else if (evt.geometry) {
                if (evt.geometry.getCentroid) {
                    pt = evt.geometry.getCentroid();
                }
                else if (evt.geometry.type === 'polyline') {
                    pt = evt.geometry.getExtent().getCenter();
                }
                else if (evt.geometry.type === 'point') {
                    pt = evt.geometry;
                }
            }
            if(pt){
                return ProjectionManager.getInstance().projectPoint(pt.spatialReference.wkid, srid, pt.x, pt.y);
            }else{
                return evt;
            }
        };



        /**
         * Construit une liste de données pour l'envoyer au template JASPER pour construire un rapport
         * @param evt le MapEvent ESRI
         * @param spwViewer la référence au SpwViewer
         * @return une promesse contenant la liste des données
         */
        Utils.getIdentifyDataForReport = function(evt, spwViewer, ignoreFields){
            var services = spwViewer.get('spwMap').getMapServices({ isBaseMap: false, visible: true });
            var promises = [];
            var reportPromises = [];
            var servicesInError = [];
            var globalResults = [];
            var globalDef = new Deferred();
            array.forEach(services, lang.hitch(this, function(service) {
                var def = new Deferred();
                reportPromises.push(def);
                promises.push(
                    service.identify(lang.mixin(evt, {
                            ignoreFields: ignoreFields,
                            tolerance: 10
                        }), lang.hitch(this, function(identifyResults, service, data){
                            globalResults.push({service: service, results: identifyResults, data: data});
                            def.resolve();
                        }),
                        lang.hitch(this, function(service){
                            servicesInError.push(service);
                            def.resolve();
                        }))
                );
            }));
            if(reportPromises.length > 0){
                all(reportPromises).then(lang.hitch(this, function(){
                    if(servicesInError.length > 0){
                        var servicesLabel = [];
                        array.forEach(servicesInError, lang.hitch(this, function(serv){
                            servicesLabel.push(serv.label ? serv.label : serv.serviceId);
                        }))
                        var errorMessage = "Une erreur est survenue lors de l'identification de ces services: "+ servicesLabel.join();
                        MessageManager.getInstance().notifyError('', errorMessage);
                    }
                    globalDef.resolve(globalResults);
                }));
            }else{
                globalDef.resolve(globalResults);
            }
            return globalDef;
        };

        Utils.testNavigatorIsIE = function() {
            return /MSIE 9/i.test(navigator.userAgent) || /rv:11.0/i.test(navigator.userAgent) || /MSIE 10/i.test(navigator.userAgent);
        };


        Utils.readShpFile = function(shpBin) {
            var def = new Deferred();
            if (window._unzip) {
                var unzipped = window._unzip(shpBin);
                var foundPrj = false;

                for (var key in unzipped) {
                    if (unzipped.hasOwnProperty(key) && key.indexOf('.prj') > -1) {
                        foundPrj = true;
                        break;
                    }
                }

                if (!foundPrj) {
                    console.error('no prj file');
                    console.error('Le shapefile ne contient pas de fichier précisant la projection spatiale (.prj)');
                    def.reject();
                }
            }

            shp(shpBin).then(lang.hitch(this, function(geojson) {
                def.resolve(geojson);
            }))['catch'](lang.hitch(this, function(err) {
                def.reject();
            }));
            return def;
        };

        /**
         * Récupère les données de localisations pour un rapport (altitude, parcelles, ...)
         * @param currentGeometry la géométrie pour laquelle on effectue la recherche
         * @param params les paramètres spécifiant quelles données interroger
         * @param spwViewer la référence au SpwViewer
         * @return une promesse contennat les résultats de la requête
         */
        Utils.getLocalizationDataForReport = function(currentGeometry, params, spwViewer) {
            var defaultParams = {
                geocodeApiUrl: "//geoservices.wallonie.be/geocodeWS",
                geolocalisationSRID : 31370,
                altitudeServiceUrl : "//geoservices.wallonie.be/arcgis/rest/services/RELIEF/WALLONIE_MNT_2013_2014/MapServer",
                mnsServiceUrl : "//geoservices.wallonie.be/arcgis/rest/services/RELIEF/WALLONIE_MNS_2013_2014/MapServer",
                cadmapApiUrl : "//geoservices.wallonie.be/cadmap/js/SpwCadmapApi.js",
                cadmapSRID : 31370,
                maxSquareAreaForCadastralReport: 250000,
                identificationType: (currentGeometry.geometry!=null ? 'polygon':'point')
            }


            if(params){
                if(Object.keys(params).length > 0){
                    array.forEach(Object.keys(params), lang.hitch(this, function(key){
                        params[key] = params[key] != null ? params[key]: defaultParams[key];
                    }))
                }
            }

            var def = new Deferred();
            var localizationDefs = [];

            var localizationResultData = {};
            localizationResultData['title'] = [];
            localizationResultData['title'].push({level: -1, label: "Données de localisation", value: ""});;

            //ADDRESS
            if(params.identificationType!='polygon'){
                var addressDef = new Deferred();
                localizationResultData['address'] = [];
                localizationDefs.push(addressDef);
                Utils.getAddress(Utils.getPoint(currentGeometry, 31370) , params.geocodeApiUrl, params.geolocalisationSRID).then(
                    lang.hitch(this, function(data){
                        localizationResultData['address'].push({level: -2, label: "Adresse approximative", value: ""});
                        if (data == null || !data.candidates || data.candidates.length <= 0) {
                            localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: "Erreur du service de localisation"});
                        }
                        if(data.candidates && data.candidates.length > 0){
                        	var c = data.candidates[0], full = "";
                        	
                        	if(c.house) full = c.street.name + ', ' + c.house.name + ' ' + c.city.name;
                        	else if(c.street) full = c.street.name + ' ' + c.city.name;
                        	else if(c.city) full = c.city.name;
                        	else full = "Pas de donnée trouvée";
                        	
                            localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: full});
                        }
//                        if (data.rue) {
//                            var full = data.rue.nom;
//
//                            if (data.num) {
//                                full += ', ' + data.num;
//                            }
//
//                            if (data.rue.cps && data.rue.cps.length > 0) {
//                                full += data.rue.cps[0];
//                            }
//
//                            if (data.rue.localites && data.rue.localites.length > 0) {
//                                full += ' ' + data.rue.localites[0];
//
//                                if (data.rue.commune) {
//                                    full += ' (' + data.rue.commune + ')';
//                                }
//                            }
//                            else if (data.rue.commune) {
//                                full += ' ' + data.rue.commune;
//                            }
//                            localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: full});
//                        }
//                        else if(data.adresse) {
//                            localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: data.adresse});
//                        }
                        else {
                            localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: "Erreur du service de localisation"});
                        }
                        addressDef.resolve();
                    }), lang.hitch(this, function(request, status, error) {
                        localizationResultData['address'].push({level: -3, label: "Adresse approximative", value: "Erreur du service de localisation"});
                        addressDef.resolve();
                    })
                );

                //COORDONNEES
                var coordDef = new Deferred();
                localizationDefs.push(coordDef);
                localizationResultData['coord'] = [];
                var pt = Utils.getPoint(currentGeometry, 4326);
                localizationResultData['coord'].push({level: -2, label: "Coordonnées", value: ""});
                localizationResultData['coord'].push({level: -3, label: "Longitude", value: (Math.round(pt.x * 1000) / 1000).toString().replace('.', ',')});
                localizationResultData['coord'].push({level: -3, label: "Latitude", value: (Math.round(pt.y * 1000) / 1000).toString().replace('.', ',')});
                localizationResultData['coord'].push({level: -2, label: "Position en Lambert Belge 72", value: ""});
                var projPt = ProjectionManager.getInstance().projectPoint(4326, 31370, pt.x, pt.y);
                localizationResultData['coord'].push({level: -3, label: "X (m)", value: projPt.x.toString().replace('.', ',')});
                localizationResultData['coord'].push({level: -3, label: "Y (m)", value: projPt.y.toString().replace('.', ',')});
                coordDef.resolve();

                //ALTITUDE
                var altitudeTerrainDef = new Deferred();
                localizationDefs.push(altitudeTerrainDef);

                var identifyParams = new IdentifyParameters();
                identifyParams.tolerance = 1;
                identifyParams.spatialReference = currentGeometry.mapPoint ? currentGeometry.mapPoint.spatialReference : currentGeometry.geometry.spatialReference;
                identifyParams.width = spwViewer.get('spwMap').get('esriMap').width;
                identifyParams.height = spwViewer.get('spwMap').get('esriMap').height;
                identifyParams.geometry = currentGeometry.mapPoint ? currentGeometry.mapPoint : currentGeometry.geometry;
                identifyParams.mapExtent = spwViewer.get('spwMap').get('esriMap').extent;

                localizationResultData['alt'] = [];
                localizationResultData['alt'].push({level: -2, label: "Altitude", value: ""});

                Utils.getAltitude(identifyParams, params.altitudeServiceUrl).then(
                    lang.hitch(this, function(identifyResult) {
                        if(identifyResult && identifyResult.length > 0){
                            var alti = Math.round(identifyResult[0].feature.attributes['Pixel Value'].replace(',','.') * 100)/100;
                            localizationResultData['alt'].push({level: -3, label: "Terrain (m)", value: isNaN(alti) ? "Valeur inconnue" : alti.toString().replace('.', ',')});
                        } else {
                            localizationResultData['alt'].push({level: -3, label: "Terrain (m)", value: "Valeur inconnue"});
                        }
                        altitudeTerrainDef.resolve();
                    }), function(error) {
                        localizationResultData['alt'].push({level: -3, label: "Terrain (m)", value: "Valeur inconnue"});
                        altitudeTerrainDef.resolve();
                    });


                var altitudeSurfaceDef = new Deferred();
                localizationDefs.push(altitudeSurfaceDef);
                Utils.getAltitude(identifyParams, params.mnsServiceUrl).then(
                    lang.hitch(this, function(identifyResult) {
                        if(identifyResult && identifyResult.length > 0){
                            var alti = Math.round(identifyResult[0].feature.attributes['Pixel Value'].replace(',','.') * 100)/100;
                            localizationResultData['alt'].push({level: -3, label: "Surface (m)", value: isNaN(alti) ? "Valeur inconnue" : alti.toString().replace('.', ',')});
                        } else {
                            localizationResultData['alt'].push({level: -3, label: "Surface (m)", value: "Valeur inconnue"});
                        }
                        altitudeSurfaceDef.resolve();
                    }), lang.hitch(this, function(error) {
                        localizationResultData['alt'].push({level: -3, label: "Surface (m)", value: "Valeur inconnue"});
                        altitudeSurfaceDef.resolve();
                    }));
            }

            //CADASTRE
            var cadastreDef = new Deferred();
            localizationDefs.push(cadastreDef);
            localizationResultData['cad'] = [];
            localizationResultData['cad'].push({level: -2, label: "Références cadastrales", value: ""});

            if(currentGeometry.geometry && params.identificationType != 'layer'){
                var squareMeterOfPolygon = GeometryUtils.area(currentGeometry.geometry, 'square-meters');
                if(squareMeterOfPolygon <= params.maxSquareAreaForCadastralReport){
                    var ignoreAttributes = ['CAPAKEY', 'CAPATY', 'Feuille cadastrale', 'OBJECTID', 'SHAPE', 'Version'];
                    Utils.getCadastralParcellesFromPolygon(currentGeometry, spwViewer).then(
                        lang.hitch(this, function(data){
                            if(data && data.length > 0){
                                array.forEach(data, lang.hitch(this, function(res){
                                    array.forEach(Object.keys(res.feature.attributes), function(key){
                                        if(ignoreAttributes.indexOf(key) == -1){
                                            localizationResultData['cad'].push({level: -3, label: key, value: res.feature.attributes[key]});
                                        }
                                    })
                                    localizationResultData['cad'].push({level: -3, label: '', value: ''});
                                }))
                            }else{
                                localizationResultData['cad'].push({level: -3, label: "Pas de parcelles cadatrales", value: "Aucune parcelle cadastrale n'a été trouvée pour le polygone que vous avez dessiné"});
                            }
                            cadastreDef.resolve();
                        }),
                        lang.hitch(this, function(error){
                            localizationResultData['cad'].push({level: -3, label: "Erreur du service du cadastre", value: ""});
                            cadastreDef.resolve();
                        })
                    )
                }else{
                    if(params.identificationType == 'layer'){
                        localizationResultData['cad'].push({level: -3, label: "Le service du cadastre n'a pas été interrogé", value: "La parcelle cadastrale que vous avez selectionnée est plus grande que la limite autorisée ("+params.maxSquareAreaForCadastralReport+"m²) pour l'interrogation des parcelles cadastrales"});
                    }else{
                        localizationResultData['cad'].push({level: -3, label: "Le service du cadastre n'a pas été interrogé", value: "Le polygone que vous avez dessiné est plus grand que la limite autorisée ("+params.maxSquareAreaForCadastralReport+"m²) pour l'interrogation des parcelles cadastrales"});
                    }
                    cadastreDef.resolve();
                }
            }else{
                Utils.getCadastre(currentGeometry, params.cadmapApiUrl, params.cadmapSRID).then(
                    lang.hitch(this, function(data){
                        if(data){
                            localizationResultData['cad'].push({level: -3, label: "Commune/INS", value: data.nomCommune + " " + data.commune});
                            localizationResultData['cad'].push({level: -3, label: "Division", value: data.divNom});
                            localizationResultData['cad'].push({level: -3, label: "Section", value: data.sect});
                            localizationResultData['cad'].push({level: -3, label: "Radical", value: data.radical});
                            localizationResultData['cad'].push({level: -3, label: "Exposant", value: data.exposant});
                            localizationResultData['cad'].push({level: -3, label: "Puissance", value: data.puissance});
                            localizationResultData['cad'].push({level: -3, label: "Bis", value: data.bis});
                        } else {
                            localizationResultData['cad'].push({level: -3, label: "Erreur du service du cadastre", value: ""});
                        }
                        cadastreDef.resolve();
                    }),
                    lang.hitch(this, function(error){
                        localizationResultData['cad'].push({level: -3, label: "Erreur du service du cadastre", value: ""});
                        cadastreDef.resolve();
                    })
                )
            }
            var buildResults = function(){
                var localizationData = [];
                localizationData.push(localizationResultData.title[0]);
                var dataProperties = ['address', 'coord', 'alt', 'parcelle', 'cad'];
                dataProperties.forEach(lang.hitch(this, function(prop){
                    if(localizationResultData[prop] && localizationResultData[prop].length > 0){
                        array.forEach(localizationResultData[prop], lang.hitch(this, function(d){
                            localizationData.push(d);
                        }))
                    }
                }));
                def.resolve(localizationData);
            };
            if(localizationDefs.length > 0){
                all(localizationDefs).then(
                    lang.hitch(this, function(){
                        buildResults();
                    }),
                    lang.hitch(this, function(){
                        buildResults();
                    })
                )
            }else{
                buildResults();
            }
            return def;
        };

        /**
         * Crée un rapport et le télécharge
         * @param currentGeometry sur laquelle baser le rapport
         * @param localizationReportDataParams un objet permettant de configurer quelles données de localisations doivent être affichée dans le rapport (parcelle, altitude, coordonnées, ...)
         * @param reportParams paramètres pour le template JASPER
         * @param data les résultats à afficher dans le rapport
         * @param spwViewer la référence à SpwViewer
         * @param {boolean} reportWithLegend détermine s'il faut afficher la légende dans le rapport ou non
         */
        Utils.createReport = function(currentGeometry, localizationReportDataParams, reportParams,data, spwViewer, reportWithLegend){
            MessageManager.getInstance().displayModalMessage("Récupération de la légende.<br>Cela peut prendre quelques secondes…");
            if(currentGeometry){
                Utils.getLocalizationDataForReport(currentGeometry, localizationReportDataParams, spwViewer).then(
                    lang.hitch(this, function(localizationData){
                        Utils.printReport(localizationData, reportWithLegend, data, spwViewer, reportParams);
                    })
                );
            }else{
                MessageManager.getInstance().notifyError("", "Aucune géométrie sélectionnée pour le rapport, veuillez en sélectionner une.");
            }
        };

        Utils.buildLocalisableUrlParams = function(params) {
            var options = {
                title: params['TOOLTIPTITLE'] ? decodeURIComponent(params['TOOLTIPTITLE']) : 'Informations',
                text:  params['TOOLTIPTEXT'] ? decodeURIComponent(params['TOOLTIPTEXT']) : '',
                scale: params['SCALE'],
                allowDelete: params['ALLOWDELETE'] != 'false',
                show: params['SHOW'] == 'true' ? true : false,
                tooltipOpen: params['TOOLTIPOPEN'] == 'true' ? true : false
            }
            return options;
        },

            Utils.jsDateToESRIFormat = function (date) {
                var dd = date.getDate();
                var mm = date.getMonth() + 1;
                var yyyy = date.getFullYear();
                if(dd<10){
                    dd='0'+dd;
                }
                if(mm<10){
                    mm='0'+mm;
                }
                return dd+'/'+mm+'/'+yyyy;
            },

            /**
             * Imprime le rapport
             * @param localizationData les données de localisations à afficher dans le rapport
             * @param reportWithLegend détermine s'il faut afficher la légende dans le rapport ou pas
             * @param data les données à afficher dans le template
             * @param spwViewer la référence à SpwViewer
             * @param reportParams les paramètres du template JASPER
             */
            Utils.printReport = function(localizationData, reportWithLegend, data, spwViewer, reportParams){
                var mapServices = spwViewer.get('spwMap').getMapServices({
                    isBaseMap: false,
                    visible: true
                });
                Utils.getPrintableLegendForServices(mapServices, spwViewer).then(lang.hitch(this, function(Data){
                    var rapportResults = Utils.buildRapportResults(data, Data);
                    if(reportWithLegend){
                        //rapportResults[1].Data.splice(-1, 1);
                    	//why ?? delete the last legend item ??
                    }
                    if(rapportResults[1].Data.length > 0){
                        localizationData.push({
                            level: -3,
                            label: 'break',
                            value: ''
                        })
                    }
                    Data.Data = localizationData.concat(rapportResults[1].Data);
                    require(['spw/api/Printer'], lang.hitch(this, function(spwPrinter){
                        var printer = new spwPrinter();
                        require(["dojo/text!"+reportParams.url], lang.hitch(this, function(JasperTmpl){
                            MessageManager.getInstance().hideModalMessage();
                            printer.downloadReport(reportParams.jasperServerUrl, JasperTmpl, Data, reportParams);
                        }));
                    }));
                }));
            };

        return Utils;
    });