nc.noumea.mairie.organigramme.viewmodel.OrganigrammeViewModel.java Source code

Java tutorial

Introduction

Here is the source code for nc.noumea.mairie.organigramme.viewmodel.OrganigrammeViewModel.java

Source

package nc.noumea.mairie.organigramme.viewmodel;

/*
 * #%L
 * Logiciel de Gestion des Organigrammes de la Ville de Nouma
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2015 Mairie de Nouma
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * #L%
 */

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import nc.noumea.mairie.organigramme.core.services.AuthentificationService;
import nc.noumea.mairie.organigramme.core.utility.OrganigrammeUtil;
import nc.noumea.mairie.organigramme.core.viewmodel.AbstractViewModel;
import nc.noumea.mairie.organigramme.core.ws.IAdsWSConsumer;
import nc.noumea.mairie.organigramme.core.ws.ISirhWSConsumer;
import nc.noumea.mairie.organigramme.dto.DuplicationDto;
import nc.noumea.mairie.organigramme.dto.EntiteDto;
import nc.noumea.mairie.organigramme.dto.ProfilAgentDto;
import nc.noumea.mairie.organigramme.entity.EntiteFavoris;
import nc.noumea.mairie.organigramme.enums.FiltreStatut;
import nc.noumea.mairie.organigramme.enums.Statut;
import nc.noumea.mairie.organigramme.enums.Transition;
import nc.noumea.mairie.organigramme.query.EntiteDtoQueryListModel;
import nc.noumea.mairie.organigramme.services.CouleurTypeEntiteService;
import nc.noumea.mairie.organigramme.services.EntiteFavorisService;
import nc.noumea.mairie.organigramme.services.ExportGraphMLService;
import nc.noumea.mairie.organigramme.services.OrganigrammeService;
import nc.noumea.mairie.organigramme.services.ReturnMessageService;
import nc.noumea.mairie.organigramme.services.TypeEntiteService;
import nc.noumea.mairie.organigramme.utils.ComparatorUtil;

import org.springframework.util.CollectionUtils;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.DependsOn;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zkplus.spring.DelegatingVariableResolver;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Messagebox.ClickEvent;
import org.zkoss.zul.Vlayout;
import org.zkoss.zul.Window;

@Init(superclass = true)
@VariableResolver(DelegatingVariableResolver.class)
public class OrganigrammeViewModel extends AbstractViewModel<EntiteDto> implements Serializable {

    private static final long serialVersionUID = 1L;

    // @formatter:off
    @WireVariable
    IAdsWSConsumer adsWSConsumer;
    @WireVariable
    ISirhWSConsumer sirhWSConsumer;
    @WireVariable(value = "ExportGraphMLServiceOrgaEntitesImpl")
    ExportGraphMLService exportGraphMLService;
    @WireVariable
    OrganigrammeService organigrammeService;
    @WireVariable
    AuthentificationService authentificationService;
    @WireVariable
    CouleurTypeEntiteService couleurTypeEntiteService;
    @WireVariable
    TypeEntiteService typeEntiteService;
    @WireVariable
    ReturnMessageService returnMessageService;
    @WireVariable
    EntiteFavorisService entiteFavorisService;
    // @formatter:on

    private static final String CREATE_ENTITE_VIEW = "/layout/createEntite.zul";

    private static final String[] LISTE_PROP_A_NOTIFIER_ENTITE = new String[] { "statut", "entity", "creable",
            "duplicable", "listeTransitionAutorise", "listeEntite", "mapIdLiEntiteDto", "selectedFiltreStatut",
            "urlImageFavoris", "selectedEntiteDtoZoom", "selectedEntiteDtoRechercheIhm", "selectedEntiteDtoZoomIhm",
            "entiteDtoQueryListModelRecherchable", "feuilleSelonFiltreStatut" };

    private OrganigrammeWorkflowViewModel organigrammeWorkflowViewModel = new OrganigrammeWorkflowViewModel(this);

    public TreeViewModel treeViewModel = new TreeViewModel(this);

    /** Le vlayout gnral dans lequel sera ajout l'arbre **/
    Vlayout vlayout;

    /** L'{@link EntiteDto} reprsentant l'arbre au complet **/
    EntiteDto entiteDtoRoot;

    /** L'{@link EntiteDto} reprsentant l'entit zomm **/
    EntiteDto selectedEntiteDtoZoom;
    EntiteDto selectedEntiteDtoZoomIhm;
    EntiteDto selectedEntiteDtoRechercheIhm;

    /**
     * Le {@link FiltreStatut} reprsentant le filtre actif, par dfaut, on
     * affiche les ACTIFS #17105
     **/
    FiltreStatut selectedFiltreStatut = FiltreStatut.ACTIF;

    /**
     * Map permettant rapidement d'accder  un nomPrenom d'agent  partir de
     * son id agent
     **/
    Map<Integer, String> mapIdAgentNomPrenom = new HashMap<Integer, String>();

    /**
     * Map permettant rapidement d'accder  une {@link EntiteDto}  partir de
     * son id html client
     **/
    Map<String, EntiteDto> mapIdLiEntiteDto;

