Subversion Repositories eFlore/Applications.coel

Rev

Rev 1613 | Rev 1860 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package org.tela_botanica.client.modeles;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.tela_botanica.client.util.UtilArray;
import org.tela_botanica.client.util.UtilString;

import com.extjs.gxt.ui.client.core.FastMap;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONObject;

/**
 * @author jpm
 *
 */
public abstract class aDonnee extends BaseModelData implements Serializable {

        private static final long serialVersionUID = 3527760464061629791L;
        
        public static final boolean SUPPRIMER_PREFIXE = true;
        public static final boolean GARDER_PREFIXE = false;
        public static final boolean INTEGRER_PROPRIETES = true;
        public static final String TYPE_AUTRE = "AUTRE";
        public static final String TYPE_TOTAL = "TOTAL";
        public static final String SEPARATEUR_TYPE_VALEUR = "##";
        public static final String SEPARATEUR_VALEURS = ";;";
        public static final String SEPARATEUR_DONNEES = "||";
        public static final String ETAT_AJOUTE = "A";
        public static final String ETAT_MODIFIE = "M";
        public static final String VALEUR_NULL = "NC";

        public HashMap<String, String> valeursInitiales = new HashMap<String, String>();
        protected boolean removePrefix = true;

        protected abstract String getPrefixe();
        protected abstract String[] getChampsObligatoires();
        
        public String getDateModification() {
                return (String) renvoyerValeurCorrecte("cmhl_date_modification");
        }
        
        public String getNotes() {
                return (String) renvoyerValeurCorrecte("cmhl_notes");
        }
        
        public String getIdModifierPar() {
                return (String) renvoyerValeurCorrecte("cmhl_ce_modifier_par");
        }
        
        public String getIdEtat() {
                return (String) renvoyerValeurCorrecte("cmhl_ce_etat");
        }
        
        public String getIp() {
                return (String) renvoyerValeurCorrecte("cmhl_ip");
        }
        
        protected void initialiserModele(JSONObject jsonObjet) {
                // l'objet JSON est une table de hachage
                Set<String> im = jsonObjet.keySet();
                valeursInitiales = new HashMap<String, String>();
                
                // Parcourt pour chaque clé
                for (Iterator<String> it = im.iterator(); it.hasNext();) {
                        // Si elle est associée à une valeur, nous l'ajoutons
                        String cle = it.next();
                        if (cle.startsWith(getPrefixe()+"_") ||cle.matches("^_.+_$")) {
                                // Suppression de l'abréviation du champ. Inutile dans le contexte d'un objet
                                String cleObjet = cle.replaceFirst("^"+getPrefixe()+"_", "");
                                // Sinon, nous ajoutons la clé avec une valeur vide
                                String valeur = "";
                                if (jsonObjet.get(cle).isString() != null) {
                                        valeur = jsonObjet.get(cle).isString().stringValue();
                                }
                                valeursInitiales.put(cleObjet, valeur);
                                this.set(cleObjet, valeur);
                        } 
                }
        }
        
        public void setValeurInitiale(String cleObjet, String valeur) {}

        /**
         * Pour éviter que l'on traite des valeurs nulles à l'affichage on passe par
         * cette fonction qui retire les charactères nuls qui font planter
         * l'affichage, il ne faut pas utiliser get directement.
         * Elle ajoute aussi le préfixe au nom du champ si nécessaire.
         * 
         * @param cle le nom du champ sans le préfixe.
         * @return la valeur associée à la clé
         */
        protected String renvoyerValeurCorrecte(String cle) {
                String sortie = "";
                cle = gererPrefixe(cle);
                if (this.get(cle) != null) {
                        String valeur = ""+this.get(cle);
                        if (! valeur.equals("null")) {
                                char nullChar = '\u0000';
                                String sNull = "" + nullChar;
                                valeur = valeur.replaceAll(sNull, "");
                                sortie =  valeur;
                        }
                }
                
                return sortie;
        }
        
        /**
         * Ajoute le préfixe au nom du champ si nécessaire.
         * 
         * @param la clé du champ
         * @param la valeur associé à la clé
         */
        protected void setValeurCorrecte(String cle, String valeur) {
                cle = gererPrefixe(cle);
                set(cle, valeur);
        }
        
