Java tutorial
package nc.noumea.mairie.appock.core.viewmodel; /*- * #%L * Logiciel de Gestion des approvisionnements et des stocks des fournitures administratives de la Mairie de Nouma * %% * Copyright (C) 2017 Mairie de Nouma, Nouvelle-Caldonie * %% * 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.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import org.zkoss.bind.BindUtils; import org.zkoss.bind.annotation.BindingParam; import org.zkoss.bind.annotation.Command; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.event.EventQueue; import org.zkoss.zk.ui.event.EventQueues; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.ListModelList; import org.zkoss.zul.Messagebox; import org.zkoss.zul.Window; import nc.noumea.mairie.appock.controller.MainController; import nc.noumea.mairie.appock.core.entity.AbstractEntity; import nc.noumea.mairie.appock.core.services.GenericService; import nc.noumea.mairie.appock.core.utility.ApplicationContextUtils; import nc.noumea.mairie.appock.core.utility.AppockUtil; import nc.noumea.mairie.appock.core.utility.MessageErreur; import nc.noumea.mairie.appock.core.utility.MessageErreurUtil; import nc.noumea.mairie.appock.event.*; /** * ViewModel abstrait parent des ViewModel de l'application qui manipulent une entit (cration, modification, et mme liste o on considre que l'entit est * celle slectionne dans la liste) * * @author AgileSoft.NC * @param <T> Type paramtr (reprsente une classe d'entit en pratique) */ public abstract class AbstractViewModel<T extends AbstractEntity> { private static Logger log = LoggerFactory.getLogger(AbstractViewModel.class); protected T entity; /** * @return l'entit concerne */ public T getEntity() { return entity; } /** * Fixe l'entit concern par le ViewModel * * @param entity entit concerne */ public void setEntity(T entity) { this.entity = entity; } /** * Mthode utilitaire, pour lister les valeurs d'une numration (dans l'ordre de leur dclaration). * * @param enumClassName nom complet de la classe (avec le package, ex : "nc.noumea.mairie.appock.enums.TypeConfig") * @return la liste des valeurs numres, dans l'ordre de leur dclaration. */ public ListModelList<?> getListeEnum(String enumClassName) { return getListeEnum(enumClassName, false); } /** * Mthode utilitaire, pour lister les valeurs d'une numration (dans l'ordre de leur dclaration), avec la possibilit d'insrer en tte la valeur null. * * @param enumClassName nom complet de la classe (avec le package, ex : "nc.noumea.mairie.appock.enums.TypeConfig") * @param insertNull indique s'il faut insrer en tte de la liste rsultat la valeur null * @return la liste des valeurs numres, dans l'ordre de leur dclaration (avec null en tte optionnellement) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public ListModelList<?> getListeEnum(String enumClassName, boolean insertNull) { try { Class<?> classe = Class.forName(enumClassName); ListModelList result = new ListModelList(classe.getEnumConstants()); if (insertNull) { result.add(0, null); } return result; } catch (ClassNotFoundException e) { log.error("erreur sur getListeEnum", e); Messagebox.show(e.toString()); } return null; } /** * Publie un vnement de demande d'ouverture d'une entity dans un nouvel onglet (ou dans un onglet existant si l'entity est dj ouverte) * * @param abstractEntity entit concerne * @param editViewURI la vue si on souhaite surcharger le comportement par dfaut */ @Command public void ouvreOnglet(@BindingParam("entity") AbstractEntity abstractEntity, String editViewURI) { defaultPublishOnAppockQueue().publish(new OuvreOngletAbstractEntityEvent(abstractEntity, editViewURI)); } /** * Publie un vnement de demande de fermeture d'un onglet qui concerne une entity * * @param abstractEntity entit concerne */ public void fermeOnglet(@BindingParam("entity") T abstractEntity) { defaultPublishOnAppockQueue().publish(new FermeOngletAbstractEntityEvent(abstractEntity)); } /** * Publie un vnement de demande de recharge de l'entity, dans l'onglet couramment slectionn */ @Command public void rechargeOnglet() { rechargeOnglet(entity, null, null); } /** * Publie un vnement de demande de recharge de l'onglet d'une liste */ @Command public void rechargeOngletListe() { defaultPublishOnAppockQueue().publish(new RechargeOngletListAbstractEntityEvent(entity)); } /** * Publie un vnement de demande de recharge de l'entity, dans l'onglet couramment slectionn (ou dans l'onglet indiqu) * @param abstractEntity l'entit recharger * @param editViewURI l'url de la page d'dition (si null, comportement par dfaut, la page sera trouve partir du nom de la classe de l'abstractEntity) * @param titreOnglet titre de l'onglet (si null, comportement par dfaut, le titre sera trouv partir du nom de la classe de l'abstractEntity) */ protected void rechargeOnglet(AbstractEntity abstractEntity, String editViewURI, String titreOnglet) { defaultPublishOnAppockQueue() .publish(new RechargeOngletAbstractEntityEvent(abstractEntity, editViewURI, titreOnglet)); } /** * Publie un vnement de demande de recharge de l'onglet de liste des demandes */ protected void rechargeOngletListeDemande() { refreshOngletGeneric(MainController.TITRE_DEMANDE, "layout/listeDemande.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des commandes termines */ protected void rechargeOngletListeCommandeTermine() { refreshOngletGeneric(MainController.TITRE_RECEPTION_COMMANDE_SERVICE_TERMINE, "layout/listeCommandeServiceTermine.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des demandes traiter */ protected void rechargeOngletListeDemandeATraiter() { refreshOngletGeneric(MainController.TITRE_DEMANDE_A_TRAITER, "layout/listeDemandeATraiter.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des demandes commander */ protected void rechargeOngletListeDemandeACommander() { refreshOngletGeneric(MainController.TITRE_DEMANDE_A_COMMANDER, "layout/listeDemandeACommander.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des commandes */ protected void rechargeOngletListeCommande() { refreshOngletGeneric(MainController.TITRE_COMMANDE_A_PASSER, "layout/listeCommandeAPasser.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des rception commandes */ protected void rechargeOngletListeReceptionCommande() { refreshOngletGeneric(MainController.TITRE_RECEPTION_COMMANDE_SERVICE, "layout/listeReceptionCommandeService.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des commandes rceptionnes */ protected void rechargeOngletListeCommandeReceptionne() { refreshOngletGeneric(MainController.TITRE_COMMANDE_ARCHIVE, "layout/listeCommandeArchive.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des rception de commandes valider */ protected void rechargeOngletListeCommandeValiderLivraison() { refreshOngletGeneric(MainController.TITRE_COMMANDE_VALIDE_LIVRAISON, "layout/listeCommandeValiderLivraison.zul"); } /** * Publie un vnement de demande de recharge de l'onglet de liste des commandes */ protected void rechargeOngletMonStock() { refreshOngletGeneric(MainController.TITRE_GESTION_STOCK_REFERENT_SERVICE, "layout/editStockReferentService.zul"); } protected void refreshOngletGeneric(String titreOnglet, String viewUri) { RechargeOngletGenericEvent event = new RechargeOngletGenericEvent(titreOnglet, viewUri); defaultPublishOnAppockQueue().publish(event); } protected void rechargeOngletListeReferentAchat() { rechargeOngletListeDemandeATraiter(); rechargeOngletListeDemandeACommander(); rechargeOngletListeCommande(); rechargeOngletListeReceptionCommande(); rechargeOngletListeCommandeReceptionne(); rechargeOngletListeCommandeValiderLivraison(); } /** * Publie un vnement de demande de mise jour du libell de l'onglet qui gre l'entity passe en argument. * * @param abstractEntity entit concerne */ @Command public void updateOnglet(@BindingParam("entity") T abstractEntity) { defaultPublishOnAppockQueue().publish(new UpdateOngletAbstractEntityEvent(abstractEntity)); } public GenericService<T> getService() { return (GenericService<T>) ApplicationContextUtils.getApplicationContext() .getBean(StringUtils.uncapitalize(getEntityName()) + "Service"); } /** * Retourne le nom simple de la classe de l'entit T * * @return ex : "Projet" */ public String getEntityName() { return AppockUtil.getSimpleNameOfClass(getEntityClass()); } /** * Retourne la classe paramtr de l'AbstractViewModel courant. * * @return ex : Projet.class dans le cas d'un ViewModel paramtr par T = Projet. */ @SuppressWarnings("unchecked") protected Class<T> getEntityClass() { return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } /** * Instancie un nouvel objet T * * @return instance cre * @throws InstantiationException en cas d'erreur la cration de l'entity * @throws IllegalAccessException en cas d'erreur la cration de l'entity */ protected T createEntity() throws InstantiationException, IllegalAccessException { return getEntityClass().newInstance(); } /** * Poste une commande globale pour signaler la mise jour de l'entity gre par le ViewModel courant, en prcisant en argument l'entit concerne. Exemple * de commande globale : "updateProjet" */ public void notifyUpdateEntity() { Map<String, Object> args = new HashMap<String, Object>(); args.put("entity", entity); BindUtils.postGlobalCommand(null, null, "update" + getEntityName(), args); } /** * Poste une commande globale pour signaler la mise jour d'une entity quelconque. Exemple de commande globale : "updateDemandeur" * * @param entityUpdated entity concerne */ protected void notifyUpdateEntity(AbstractEntity entityUpdated) { if (entityUpdated == null) { return; } Map<String, Object> args = new HashMap<String, Object>(); args.put("entity", entityUpdated); BindUtils.postGlobalCommand(null, null, "update" + AppockUtil.getSimpleClassNameOfObject(entityUpdated), args); } public static void notifyChange(String prop, Object bean) { BindUtils.postNotifyChange(null, null, bean, prop); } public void notifyChange(String prop) { notifyChange(prop, this); } public static void notifyChange(String[] listProperty, Object bean) { if (listProperty == null) { return; } if (Executions.getCurrent() == null) { return; } for (String prop : listProperty) { if (!StringUtils.isBlank(prop)) { notifyChange(prop, bean); } } } public void notifyChange(String[] listProperty) { notifyChange(listProperty, this); } public void postGlobalCommandRefreshListe() { BindUtils.postGlobalCommand(null, null, "refreshListe" + getEntityName(), null); } /** * Affiche une popup d'erreur, concernant une liste d'erreurs (si la liste est null ou fait 0 lment, la mthode ne fait rien) * * @param listeMessageErreur liste de messages d'erreur afficher * @return true si au moins un message a t affich */ public static boolean showErrorPopup(List<MessageErreur> listeMessageErreur) { if (CollectionUtils.isEmpty(listeMessageErreur)) { return false; } Messagebox.show(MessageErreurUtil.construitReprListeMessageErreur(listeMessageErreur), "Erreur", Messagebox.OK, Messagebox.ERROR); return true; } /** * Affiche une popup modale de messages d'erreur concernant l'entit (les erreurs spcifiques mtier et les violations de contraintes observes sur * l'entit) * * @param entity entit concerne * @return true si des erreurs ont t affichs, false si aucune erreur */ public static boolean showErrorPopup(AbstractEntity entity) { return showErrorPopup(entity.construitListeMessageErreur()); } /** * Affiche une popup d'erreur, concernant une erreur unique * * @param message Message d'erreur (si le message est "blanc", la mthode ne fait rien) * @return true si un message (non vide) a t affich, false sinon */ public static boolean showErrorPopup(String message) { if (StringUtils.isBlank(message)) { return false; } List<MessageErreur> listeMessageErreur = new ArrayList<>(); listeMessageErreur.add(new MessageErreur(message)); return AbstractViewModel.showErrorPopup(listeMessageErreur); } public void showNotificationStandard(String message) { Clients.showNotification(message, "info", null, "bottom_center", 3000); } public Integer getMaxLength(Object object, String property) throws Exception { return AppockUtil.getMaxLength(object, property); } public Integer getMaxLengthClassProperty(String className, String property) throws Exception { return AppockUtil.getMaxLengthClassProperty(className, property); } public Object ouvrePopupCreation(String template) throws InstantiationException, IllegalAccessException { Map<String, Object> arguments = new HashMap<String, Object>(); T windowEntity = getEntityClass().newInstance(); arguments.put("entity", windowEntity); Window window = (Window) Executions.createComponents(template, null, arguments); window.doModal(); return windowEntity; } private EventQueue defaultPublishOnAppockQueue() { return EventQueues.lookup("appockQueue", EventQueues.DESKTOP, true); } }