    List<EntiteDto> listeEntiteFavorisDto = new ArrayList<EntiteDto>();

    /**
     * Map permettant de savoir si le Li est ouvert ou non  partir de son id
     * html client
     **/
    Map<String, Boolean> mapIdLiOuvert = new HashMap<String, Boolean>();

    /** Le currentUser connect **/
    ProfilAgentDto profilAgentDto;

    /** Liste de toutes les entits recherchables **/
    List<EntiteDto> listeEntite = new ArrayList<EntiteDto>();

    /** ListModel de toutes les entits recherchables **/
    EntiteDtoQueryListModel entiteDtoQueryListModelRecherchable;

    EntiteDto selectedEntiteDtoFavoris;

    // sett par le treeViewModel
    public void setListeEntite(List<EntiteDto> listeEntite) {
        this.listeEntite = listeEntite;
    }

    public EntiteDto getSelectedEntiteDtoZoom() {
        return selectedEntiteDtoZoom;
    }

    public EntiteDto getSelectedEntiteDtoZoomIhm() {
        return selectedEntiteDtoZoomIhm;
    }

    public void setSelectedEntiteDtoZoomIhm(EntiteDto selectedEntiteDtoZoomIhm) {
        this.selectedEntiteDtoZoomIhm = selectedEntiteDtoZoomIhm;
    }

    public void setSelectedEntiteDtoZoom(EntiteDto selectedEntiteDtoZoom) {
        this.selectedEntiteDtoZoom = selectedEntiteDtoZoom;
    }

    public EntiteDto getSelectedEntiteDtoRechercheIhm() {
        return selectedEntiteDtoRechercheIhm;
    }

    public void setSelectedEntiteDtoRechercheIhm(EntiteDto selectedEntiteDtoRechercheIhm) {
        this.selectedEntiteDtoRechercheIhm = selectedEntiteDtoRechercheIhm;
    }

    public FiltreStatut getSelectedFiltreStatut() {
        return selectedFiltreStatut;
    }

    public void setSelectedFiltreStatut(FiltreStatut selectedFiltreStatut) {
        this.selectedFiltreStatut = selectedFiltreStatut;
    }

    public EntiteDto getSelectedEntiteDtoFavoris() {
        return selectedEntiteDtoFavoris;
    }

    public void setSelectedEntiteDtoFavoris(EntiteDto selectedEntiteDtoFavoris) {
        this.selectedEntiteDtoFavoris = selectedEntiteDtoFavoris;
    }

    public EntiteDtoQueryListModel getEntiteDtoQueryListModelRecherchable() {
        return entiteDtoQueryListModelRecherchable;
    }

    public void setEntiteDtoQueryListModelRecherchable(
            EntiteDtoQueryListModel entiteDtoQueryListModelRecherchable) {
        this.entiteDtoQueryListModelRecherchable = entiteDtoQueryListModelRecherchable;
    }

    public List<EntiteDto> getListeEntite() {

        // On filtre la liste des entits recherchables selon le
        // statut selectionn
        if (this.selectedFiltreStatut != null && !this.selectedFiltreStatut.equals(FiltreStatut.TOUS)) {
            List<EntiteDto> listeEntiteClone = new ArrayList<EntiteDto>();
            listeEntiteClone.addAll(this.listeEntite);
            for (EntiteDto entiteDto : listeEntiteClone) {
                if (!this.selectedFiltreStatut.getListeStatut().contains(entiteDto.getStatut())) {
                    listeEntite.remove(entiteDto);
                }
            }
        }

        return listeEntite;
    }

    public List<EntiteDto> getListeEntiteFavorisDto() {
        Collections.sort(listeEntiteFavorisDto, new ComparatorUtil.EntiteComparator());

        return listeEntiteFavorisDto;
    }

    /**
     * Point d'entre du viewModel. Fait un appel  ADS afin de rcuprer
     * l'arbre et le cre
     * 
     * @param view
     *            : la vue permettant de rcuperer le {@link Vlayout} dans
     *            lequel sera ajout l'arbre
     */
    @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        // permet de grer le onClickEntite
        Selectors.wireEventListeners(view, this);

        for (EntiteDto entiteDto : adsWSConsumer.getAllEntiteAPlat(null)) {
            mapIdLiOuvert.put(entiteDto.getIdLi(), false);
        }
        vlayout = (Vlayout) Selectors.iterable(view, "#organigramme").iterator().next();
        profilAgentDto = authentificationService.getCurrentUser();

        // On recharge l'arbre complet d'ADS et on rafraichi le client. Ainsi on
        // est sur d'avoir une version bien  jour
        refreshArbreComplet();