        /**
         * Ajoute un nouvel élément avec son type à une chaine dénormalisée.
         * Champ de type "truk" contenant des valeurs séparées par ";;" qui elle même possèdent un type séparé par "##".
         * Si l'élément existe déjà, il ne sera pas ajouté.
         * 
         * @param champ le nom du champ dénormalisé
         * @param type le type de la valeur à ajouter
         * @param valeur la valeur à ajouter
         */
        protected void ajouterChaineDenormaliseAvecType(String champ, String type, Object valeur) {
                if (valeur instanceof String) {
                        String chaineExistante = renvoyerValeurCorrecte(champ);
                        if (UtilString.isEmpty(chaineExistante)) {
                                this.set(champ, type+SEPARATEUR_TYPE_VALEUR+valeur);
                        } else {
                                // Si la valeur à ajouter n'est pas déjà présente, nous l'ajoutons
                                if (!chaineExistante.matches("(^|"+SEPARATEUR_VALEURS+")"+type+SEPARATEUR_TYPE_VALEUR+valeur+"("+SEPARATEUR_VALEURS+"|$)")) {
                                        this.set(champ, chaineExistante+";;"+type+SEPARATEUR_TYPE_VALEUR+valeur);
                                }
                        }
                }
        }
        
        protected void supprimerTypeDansChaineDenormalise(String champ, String type) {
                String chaineExistante = renvoyerValeurCorrecte(champ);
                if (!UtilString.isEmpty(chaineExistante)) {
                        if (chaineExistante.matches("(?:^|.*"+SEPARATEUR_VALEURS+")"+type+SEPARATEUR_TYPE_VALEUR+".*")) {
                                chaineExistante = chaineExistante.replaceFirst("(^|.*"+SEPARATEUR_VALEURS+")"+type+SEPARATEUR_TYPE_VALEUR+".*?("+SEPARATEUR_VALEURS+".*|$)", "$1$2");
                                chaineExistante = chaineExistante.replaceAll("(.*)"+SEPARATEUR_VALEURS+SEPARATEUR_VALEURS+"(.*)", "$1"+SEPARATEUR_VALEURS+"$2");
                                chaineExistante = chaineExistante.replaceAll("^"+SEPARATEUR_VALEURS+"(.*)", "$1");
                                chaineExistante = chaineExistante.replaceAll("(.*)"+SEPARATEUR_VALEURS+"$", "$1");
                                this.set(champ, chaineExistante);
                        }
                }
        }
        
        protected void remplacerTypeDansChaineDenormalise(String champ, String type, Object valeur) {
                if (valeur != null && !valeur.equals("")) {
                        ajouterChaineDenormaliseAvecType(champ, type, valeur);
                } else {
                        supprimerTypeDansChaineDenormalise(champ, type);
                }
        }
        
        /**
         * Ajoute un nouvel élément sans type à une chaine dénormalisée.
         * Champ de type "truk" contenant seulement des valeurs séparées par ";;".
         * Si l'élément existe déjà, il ne sera pas ajouté.
         * 
         * @param champ le nom du champ dénormalisé
         * @param valeur la valeur à ajouter
         */
        protected void ajouterChaineDenormalise(String champ, Object valeur) {
                if (valeur instanceof String) {
                        String chaineExistante = renvoyerValeurCorrecte(champ);
                        if (UtilString.isEmpty(chaineExistante)) {
                                this.set(champ, valeur);
                        } else {
                                // Si la valeur à ajouter n'est pas déjà présente, nous l'ajoutons
                                if (!chaineExistante.matches("(^|"+SEPARATEUR_VALEURS+")"+valeur+"("+SEPARATEUR_VALEURS+"|$)")) {
                                        this.set(champ, chaineExistante+SEPARATEUR_VALEURS+valeur);
                                }
                        }
                }
        }
        
