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 + * @returntrue 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('}');
+// }
+// }