Index: lutinutil/src/java/org/codelutin/util/CardinalityHelper.java diff -u /dev/null lutinutil/src/java/org/codelutin/util/CardinalityHelper.java:1.1 --- /dev/null Mon Dec 17 23:27:38 2007 +++ lutinutil/src/java/org/codelutin/util/CardinalityHelper.java Mon Dec 17 23:27:30 2007 @@ -0,0 +1,351 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* +* 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 2 +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* ##% */ +package org.codelutin.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Une classe avec des méthodes utiles sur les cardinalités : + *

+ * parser une cardinalité {@link #parseCardinalite(String, boolean)} + *

+ * afficher une cardinité {@link #printCardinalite(StringBuilder, String, int, int, boolean, String, String, String, String)} + *

+ * et pour tester des cardinalités : + *

+ * {@link #isMandatory(int)}, savoir si une cardinalité est obligatoire à + * partir de son min. + *

+ * {@link #isRepetable(int)}, savoir si une cardinalité est répétable à partir + * de son max. + *

+ * {@link #isMaxBounded(int)}, savoir si une cardinalité est bornée sur son max + * à partir de son max. + *

+ * {@link #isDefaultMandatory(int, int)}, savoir si la cardinalité est la + * cardinalité obligatoire par défaut {1}. + *

+ * {@link #isDefaultOptional(int, int)}, savoir si la cardinalité est la + * cardinalité optionel par défaut {0,1}. + *

+ * {@link #isAvailable(int, int)}, savoir si il reste encore des occurrences + * disponibles sur une cardianlité à partir d'un nombre d'oocurrence et du max + * de la cardinalité. + * + * @author tony + */ +public class CardinalityHelper { + + static final Pattern PATTERN_OPTIONAL = Pattern.compile("\\[.*\\]"); + static final Pattern PATTERN_MANDATORY = Pattern.compile("\\<.*\\>"); + + /** XXX + ou XXX * */ + public static final Pattern PATTERN_NO_MAX_BOUND = Pattern.compile("(.*)(\\+|\\*)"); + + /** XXX {n} n est un entier */ + public static final Pattern PATTERN_EXTACLY = Pattern.compile("(.*)\\{([0-9]+)\\}"); + + /** XXX {n,m} n est un entier, m est un entier ou * */ + public static final Pattern PATTERN_BOUNDED = Pattern.compile("(.*)\\{([0-9]+),([0-9]+|\\*)\\}"); + + /** + * Indique si une cardinalité est la cardinalité obligatoire par défaut {1} + * + * @param min le min de la cardinalité à tester + * @param max le max de la cardinalité à tester + * @return true si min==1 et max=1 + */ + public static boolean isDefaultMandatory(int min, int max) { + return min == 1 && max == 1; + } + + /** + * Indique si une cardinalité est la cardinalité optionel par défaut {0,1} + * + * @param min le min de la cardinalité à tester + * @param max le max de la cardinalité à tester + * @return true si min==0 && max==1 + */ + public static boolean isDefaultOptional(int min, int max) { + return min == 0 && max == 1; + } + + /** + * Indique si une cardinalité est obligatoire à partir de son min + * + * @param min le min de la cardinalité à tester + * @return true if min>0 + */ + public static boolean isMandatory(int min) { + return min > 0; + } + + /** + * Indique si une cardinalité est majorée à partir de son max + * + * @param max le max de la cardinalité à tester + * @return true si max!=-1 + */ + public static boolean isMaxBounded(int max) { + return max != -1; + } + + /** + * Indique si une cardinalité est répétable à partir de son max + * + * @param max le max de la cardinalité à tester + * @return true si max>0 || max==-1 + */ + public static boolean isRepetable(int max) { + return !isMaxBounded(max) || max > 0; + } + + /** + * Indique si on n'a pas encore atteint la borne max d'une cardinalité à + * partir de son max et d'un nombre d'occurrences déjà atteint. + * + * @param current le nombre d'occurence actuel + * @param max la borne max de la cardinalité + * @return true si la cardinalité n'a pas atteint sa borne max + */ + + public static boolean isAvailable(int current, int max) { + return !isMaxBounded(max) || current < max; + } + + /** + * Retourne le min par défault d'une cardinalité à partir du critère + * obligatoire ou non. + * + * @param mandatory le critère à tester + * @return 1 si obligatoire, 0 sinon. + */ + public static int getDefaultMin(boolean mandatory) { + return mandatory ? 1 : 0; + } + + /** + * Parse la cardinalite à la fin d'un texte. + * + * @param txt la valeur dont on cherche la cardinalité + * @param mandatory si vrai, valeurs par default {1}, sinon {0,1} + * @return un tableau contenant 3 object : le texte donné sans les + * informations de cardinalité, la répétitionMin, la répétitionMax. + */ + public static Object[] parseCardinalite(String txt, boolean mandatory) { + + Object[] result = new Object[3]; + Matcher matcher; + + // always trim the text + txt = txt.trim(); + if ((matcher = PATTERN_NO_MAX_BOUND.matcher(txt)).matches()) { + // find a no max cardinalite *|+ + result[0] = matcher.group(1).trim(); + result[1] = getDefaultMin(matcher.group(2).equals("+")); + result[2] = -1; + } else if ((matcher = PATTERN_EXTACLY.matcher(txt)).matches()) { + // found a exactly cardinalite {n} + result[0] = matcher.group(1).trim(); + result[1] = Integer.valueOf(matcher.group(2)); + result[2] = result[1]; + } else if ((matcher = PATTERN_BOUNDED.matcher(txt)).matches()) { + // found a bounded cardinalite {n,m} + result[0] = matcher.group(1).trim(); + result[1] = Integer.valueOf(matcher.group(2)); + String max = matcher.group(3); + result[2] = max.equals("*") ? -1 : Integer.valueOf(max); + } else { + // no cardinalite was found, use default values + result[0] = txt.trim(); + result[1] = getDefaultMin(mandatory); + result[2] = 1; + } + return result; + } + + /** + * Imprime dans le builder, le txt + une cardinalité. + * + * @param sb le builder + * @param txt le txt à imprimer + * @param min la caridnalité min + * @param max la cardinalité max + * @param mandatory pour indiquer dans quel cas on affiche la cardinalité : + * si elle correspond aux valeurs par défaut + * de mandatory {1} ou optionel {0,1}, pas d'impression. + * @param mo le caractère ouvrant pour un object obligatoire + * @param mc le caractère fermant pour un object obligatoire + * @param oo le caractère ouvrant pour un object optionel + * @param oc le caractère fermant pour un object optionel + */ + public static void printCardinalite(StringBuilder sb, String txt, int min, int max, boolean mandatory, String mo, String mc, String oo, String oc) { + // flag pour indiquer s'il faut ou non imprimer les bordures + boolean print = false; + + boolean maxBounded = isMaxBounded(max); + if (isMandatory(min)) { + sb.append(mo).append(txt).append(mc); + if (isDefaultMandatory(min, max)) { + if (mandatory || mo.length() > 0) { + // rien a faire on a la valeur par defaut attendue, ou la + // bordure existe et remplace la valeur par defaut + } else { + // pas de bordure, ou valeur optionel attendue, on doit imprimer la cardinalite + print = true; + } + } else { + if (!maxBounded && min == 1) { + sb.append('+'); + } else { + print = true; + } + } + } else { + sb.append(oo).append(txt).append(oc); + if (isDefaultOptional(min, max)) { + if (!mandatory || oo.length() > 0) { + // rien a faire on a la valeur par defaut attendue, ou la + // bordure existe et remplace la valeur par defaut + } else { + // pas de bordure, ou valeur optionel attendue, on doit imprimer la cardinalite + print = true; + } + } else { + if (!maxBounded) { + sb.append('*'); + } else { + print = true; + } + } + } + if (print) { + sb.append('{'); + sb.append(min); + if (max != min) { + sb.append(','); + sb.append(maxBounded ? max : "*"); + } + sb.append('}'); + } + } + + protected CardinalityHelper() { + // do not instanciate + } + + +} + +// /** +// * Parse la cardinalite à la fin d'un texte. +// * +// * TODO A améliorer. +// * +// * @param key la valeur dont on cherche la cardinalité +// * @param mandatory flag to say if this is a mandatory element or not. +// * @return un tableau contenant 3 object : le texte donné sans les +// * informations de cardinalité, la répétitionMin, la répétitionMax. +// */ +// public static Object[] parseCardinalite(String key, boolean mandatory) { +// Object[] result = new Object[3]; +// int repetitionMin; +// int repetitionMax; +// String cleanKey; +// +// if (key.endsWith("+")) { +// // cardinalité + = {1,-1} +// repetitionMin = 1; +// repetitionMax = -1; +// cleanKey = key.substring(0, key.length() - 1); +// } else { +// if (key.endsWith("*")) { +// // cardinalité * = {0,-1} +// repetitionMin = 0; +// repetitionMax = -1; +// cleanKey = key.substring(0, key.length() - 1); +// } else { +// if (key.endsWith("}")) { +// // cardinalité spécifiée +// int index = key.indexOf("{"); +// cleanKey = key.substring(0, index); +// String tmp = key.substring(index + 1, key.length() - 1); +// int comaIndex = tmp.indexOf(','); +// if (comaIndex == -1) { +// // cardinalité unique +// repetitionMax = repetitionMin = Integer.valueOf(tmp); +// } else { +// repetitionMin = Integer.valueOf(tmp.substring(0, comaIndex)); +// repetitionMax = Integer.valueOf(tmp.substring(comaIndex + 1)); +// } +// } else { +// // pas de cardinalité +// // rien à faire (on prend les valeurs par defaut) +// cleanKey = key; +// if (mandatory) { +// repetitionMin = 1; +// repetitionMax = 1; +// } else { +// repetitionMin = 0; +// repetitionMax = 1; +// } +// } +// } +// } +// result[0] = cleanKey.trim().toLowerCase(); +// result[1] = repetitionMin; +// result[2] = repetitionMax; +// return result; +// } + +//public static void printCardinalite(StringBuilder sb, String txt, int min, int max, boolean mandatory, String mo, String mc, String oo, String oc) { +// // flag pour indiquer s'il faut ou non imprimer les bordures +// boolean print = false; +// if (mandatory) { +// sb.append(mo).append(txt).append(mc); +// if (max == -1 && min == 1) { +// sb.append('+'); +// } else { +// if (max != 0 && min != 1) { +// print = true; +// } +// } +// } else { +// if (max == -1) { +// sb.append(oo).append(txt).append(oc); +// sb.append('*'); +// } else { +// if (max == 1 && min == 0) { +// sb.append(oo).append(txt).append(oc); +// } else { +// sb.append(mo).append(txt).append(mc); +// print = true; +// } +// } +// } +// if (print) { +// sb.append('{'); +// sb.append(min); +// if (max != min) { +// sb.append(','); +// sb.append(max == -1 ? '*' : max); +// } +// sb.append('}'); +// } +// }