        /**
         * Permet de constuire correctement une chaine dénormalisée unique (champ de type "ce_truk").
         * 
         * @param champ le nom du champ dénormalisé
         * @param type le type de la valeur à ajouter
         * @param valeur la valeur à ajouter
         */
        protected void setChaineDenormaliseUnique(String champ, String type, String valeur) {
                champ = gererPrefixe(champ);
                if (valeur == null || UtilString.isEmpty(valeur)) {
                        this.set(champ, "");
                } else if (valeur instanceof String) {
                        if (((String) valeur).matches("^[0-9]+$")) {
                                this.set(champ, valeur);
                        } else {
                                this.set(champ, type+SEPARATEUR_TYPE_VALEUR+valeur);
                        }
                }
        }
        
        private String gererPrefixe(String champ) {
                String champMisAJour = null;
                String prefixe = getPrefixe()+"_";
                if (removePrefix) {
                        champMisAJour = champ.replaceFirst(prefixe, "");
                } else {
                        champMisAJour = (champ.startsWith(prefixe)) ? champ : prefixe+champ ;
                }
                return champMisAJour;
        }
        
        /**
         * Permet de récupérer pour l'affichage une chaine dénormalisée unique (champ de type "ce_truk").
         * 
         * @param champ le nom du champ dénormalisé
         */
        protected String getChaineDenormaliseUnique(String champ) {
                String valeur = renvoyerValeurCorrecte(champ);
                
                if (!UtilString.isEmpty(valeur)) {
                        valeur = valeur.replaceFirst("^"+TYPE_AUTRE+SEPARATEUR_TYPE_VALEUR, "");
                }
                
                return valeur;
        }
        
        protected String getInfoDenormaliseParType(String chaineExistante, String type) {
                String sortie = "";
                if (!UtilString.isEmpty(chaineExistante)) {
                        String[] valeurs = chaineExistante.split(SEPARATEUR_VALEURS);
                        for (int i = 0; i < valeurs.length; i++) {
                                if (valeurs[i].startsWith(type+SEPARATEUR_TYPE_VALEUR)) {
                                        sortie =  valeurs[i].replaceFirst("^"+type+SEPARATEUR_TYPE_VALEUR, "");
                                }
                        }
                }
                return sortie;
        }
        
        /**
         * Permet de récupérer une map avec toutes les valeurs de la chaine truk sous la forme clé => valeur
         * 
         * @param champ le nom du champ dénormalisé
         * @return map ou liste en fonction du type de chaine truk (list si champ;;champ;; map si type##champ;;)
         */
        public Object getChaineDenormaliseAsMapOrList(String champ)     {
                                
                        Object retourObjet = null;
                        
                        String valeurChamp = renvoyerValeurCorrecte(champ);
                        
                        if ((valeurChamp!=null)&&(!valeurChamp.trim().equals("")))      {
                                String[] valeurs = valeurChamp.split(SEPARATEUR_VALEURS);
                        
                                if (valeurs.length > 0) {
                                        if (valeurs[0].contains(SEPARATEUR_TYPE_VALEUR))        {
                                                // Les champs sont typés, on en fait une Map
                                                HashMap<String,String> mapValeurs = new HashMap<String,String>();
                                                for (int i = 0; i < valeurs.length; i++)        {
                                                        String typeEtValeur[] = valeurs[i].split(SEPARATEUR_TYPE_VALEUR);
                                                        mapValeurs.put(typeEtValeur[1], typeEtValeur[0]);               
                                                }
                                                retourObjet = mapValeurs;
                                        }
                                        else    {
                                                
                                                //Les champs ne sont pas typés, on en fait une Liste
                                                LinkedList<String> listeValeurs = new LinkedList<String>();
                                                for (int i = 0; i < valeurs.length; i++)        {
                                                        if ((valeurs[i]!=null)&&(!valeurs[i].equals("")))       {
                                                                listeValeurs.add(valeurs[i]);
                                                        }
                                                }
                                                retourObjet = listeValeurs;
                                        }
                                        
                                }
                        }
                        
                        return retourObjet;
                        
        }
        