        // Gestion des favoris
        construireListeEntiteFavoris();
    }

    private void construireListeEntiteFavoris() {
        listeEntiteFavorisDto = new ArrayList<EntiteDto>();
        for (EntiteFavoris entiteFavoris : entiteFavorisService.findAllByIdAgent(profilAgentDto.getIdAgent())) {
            EntiteDto entiteDtoFavoris = adsWSConsumer.getEntiteWithChildren(entiteFavoris.getIdEntite());
            if (entiteDtoFavoris != null) {
                this.listeEntiteFavorisDto.add(entiteDtoFavoris);
            }
        }
    }

    /**
     * Cre l'arbre et l'ajoute au {@link Vlayout} client et rafraichi le client
     */
    @GlobalCommand
    public void creeArbreEtRafraichiClient() {
        refreshArbreComplet();
        Clients.evalJavaScript("refreshOrganigramme();");
    }

    @Command
    @NotifyChange("selectedEntiteDtoFavoris")
    public void onChangeFavoris() {
        if (this.selectedEntiteDtoFavoris != null) {
            selectionneEntiteZoom(selectedEntiteDtoFavoris);
            this.selectedEntiteDtoFavoris = null;
        }
    }

    @GlobalCommand
    public void refreshOrganigrammeSuiteAjout(@BindingParam("entiteDto") EntiteDto entiteDto) {
        refreshArbreComplet();
        Clients.evalJavaScript("refreshOrganigrammeSuiteAjout('" + entiteDto.getIdLi() + "');");
    }

    @GlobalCommand
    @NotifyChange({ "*" })
    public void refreshOrganigrammeWithoutSelectedEntite() {
        setEntity(null);
        refreshArbreComplet();

        // On recharge les favoris au cas o par exemple on vienne de supprimer
        // une entit qui tait dans les favoris
        construireListeEntiteFavoris();

        Clients.evalJavaScript("refreshOrganigrammeWithoutSelectedEntite();");
    }

    private void refreshArbreComplet() {
        majEntiteRootByFiltreAndZoom();
        treeViewModel.creeArbre(entiteDtoRoot);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    /**
     * Evenement qui se dclenche lors d'un click sur une entit ct client
     * 
     * @param event
     *            : l'venement click qui contient dans getData() l'id du li
     *            selectionn
     */
    @Listen("onClickEntite = #organigramme")
    public void onClickEntite(Event event) {

        EntiteDto entiteDto = mapIdLiEntiteDto.get(event.getData());
        EntiteDto entiteDtoFromBdd = entiteDto;
        if (entiteDto != null) {
            entiteDtoFromBdd = adsWSConsumer.getEntiteWithChildren(entiteDto.getIdEntite());
        }
        setEntity(entiteDtoFromBdd);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    @Listen("onClickFlecheDeplierReplier = #organigramme")
    public void onClickFlecheDeplierReplier(Event event) {
        EntiteDto entiteDto = mapIdLiEntiteDto.get(event.getData());

        boolean ouvert = mapIdLiOuvert.get(entiteDto.getIdLi()) != null ? !mapIdLiOuvert.get(entiteDto.getIdLi())
                : false;
        mapIdLiOuvert.put(entiteDto.getIdLi(), ouvert);
    }

    /**
     * Evenement qui se dclenche lors d'un double click sur une entit ct
     * client
     * 
     * @param event
     *            : l'venement click qui contient dans getData() l'id du li
     *            selectionn
     */
    @Listen("onDblClickEntite = #organigramme")
    public void onDblClickEntite(Event event) {
        EntiteDto entiteDto = mapIdLiEntiteDto.get(event.getData());
        ouvreOngletEntite(entiteDto, 0);
    }

    @Listen("onClickToutDeplier = #organigramme")
    public void onClickToutDeplier(Event event) {
        if (this.selectedEntiteDtoZoom == null && this.selectedEntiteDtoRechercheIhm == null) {
            setEntity(null);
        } else {
            this.selectedEntiteDtoRechercheIhm = null;
        }

        mapIdLiOuvert.put(entiteDtoRoot.getIdLi(), true);
        setLiOuvertOuFermeArbre(entiteDtoRoot.getEnfants(), true);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    @Listen("onClickToutReplier = #organigramme")
    public void onClickToutReplier(Event event) {
        setEntity(null);
        mapIdLiOuvert.put(entiteDtoRoot.getIdLi(), false);
        setLiOuvertOuFermeArbre(entiteDtoRoot.getEnfants(), false);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    /**
     * Mthode qui parcours tout l'arbre et met  jour la mapIdLiOuvert
     * 
     * @param listeEntiteDto
     *            : la liste  parcourir
     * @param ouvert
     *            : ouvert ou ferm
     */
    private void setLiOuvertOuFermeArbre(List<EntiteDto> listeEntiteDto, boolean ouvert) {
        for (EntiteDto entiteDto : listeEntiteDto) {
            mapIdLiOuvert.put(entiteDto.getIdLi(), ouvert);
            setLiOuvertOuFermeArbre(entiteDto.getEnfants(), ouvert);
        }
    }

    /**
     * Initialise un {@link EntiteDto} avec son parent et rend visible la popup
     * de cration de l'entit
     * 
     * @param entiteDto
     *            : le {@link EntiteDto} parent
     * @throws IllegalAccessException
     *             IllegalAccessException
     * @throws InstantiationException
     *             InstantiationException
     */
    @Command
    public void createEntite(@BindingParam("entity") EntiteDto entiteDto)
            throws InstantiationException, IllegalAccessException {

        if (!profilAgentDto.isEdition()) {
            return;
        }

        // Le parent doit tre en statut P ou A
        if (entiteDto.getStatut() != Statut.PREVISION && entiteDto.getStatut() != Statut.ACTIF) {
            AbstractViewModel.showErrorPopup(
                    "Vous ne pouvez crer une entit que si son parent est dans l'tat Actif ou Prvision");
            return;
        }

        EntiteDto newEntiteDto = new EntiteDto();
        newEntiteDto.setEntiteParent(entiteDto);
        initPopupEdition(newEntiteDto, CREATE_ENTITE_VIEW);
    }

    /**
     * Recharge l'arbre complet, rafraichi le client et selectionne l'entit
     * cre
     * 
     * @param newEntiteDto
     *            : la nouvelle entite
     * @param ouvreOnglet
     *            : doit-on ou non ouvrir l'onglet de l'entit cr  la fin de
     *            la mthode ?
     */
    @GlobalCommand
    public void refreshArbreSuiteAjout(@BindingParam("newEntiteDto") EntiteDto newEntiteDto,
            @BindingParam("ouvreOnglet") boolean ouvreOnglet) {

        // Comme on est en train de crer une entit en statut prvisionnel, on
        // force l'affichage du statut pour pouvoir voir cette nouvelle entit
        boolean filtreStatutPrevisionVisible = selectedFiltreStatut != null
                && (selectedFiltreStatut.equals(FiltreStatut.ACTIF_PREVISION)
                        || selectedFiltreStatut.equals(FiltreStatut.TOUS)
                        || selectedFiltreStatut.equals(FiltreStatut.ACTIF_PREVISION_TRANSITOIRE));
        if (!filtreStatutPrevisionVisible) {
            setSelectedFiltreStatut(FiltreStatut.ACTIF_PREVISION_TRANSITOIRE);
        }
        refreshArbreComplet();

        // Vu qu'on vient de reconstruire l'arbre complet on recharge les
        // nouveaux
        // DTO
        newEntiteDto = OrganigrammeUtil.findEntiteDtoDansArbreById(entiteDtoRoot, newEntiteDto.getIdEntite(), null);
        EntiteDto entiteDtoParent = OrganigrammeUtil.findEntiteDtoDansArbreById(entiteDtoRoot,
                newEntiteDto.getEntiteParent().getIdEntite(), null);

        setEntity(newEntiteDto);
        mapIdLiOuvert.put(newEntiteDto.getIdLi(), false);
        // Appel de la fonction javascript correspondante
        Clients.evalJavaScript("refreshOrganigrammeSuiteAjout('" + newEntiteDto.getIdLi() + "', '"
                + entiteDtoParent.getIdLi() + "');");

        if (!filtreStatutPrevisionVisible) {
            Messagebox.show(
                    "Le filtre d'affichage a t chang pour vous permettre de visualiser la nouvelle entit",
                    "Information", Messagebox.OK, Messagebox.INFORMATION);
        }

        if (ouvreOnglet) {
            ouvreOngletEntite(newEntiteDto, 0);
        } else {
            Clients.evalJavaScript("goToByScroll('" + newEntiteDto.getIdLi() + "');");
        }
    }

    @Command
    public void ouvreOngletEntite(@BindingParam("entity") EntiteDto entiteDto, Integer selectedTabIndex) {
        setEntity(null);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
        Clients.evalJavaScript("refreshOrganigrammeWithoutSelectedEntite();");
        super.ouvreOnglet(entiteDto, selectedTabIndex);
    }

    /**
     * Dplie {@link EntiteDto} ct client.
     * 
     * @param entiteDto
     *            : l'{@link EntiteDto}  dplier
     */
    @Command
    public void deplierEntite(@BindingParam("entity") EntiteDto entiteDto) {
        Clients.evalJavaScript("expandEntiteFromIdDiv('" + entiteDto.getIdLi() + "');");
    }

    /**
     * @return la liste des transitions autorises pour cette entit
     */
    public List<Transition> getListeTransitionAutorise() {
        if (this.entity == null) {
            return null;
        }
        return this.entity.getListeTransitionAutorise();
    }

    /**
     * Effectue un changement d'tat sur l'entit
     * 
     * @param transition
     *            Transition concerne
     */
    @GlobalCommand
    @NotifyChange({ "*" })
    public void passerTransition(@BindingParam("transition") Transition transition) {

        if (!profilAgentDto.isEdition()) {
            return;
        }

        organigrammeWorkflowViewModel.passerTransition(transition, this.entity);
    }

    /**
     * Effectue un changement d'tat sur l'entit
     * 
     * @param transition
     *            Transition concerne
     */
    @GlobalCommand
    @NotifyChange({ "*" })
    public void passerTransitionSurEntite(@BindingParam("transition") Transition transition,
            @BindingParam("entite") EntiteDto entiteDto) {
        organigrammeWorkflowViewModel.passerTransition(transition, entiteDto);
    }

    /**
     * @return statut de l'entit
     */
    @DependsOn("entity")
    public Statut getStatut() {
        if (this.entity == null) {
            return null;
        }
        return entity.getStatut();
    }

    @GlobalCommand
    public void refreshApresTransition(@BindingParam("entity") EntiteDto entiteDto) {
        refreshGeneric(entiteDto, LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    public void refreshGeneric(EntiteDto entiteDto, String[] listePropANotifier) {

        // ne devrait pas arriver
        if (entity == null) {
            return;
        }

        // l'entit  rafrachir n'est pas celle associe  ce ViewModel
        if (!OrganigrammeUtil.sameIdAndNotNull(entity.getId(), this.entity.getId())) {
            return;
        }

        notifyChange(listePropANotifier);

        // Appel de la fonction javascript correspondante
        Clients.evalJavaScript("refreshOrganigramme();");
    }

    /**
     * L'entit est-elle crable ?
     * 
     * @return true si l'entit est crable, false sinon
     */
    public boolean isCreable() {
        // On ne peux crer que si on a le rle dition
        return profilAgentDto.isEdition() && this.entity != null;
    }

    /**
     * L'entit est-elle duplicable ?
     * 
     * @return true si l'entit est duplicable, false sinon
     */
    public boolean isDuplicable() {
        // On ne peux crer que si on a le rle dition
        return profilAgentDto.isEdition() && this.entity != null
                && (this.entity.isActif() || this.entity.isTransitoire());
    }

    /**
     * Met  jour l'entit avec les dates et les rfrences de dlibrations
     * saisies et passe la transition
     * 
     * @param entiteDto
     *            : l'{@link EntiteDto} sur laquelle on souhaite passer la
     *            transition
     * @param transition
     *            : la transition a passer
     * @param popup
     *            : la popup de changement de statut
     * @param majEntitesEnfant
     *            met-on  jour ou non les enfants
     */
    @GlobalCommand
    public void saveStatutWithRefAndDateGenerique(@BindingParam("entity") final EntiteDto entiteDto,
            @BindingParam("transition") final Transition transition, @BindingParam("popup") final Window popup,
            @BindingParam("majEntitesEnfant") final boolean majEntitesEnfant) {

        if (transition.getStatut().equals(Statut.ACTIF)) {
            String messageConfirmation = "tes-vous sur de vouloir passer cette entit en statut 'ACTIF' ? Plus aucune information de cette entit ne pourra tre modifie ( part le type et les commentaires).";
            Messagebox.show(messageConfirmation, "Confirmation",
                    new Messagebox.Button[] { Messagebox.Button.YES, Messagebox.Button.NO }, Messagebox.EXCLAMATION,
                    new EventListener<Messagebox.ClickEvent>() {
                        @Override
                        public void onEvent(ClickEvent evt) {
                            if (evt.getName().equals("onYes")) {
                                if (organigrammeWorkflowViewModel.executerTransitionGeneric(transition,
                                        majEntitesEnfant, entiteDto)) {
                                    popup.detach();
                                }
                            }
                        }
                    });
        } else {
            if (organigrammeWorkflowViewModel.executerTransitionGeneric(transition, majEntitesEnfant, entiteDto)) {
                popup.detach();
            }
        }

        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
    }

    public Map<String, EntiteDto> getMapIdLiEntiteDto() {
        return mapIdLiEntiteDto;
    }

    @Command
    public void deplierTout() {
        Clients.evalJavaScript("deplierTout();");
    }

    @Command
    public void deplierNiveau(@BindingParam("entity") EntiteDto entiteDto) {
        deplierReplierNiveau(entiteDto, true);
    }

    @Command
    public void replierNiveau(@BindingParam("entity") EntiteDto entiteDto) {
        deplierReplierNiveau(entiteDto, false);
    }

    private Map<EntiteDto, Integer> getMapEntiteNiveau(EntiteDto entiteDto, Map<EntiteDto, Integer> mapEntiteNiveau,
            Integer niveau) {
        if (mapIdLiOuvert.get(entiteDto.getIdLi())) {

            for (EntiteDto entiteDtoEnfant : entiteDto.getEnfants()) {
                mapEntiteNiveau.put(entiteDtoEnfant, niveau);
            }
            for (EntiteDto entiteDtoEnfant : entiteDto.getEnfants()) {
                if (mapIdLiOuvert.get(entiteDtoEnfant.getIdLi())
                        && !CollectionUtils.isEmpty(entiteDtoEnfant.getEnfants())) {
                    EntiteDto entiteDtoIhm = rechercheEntiteIhm(this.entiteDtoRoot, entiteDtoEnfant, null);
                    if (entiteDtoIhm != null && !CollectionUtils.isEmpty(entiteDtoIhm.getEnfants())) {
                        getMapEntiteNiveau(entiteDtoEnfant, mapEntiteNiveau, niveau + 1);
                    }
                }
            }
        }

        return mapEntiteNiveau;
    }

    private Integer getMaxNiveauFromMap(Map<EntiteDto, Integer> mapEntiteNiveau) {
        Map.Entry<EntiteDto, Integer> maxEntry = null;

        for (Map.Entry<EntiteDto, Integer> entry : mapEntiteNiveau.entrySet()) {
            if (maxEntry == null || entry.getValue().compareTo(maxEntry.getValue()) > 0) {
                maxEntry = entry;
            }
        }

        return maxEntry.getValue();
    }

    private void deplierReplierNiveau(EntiteDto entiteDto, boolean deplier) {
        if (entiteDto != null) {

            Map<EntiteDto, Integer> mapEntiteNiveau = new HashMap<EntiteDto, Integer>();
            mapEntiteNiveau.put(entiteDto, 0);
            mapEntiteNiveau = getMapEntiteNiveau(entiteDto, mapEntiteNiveau, 1);
            Integer maxNiveauOuvert = getMaxNiveauFromMap(mapEntiteNiveau);

            List<EntiteDto> listeEntiteDto = new ArrayList<EntiteDto>();
            listeEntiteDto.add(entiteDto);
            Integer niveauRecherche = deplier ? maxNiveauOuvert : maxNiveauOuvert - 1;

            if (deplier) {
                for (int niveauParcouru = 0; niveauParcouru <= niveauRecherche; niveauParcouru++) {
                    deplierReplierParNiveau(deplier, listeEntiteDto, niveauParcouru);
                }
            } else {
                deplierReplierParNiveau(deplier, listeEntiteDto, maxNiveauOuvert - 1);
            }

            notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
            refreshArbreComplet();
            Clients.evalJavaScript("refreshOrganigrammeSuiteReplierDeplierNiveau('" + entiteDto.getIdLi() + "');");
        }
    }

    private void deplierReplierParNiveau(boolean deplier, List<EntiteDto> listeEntiteDto, int niveauParcouru) {
        for (EntiteDto entiteDtoNiveau : getListeFromEntiteAndNiveau(listeEntiteDto, niveauParcouru,
                new ArrayList<EntiteDto>())) {

            mapIdLiOuvert.put(entiteDtoNiveau.getIdLi(), deplier);

            String entiteIdLi = entiteDtoNiveau.getIdLi();

            if (deplier) {
                Clients.evalJavaScript("deplierNiveau('" + entiteIdLi + "');");
            } else {
                Clients.evalJavaScript("replierNiveau('" + entiteIdLi + "');");
            }
        }
    }

    private List<EntiteDto> getListeFromEntiteAndNiveau(List<EntiteDto> listeEnfant, Integer niveau,
            List<EntiteDto> result) {
        if (niveau.equals(0)) {
            result.addAll(listeEnfant);
            return result;
        }

        for (EntiteDto entiteDtoEnfant : listeEnfant) {
            getListeFromEntiteAndNiveau(entiteDtoEnfant.getEnfants(), niveau - 1, result);
        }

        return result;
    }

    @Command
    public void replierTout() {
        Clients.evalJavaScript("replierTout();");
    }

    @Command
    public void refresh() {
        setEntity(null);
        refreshArbreComplet();
        Clients.evalJavaScript("refreshOrganigrammeWithoutSelectedEntite();");
        Clients.showNotification("Organigramme rafrachi.", "info", null, "top_center", 0);
    }

    @Command
    public void dezoomer() {
        setSelectedEntiteDtoZoom(null);
        setEntity(null);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
        refreshArbreComplet();
        Clients.evalJavaScript("refreshOrganigrammeReplie();");
    }

    public void selectionneEntiteZoom(EntiteDto entiteDto) {
        this.selectedEntiteDtoZoom = entiteDto;

        if (!this.selectedEntiteDtoZoom.isActif()) {
            if ((this.selectedEntiteDtoZoom.isPrevision() || this.selectedEntiteDtoZoom.isTransitoire())
                    && !selectedFiltreStatut.equals(FiltreStatut.ACTIF_PREVISION)
                    && !selectedFiltreStatut.equals(FiltreStatut.ACTIF_PREVISION_TRANSITOIRE)
                    && !selectedFiltreStatut.equals(FiltreStatut.TOUS)) {
                setSelectedFiltreStatut(FiltreStatut.ACTIF_PREVISION_TRANSITOIRE);
            }
            if (this.selectedEntiteDtoZoom.isInactif()
                    && !selectedFiltreStatut.equals(FiltreStatut.ACTIF_TRANSITOIRE_INACTIF)
                    && !selectedFiltreStatut.equals(FiltreStatut.TOUS)) {
                setSelectedFiltreStatut(FiltreStatut.TOUS);
            }

            Messagebox.show(
                    "Le filtre d'affichage a t chang pour vous permettre de visualiser correctement l'entit zoome",
                    "Information", Messagebox.OK, Messagebox.INFORMATION);
        }

        setEntity(this.selectedEntiteDtoZoom);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
        refreshArbreComplet();
        Clients.evalJavaScript(
                "refreshOrganigrammeSuiteZoom('" + "entite-id-" + this.selectedEntiteDtoZoom.getIdEntite() + "');");
    }

    public void selectionneEntiteRecherche(EntiteDto entiteDto) {
        setEntity(entiteDto);
        notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
        Clients.evalJavaScript("goToByScroll('" + entiteDto.getIdLi() + "');");
    }

    /**
     * Permet de zoomer sur une entit
     * 
     * @param entiteDto
     *            : l'entit sur laquelle zoomer
     */
    @Command
    public void zoomSurEntite(@BindingParam("entity") EntiteDto entiteDto) {
        selectionneEntiteZoom(entiteDto);
    }

    @Command
    public void selectionneFiltreStatut() {
        if (this.selectedFiltreStatut != null) {

            // Si une entit tait en dition, on vide pour ne pas se retrouver
            // dans des cas bizarre d'entit ouverte en dition alors qu'elle
            // n'est
            // pas prsente avec le fitre actif
            setEntity(null);
            majEntiteRootByFiltreAndZoom();
            treeViewModel.creeArbre(entiteDtoRoot);
            notifyChange(LISTE_PROP_A_NOTIFIER_ENTITE);
            Clients.evalJavaScript("refreshOrganigrammeWithoutSelectedEntite();");
        }
    }

    private void majEntiteRootByFiltreAndZoom() {
        // On recharge toujours  partir d'ADS avant de filtrer pour tre sur de
        // tout rcuprer  jour
        if (this.selectedFiltreStatut.equals(FiltreStatut.TOUS)) {
            // Si on est en zoom, on filtre uniquement sur les entits zoomes
            if (this.selectedEntiteDtoZoom != null) {
                entiteDtoRoot = adsWSConsumer.getEntiteWithChildren(this.selectedEntiteDtoZoom.getIdEntite());
            } else {
                entiteDtoRoot = adsWSConsumer.getCurrentTreeWithVDNRoot();
            }
        } else {
            // Si on est en zoom, on filtre uniquement sur les entits zoomes
            EntiteDto entiteDtoAFiltre = null;
            if (this.selectedEntiteDtoZoom != null) {
                entiteDtoAFiltre = adsWSConsumer.getEntiteWithChildren(this.selectedEntiteDtoZoom.getIdEntite());

            } else {
                entiteDtoAFiltre = adsWSConsumer.getCurrentTreeWithVDNRoot();
            }
            entiteDtoRoot = filtrerEntiteDtoRootParStatut(entiteDtoAFiltre, this.selectedFiltreStatut);
        }
    }

    /**
     * Renvoi une arborescence compos uniquement des statuts correspondant au
     * filtre pass en paramtre
     * 
     * @param entiteDto
     *            : l'entit root de l'arbre  filtrer
     * @param filtreStatut
     *            : le filtre a appliquer
     * @return un arbre ne contenant que les statuts correspondant au filtre
     */
    private EntiteDto filtrerEntiteDtoRootParStatut(EntiteDto entiteDto, FiltreStatut filtreStatut) {
        if (filtreStatut == null || entiteDto == null) {
            return null;
        }

        removeEntiteDtoIfNotInFiltre(entiteDto, filtreStatut);

        return entiteDto;
    }

    /**
     * Mthode rcursive qui parcoure les enfants et les enlve de l'arbre si
     * ils ne sont pas dans un des statuts du filtre
     * 
     * @param entiteDto
     *            : l'entit parcourue
     * @param filtreStatut
     *            : le filtre
     */
    private void removeEntiteDtoIfNotInFiltre(EntiteDto entiteDto, FiltreStatut filtreStatut) {
        List<EntiteDto> listeEnfant = new ArrayList<EntiteDto>();
        listeEnfant.addAll(entiteDto.getEnfants());
        for (EntiteDto entiteDtoEnfant : listeEnfant) {
            if (!filtreStatut.getListeStatut().contains(entiteDtoEnfant.getStatut())) {
                entiteDto.getEnfants().remove(entiteDtoEnfant);
                // bug #20959
                if (mapIdLiOuvert.containsKey(entiteDtoEnfant.getIdLi())) {
                    mapIdLiOuvert.remove(entiteDtoEnfant.getIdLi());
                }
            } else {
                // bug #20959
                mapIdLiOuvert.put(entiteDtoEnfant.getIdLi(), true);
                removeEntiteDtoIfNotInFiltre(entiteDtoEnfant, filtreStatut);
            }
        }
    }

    public List<FiltreStatut> getListeFiltreStatut() {
        return Arrays.asList(FiltreStatut.values());
    }

    public String getComboVide() {
        return null;
    }

    public String getUrlImageFavoris() {
        if (this.entity != null && !CollectionUtils.isEmpty(this.listeEntiteFavorisDto)) {
            for (EntiteDto entiteDto : this.listeEntiteFavorisDto) {
                if (entiteDto.getIdEntite().equals(this.entity.getIdEntite())) {
                    return "/imgs/icon/favoris.png";
                }
            }
        }

        return "/imgs/icon/no-favoris.png";
    }

    /**
     * Ajoute ou retire une entit favoris
     * 
     * @param entiteDto
     *            l'entit dto qu'on souhaite ajouter
     */
    @NotifyChange({ "urlImageFavoris", "listeEntiteFavorisDto", "selectedEntiteDtoZoomIhm" })
    @Command
    public void ajoutOuRetireFavoris(@BindingParam("entity") EntiteDto entiteDto) {
        boolean dejaFavoris = false;
        if (this.entity != null && !CollectionUtils.isEmpty(this.listeEntiteFavorisDto)) {
            for (EntiteDto entiteFavorisDto : this.listeEntiteFavorisDto) {
                if (entiteFavorisDto.getIdEntite().equals(entiteDto.getIdEntite())) {
                    this.listeEntiteFavorisDto.remove(entiteFavorisDto);
                    EntiteFavoris entiteFavoris = entiteFavorisService.findByIdAgentAndIdEntite(
                            this.profilAgentDto.getIdAgent(), entiteFavorisDto.getIdEntite());
                    entiteFavorisService.delete(entiteFavoris);
                    dejaFavoris = true;
                    Clients.showNotification(
                            "L'entit " + this.entity.getSigle() + " a t retire de vos favoris.", "info",
                            null, "top_center", 0);
                    break;
                }
            }
        }

        if (!dejaFavoris) {
            EntiteFavoris entiteFavoris = new EntiteFavoris();
            entiteFavoris.setIdAgent(this.profilAgentDto.getIdAgent());
            entiteFavoris.setIdEntite(entiteDto.getIdEntite());
            entiteFavorisService.save(entiteFavoris);

            this.listeEntiteFavorisDto.add(mapIdLiEntiteDto.get("entite-id-" + entiteFavoris.getIdEntite()));
            Clients.showNotification("L'entit " + this.entity.getSigle() + " a t ajoute  vos favoris.",
                    "info", null, "top_center", 0);
        }
    }

    /**
     * Exporte au format GraphML l'arbre ayant pour racine l'{@link EntiteDto}
     * entiteDto
     * 
     * @param entiteDto
     *            l'entit root de l'export
     */
    @Command
    public void lancerExport(@BindingParam("entity") EntiteDto entiteDto) {
        try {
            exportGraphMLService.exportGraphMLFromEntite(
                    mapIdLiEntiteDto.get("entite-id-" + entiteDto.getIdEntite()), this.selectedFiltreStatut,
                    mapIdLiOuvert);
        } catch (IOException e) {
            AbstractViewModel.showErrorPopup(
                    "Une erreur est survenu lors de l'ajout du logo de la Mairie dans le fichier d'export");
        }
    }

    @Command
    public void ouvrirPopupCreateDuplication(@BindingParam("entity") EntiteDto entiteDto) {
        DuplicationDto duplicationDto = new DuplicationDto();
        duplicationDto.setEntiteDto(entiteDto);
        Map<String, Object> args = new HashMap<>();
        args.put("duplicationDto", duplicationDto);
        Executions.createComponents("/layout/createDuplication.zul", null, null);
        BindUtils.postGlobalCommand(null, null, "ouvrePopupCreationDuplication", args);
    }

    public EntiteDtoQueryListModel getEntiteDtoQueryListModelZoomable() {
        return new EntiteDtoQueryListModel(adsWSConsumer.getAllEntiteAPlat(null));
    }

    @Command
    public void zoom() {
        if (this.selectedEntiteDtoZoomIhm != null) {
            selectionneEntiteZoom(this.selectedEntiteDtoZoomIhm);
            this.selectedEntiteDtoZoomIhm = null;
        }
    }

    @Command
    public void recherche() {
        if (this.selectedEntiteDtoRechercheIhm != null) {
            selectionneEntiteRecherche(this.selectedEntiteDtoRechercheIhm);
        }
    }

    /**
     * Permet de savoir si l'entit en cours est une feuille selon le statut
     * selectionn. Elle peux avoir des enfants mais qui ne sont pas affichs
     * avec le filtre en cours, du coup a renverra true
     * 
     * @return true si l'entit en cours n'a pas d'enfants en visuel selon le
     *         filtre en cours
     */
    public boolean isFeuilleSelonFiltreStatut() {
        if (this.entity == null) {
            return true;
        }

        if (this.entity.isFeuille()) {
            return true;
        }

        EntiteDto entiteDtoIhm = rechercheEntiteIhm(this.entiteDtoRoot, this.entity, null);
        if (entiteDtoIhm == null) {
            return true;
        }

        return CollectionUtils.isEmpty(entiteDtoIhm.getEnfants());
    }

    private EntiteDto rechercheEntiteIhm(EntiteDto entiteDto, EntiteDto entiteDtoRecherche, EntiteDto result) {
        if (result != null) {
            return result;
        }
        if (entiteDto.getId().equals(entiteDtoRecherche.getId())) {
            result = entiteDto;
        } else {
            for (EntiteDto entiteDtoEnfant : entiteDto.getEnfants()) {
                result = rechercheEntiteIhm(entiteDtoEnfant, entiteDtoRecherche, result);
            }
        }

        return result;
    }
}