package nc.noumea.mairie.organigramme.viewmodel; /* * #%L * Logiciel de Gestion des Organigrammes de la Ville de Nouméa * $Id:$ * $HeadURL:$ * %% * Copyright (C) 2015 Mairie de Nouméa * %% * 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.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import nc.noumea.mairie.organigramme.core.utility.DateUtil; import nc.noumea.mairie.organigramme.core.utility.OrganigrammeUtil; import nc.noumea.mairie.organigramme.core.viewmodel.AbstractViewModel; import nc.noumea.mairie.organigramme.dto.EntiteDto; import nc.noumea.mairie.organigramme.entity.CouleurTypeEntite; import nc.noumea.mairie.organigramme.enums.Statut; import nc.noumea.mairie.organigramme.query.EntiteDtoQueryListModel; import org.apache.commons.lang.StringUtils; import org.springframework.util.CollectionUtils; import org.zkoss.zhtml.Li; import org.zkoss.zhtml.Ul; import org.zkoss.zk.ui.Component; import org.zkoss.zul.Label; import org.zkoss.zul.Vlayout; /** * Classe utilitaire permettant de créer l'organigramme */ public class TreeViewModel extends AbstractViewModel<EntiteDto> implements Serializable { private static final long serialVersionUID = 1L; private OrganigrammeViewModel organigrammeViewModel; public TreeViewModel(OrganigrammeViewModel organigrammeViewModel) { this.organigrammeViewModel = organigrammeViewModel; } public EntiteDto entity() { return organigrammeViewModel.getEntity(); } /** * Crée l'arbre et l'ajoute au {@link Vlayout} client * * @param entiteDtoRoot * : l'ancien arbre */ public void creeArbre(EntiteDto entiteDtoRoot) { // On renseigne deux map<idTypeEntite, couleur> qui permettront de // setter chaque couleur de chaque EntiteDto de l'arbre Map<Long, String> mapIdTypeEntiteCouleurEntite = new HashMap<Long, String>(); Map<Long, String> mapIdTypeEntiteCouleurTexte = new HashMap<Long, String>(); List<CouleurTypeEntite> listeCouleurTypeEntite = organigrammeViewModel.couleurTypeEntiteService.findAll(); for (CouleurTypeEntite couleurTypeEntite : listeCouleurTypeEntite) { mapIdTypeEntiteCouleurEntite.put(new Long(couleurTypeEntite.getIdTypeEntite()), couleurTypeEntite.getCouleurEntite()); mapIdTypeEntiteCouleurTexte.put(new Long(couleurTypeEntite.getIdTypeEntite()), couleurTypeEntite.getCouleurTexte()); } Vlayout vlayout = organigrammeViewModel.vlayout; Component arbre = genereArbre(organigrammeViewModel.entiteDtoRoot, mapIdTypeEntiteCouleurEntite, mapIdTypeEntiteCouleurTexte); if (!CollectionUtils.isEmpty(vlayout.getChildren())) { vlayout.removeChild(vlayout.getChildren().get(0)); } if (arbre == null) { return; } vlayout.appendChild(arbre); } /** * Génére les composants {@link Ul}/{@link Li} qui forment l'arbre (ces * {@link Ul}/{@link Li} html seront retravaillées par le plugin jQuery Org * Chart afin de les transformer en div/table/tr/td et de les afficher sous * forme d'arbre) * * @param entiteDto * : le {@link EntiteDto} racine qui contient tout l'arbre * @param mapIdTypeEntiteCouleurEntite * : la map des différentes couleurs pour les types d'entités qui * va nous permettre de setter chaque couleur de chaque type * d'entité * @param mapIdTypeEntiteCouleurTexte * : la map des différentes couleurs pour les types d'entités qui * va nous permettre de setter chaque couleur de chaque type * d'entité * @return le {@link Ul} de plus haut niveau qui est ajouté au * {@link Vlayout} */ public Component genereArbre(EntiteDto entiteDto, Map<Long, String> mapIdTypeEntiteCouleurEntite, Map<Long, String> mapIdTypeEntiteCouleurTexte) { if (entiteDto == null) { return null; } // On vide la map de correspondance id HTML<->EntiteDTO car on va la // renseigner dans creeLiEntite() organigrammeViewModel.mapIdLiEntiteDto = new HashMap<String, EntiteDto>(); // On recrée la liste de toutes les entités organigrammeViewModel.setListeEntite(new ArrayList<EntiteDto>()); // Initialisation de l'entité ROOT Ul ulRoot = new Ul(); ulRoot.setId("organigramme-root"); ulRoot.setSclass("hide"); setCouleur(mapIdTypeEntiteCouleurEntite, mapIdTypeEntiteCouleurTexte, entiteDto); Li li = creeLiEntite(ulRoot, entiteDto); organigrammeViewModel.getListeEntite().add(entiteDto); // Initialisation du reste de l'arbre genereArborescenceHtml(entiteDto.getEnfants(), li, mapIdTypeEntiteCouleurEntite, mapIdTypeEntiteCouleurTexte); // Maintenant qu'on a setté la liste de entités disponibles à la // recherche, on renseigne la ListModel organigrammeViewModel.setEntiteDtoQueryListModelRecherchable(new EntiteDtoQueryListModel(organigrammeViewModel.getListeEntite())); return ulRoot; } /** * Méthode récursive pour générer tous les {@link Ul}/{@link Li} formant * l'arbre * * @param listeEntiteDTO * : la liste des enfants de l'entité courante * @param component * : le composant sous lequel ajouter les enfants * @param mapIdTypeEntiteCouleur * : la map des différentes couleurs pour les types d'entités qui * va nous permettre de setter chaque couleur de chaque type * d'entité mapIdTypeEntiteCouleurTexte : la map des différentes * couleurs pour les types d'entités qui va nous permettre de * setter chaque couleur de chaque type d'entité * @param mapIdTypeEntiteCouleurTexte * : la map contenant les différentes couleurs selon le type de * l'entité * @return l'Ul représentant l'arbre complet (sans l'entité root qui est * initialisée dans "genereArbre") */ public Component genereArborescenceHtml(List<EntiteDto> listeEntiteDTO, Component component, Map<Long, String> mapIdTypeEntiteCouleur, Map<Long, String> mapIdTypeEntiteCouleurTexte) { Ul ul = new Ul(); ul.setParent(component); for (final EntiteDto entiteDto : listeEntiteDTO) { setCouleur(mapIdTypeEntiteCouleur, mapIdTypeEntiteCouleurTexte, entiteDto); Li li = creeLiEntite(ul, entiteDto); organigrammeViewModel.getListeEntite().add(entiteDto); if (entiteDto.hasChildren()) { genereArborescenceHtml(entiteDto.getEnfants(), li, mapIdTypeEntiteCouleur, mapIdTypeEntiteCouleurTexte); } } return ul; } private void setCouleur(Map<Long, String> mapIdTypeEntiteCouleurEntite, Map<Long, String> mapIdTypeEntiteCouleurTexte, final EntiteDto entiteDto) { // On set la couleur du type d'entité if (entiteDto.getTypeEntite() != null) { entiteDto.getTypeEntite().setCouleurEntite(mapIdTypeEntiteCouleurEntite.get(entiteDto.getTypeEntite().getId())); entiteDto.getTypeEntite().setCouleurTexte(mapIdTypeEntiteCouleurTexte.get(entiteDto.getTypeEntite().getId())); } } /** * Crée une feuille unitaire et lui ajoute un événement onClick qui * permettra d'effecture des opérations sur cette feuille * * @param ul * : le {@link Ul} parent * @param entiteDto * : l'{@link EntiteDto} a transformer en {@link Li} * @return le composant {@link Li} représentant l'entité */ public Li creeLiEntite(Ul ul, final EntiteDto entiteDto) { Li li = new Li(); String sigleSplit = OrganigrammeUtil.splitByNumberAndSeparator(entiteDto.getSigle(), 8, "\n"); li.appendChild(new Label(sigleSplit)); li.setParent(ul); li.setSclass("statut-" + StringUtils.lowerCase(entiteDto.getStatut().name())); li.setDynamicProperty("title", creeTooltipEntite(entiteDto)); boolean couleurEntiteTypeEntiteRenseigne = entiteDto.getTypeEntite() != null && !StringUtils.isBlank(entiteDto.getTypeEntite().getCouleurEntite()); if (couleurEntiteTypeEntiteRenseigne) { String style = "background-color:" + entiteDto.getTypeEntite().getCouleurEntite() + "; color:" + entiteDto.getTypeEntite().getCouleurTexte() + ";"; if (entiteDto.getStatut().equals(Statut.PREVISION)) { style += "border-color: " + entiteDto.getTypeEntite().getCouleurTexte() + ";"; } li.setStyle(style); } else { li.setStyle("background-color:#FFFFCF; color:#000000;"); } li.setId("entite-id-" + entiteDto.getId().toString()); // On maintient une map permettant d'aller plus vite lors d'un click // event pour retrouver l'EntiteDto correspondant à l'id du Li organigrammeViewModel.mapIdLiEntiteDto.put(li.getId(), entiteDto); return li; } private String creeTooltipEntite(EntiteDto entiteDto) { List<String> tooltip = new ArrayList<String>(); tooltip.add(entiteDto.getLibelleTypeEntite() + " - " + entiteDto.getLabel()); if (entiteDto.getDateDeliberationActif() != null) { tooltip.add("Date délib./CTP activation : " + DateUtil.formatDate(entiteDto.getDateDeliberationActif()) + " - " + entiteDto.getRefDeliberationActif()); } if (entiteDto.getDateDeliberationInactif() != null) { tooltip.add("Date délib./CTP inactivation : " + DateUtil.formatDate(entiteDto.getDateDeliberationInactif()) + " - " + entiteDto.getRefDeliberationInactif()); } if (StringUtils.isNotBlank(entiteDto.getNfa())) { tooltip.add("NFA : " + entiteDto.getNfa()); } if (entiteDto.getEntiteRemplacee() != null) { tooltip.add("Remplace : " + entiteDto.getEntiteRemplacee().getSigle()); } if (!StringUtils.isBlank(entiteDto.getCommentaire())) { tooltip.add("<br/>" + entiteDto.getCommentaire()); } return StringUtils.join(tooltip, "<br/>"); } }