        /**
         * Permet de modifier correctement une chaine dénormalisée (champ de type "truk").
         * Remplace par la valeur de la première instance du type indiqué dans la chaine dénormalisée.
         * Si aucun type n'est trouvé, nous en ajoutons un avec la nouvelle valeur.
         * 
         * @param champ le nom du champ dénormalisé
         * @param type le type de la valeur à modifier
         * @param valeur la valeur pour le type en question
         */
        protected void modifierChaineDenormaliseParType(String champ, String type, Object valeur) {
                if (valeur == null || valeur.equals("")) {
                        supprimerTypeDansChaineDenormalise(champ, type);
                } else if (valeur instanceof String) {
                        String chaineExistante = renvoyerValeurCorrecte(champ);
                        
                        if (UtilString.isEmpty(chaineExistante)) {
                                this.set(champ, type+SEPARATEUR_TYPE_VALEUR+valeur);
                        } else {
                                String[] valeurs = chaineExistante.split(SEPARATEUR_VALEURS);
                                HashMap<String,String> valeursModifiees = new HashMap<String,String>();
                                for (int i = 0; i < valeurs.length; i++) {
                                        if (valeurs[i].startsWith(type+SEPARATEUR_TYPE_VALEUR)) {
                                                valeursModifiees.put(type, type+SEPARATEUR_TYPE_VALEUR+valeur);
                                        } else if (i == (valeurs.length -1) && !valeurs[i].startsWith(type+SEPARATEUR_TYPE_VALEUR)) {
                                                valeursModifiees.put(valeurs[i].split(SEPARATEUR_TYPE_VALEUR)[0], valeurs[i]);
                                                valeursModifiees.put(type, type+SEPARATEUR_TYPE_VALEUR+valeur);
                                        } else {
                                                valeursModifiees.put(valeurs[i].split(SEPARATEUR_TYPE_VALEUR)[0], valeurs[i]);
                                        }
                                }
                                String[] tableauValeursModifiees = valeursModifiees.values().toArray(new String[valeursModifiees.size()]);
                                this.set(champ, UtilArray.implode(tableauValeursModifiees, SEPARATEUR_VALEURS));
                        }
                }
        }
        
        protected String getInfoDenormaliseParPosition(String chaineExistante, int position) {
                String sortie = "";
                if (!UtilString.isEmpty(chaineExistante)) {
                        String[] valeurs = chaineExistante.split(SEPARATEUR_VALEURS);
                        if (valeurs.length >= position) {
                                for (int i = 0; i < valeurs.length; i++) {
                                        if (i == (position - 1)) {
                                                if (valeurs[i].contains(SEPARATEUR_TYPE_VALEUR)) {
                                                        sortie = valeurs[i].replaceFirst("^[^#]+"+SEPARATEUR_VALEURS, "");
                                                } else {
                                                        sortie = valeurs[i];
                                                }
                                                break;
                                        }
                                }
                        }
                }
                return sortie;
        }
        
        /**
         * Permet de modifier correctement une chaine dénormalisée (champ de type "truk").
         * Remplace par la valeur l'instance dont la position a été indiquée.
         * Si la chaine dénormalisée est vide, l'élement est ajouté quelque soit la position indiquée.
         * Si la position est supérieure au nombre d'élément de la chaine dénormalisé, rien n'est modifié.
         * 
         * @param champ le nom du champ dénormalisé
         * @param position le type de la valeur à modifier
         * @param valeur la valeur à remplacer à la position indiquée
         */
        protected void modifierChaineDenormaliseParPosition(String champ, int position, Object valeur) {
                if (valeur == null || valeur.equals("")) {
                        supprimerChaineDenormaliseParPosition(champ, position);
                } else if (valeur instanceof String) {
                        String chaineExistante = renvoyerValeurCorrecte(champ);
                        if (UtilString.isEmpty(chaineExistante)) {
                                this.set(champ, valeur);
                        } else {
                                String[] valeurs = chaineExistante.split(SEPARATEUR_VALEURS);
                                if (valeurs.length >= position) {
                                        for (int i = 0; i < valeurs.length; i++) {
                                                if (i == (position - 1)) {
                                                        valeurs[i] = (String) valeur;
                                                        break;
                                                }
                                        }
                                        this.set(champ, UtilArray.implode(valeurs, SEPARATEUR_VALEURS));
                                }
                        }
                }
        }
        
        protected void supprimerChaineDenormaliseParPosition(String champ, int position) {
                String chaineExistante = renvoyerValeurCorrecte(champ);
                if (!UtilString.isEmpty(chaineExistante)) {
                        String[] valeurs = chaineExistante.split(SEPARATEUR_VALEURS);
                        HashMap<String,String> valeursModifiees = new HashMap<String,String>();
                        if (valeurs.length >= position) {
                                for (int i = 0; i < valeurs.length; i++) {
                                        if (i != (position - 1)) {
                                                valeursModifiees.put(""+i, valeurs[i]);
                                        }
                                }
                                String[] tableauValeursModifiees = valeursModifiees.values().toArray(new String[valeursModifiees.size()]);
                                this.set(champ, UtilArray.implode(tableauValeursModifiees, SEPARATEUR_VALEURS));
                        }
                }
        }
        
        /** (non-Javadoc)
         * @see java.lang.Object#toString()
         */
        public String toString() {
                String sortie = "";
                
                // Champs du BaseModelData
                Set<String> proprietes = this.getProperties().keySet();
                TreeSet<String> proprietesTriees = new TreeSet<String>(proprietes);
                for (Iterator<String> it = proprietesTriees.iterator(); it.hasNext();) {
                        String cle = it.next();
                        if (this.get(cle) != null && !this.get(cle).equals("")) {
                                sortie += cle+" : "+this.get(cle).toString()+"\n";
                        }
                }
                
                return sortie;
        }
        
        public Boolean comparer(BaseModelData objetAComparer) {
                Boolean retour = true;
                Map<String, Object> a = this.getProperties();
                Map<String, Object> b = objetAComparer.getProperties();
                if (a.size() != b.size()) {
                        retour = false;
                } else {
                        Set<String> cles = a.keySet();
                        Iterator<String> it = cles.iterator();
                        while (it.hasNext()) {
                                String cle = it.next();
                                if (a.get(cle) != null && !a.get(cle).equals(b.get(cle))) {
                                        retour = false;
                                        break;
                                }
                        }
                }
                return retour;
        }
        
        public Object cloner(BaseModelData nouvelleInstance) {
                Map<String, Object> proprietes = this.getProperties();
                Set<String> cles = proprietes.keySet();
                for (Iterator<String> it = cles.iterator(); it.hasNext();) {
                        String cle = it.next();
                        nouvelleInstance.set(cle, this.get(cle));
                }
                
                return nouvelleInstance;
        }
        
        /**
         * Renvoie une chaîne de caractère formatée et encodée pour POST avec toutes les propriétés du modèle
         * */
        public String obtenirChainePOST() {
                String post = "";
                
                FastMap<?> proprietees = (FastMap<?>) getProperties();
                Collection<String> cles = proprietees.keySet();
                Iterator<String> it = cles.iterator();
                
                while (it.hasNext())    {
                        String cle = it.next();
                        //Les Radio Box couplées à la fonction autobind créent des variables gxt.RadioGroup.X, qu'il ne faut pas mettre dans la requête
                        if (!cle.startsWith("gxt.")&&!cle.matches("^_.+_$"))    {
                                
                                //Si, et seulement si, la valeur diffère de la valeur initiale OU la clé est dans les champs obligatoire
                                if (Arrays.asList(getChampsObligatoires()).contains(getPrefixe() + "_" + cle) || ((valeursInitiales.get(cle) != null && !valeursInitiales.get(cle).equals(get(cle))) || valeursInitiales.get(cle) == null))     {
                                        post += getPrefixe() + "_" +  cle + "=" + URL.encodeQueryString(renvoyerValeurCorrecte(cle));
                                        if (it.hasNext())       {
                                                post += "&";
                                        }
                                }
                        }
                }
                
                return post;
        }
        
        /**
         * Met à jour l'objet this avec les données de l'objet passé en paramêtre.
         */
        public void mettreAJour(aDonnee nouveau) {
                Collection<String> cles = nouveau.getProperties().keySet();
                Iterator<String> it = cles.iterator();
                while (it.hasNext())    {
                        String cle = it.next();
                        if (!this.get(cle).equals(nouveau.get(cle))) {
                                this.set(cle, nouveau.get(cle));
                        }
                }
        }
}