This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository observe. See http://git.codelutin.com/observe.git commit e6189b3933d68026e02fa071cd23fbaf56ff464e Author: Tony CHEMIT <chemit@codelutin.com> Date: Sat Jun 13 15:16:08 2015 +0200 ajout d'un nouveau validateur pour tester l'unicité dans une collection (refs #7216) --- .../field/ObserveCollectionUniqueKeyValidator.java | 276 +++++++++++++++++++++ .../src/main/resources/validators.xml | 1 + 2 files changed, 277 insertions(+) diff --git a/observe-validation/src/main/java/fr/ird/observe/validation/field/ObserveCollectionUniqueKeyValidator.java b/observe-validation/src/main/java/fr/ird/observe/validation/field/ObserveCollectionUniqueKeyValidator.java new file mode 100644 index 0000000..041e85b --- /dev/null +++ b/observe-validation/src/main/java/fr/ird/observe/validation/field/ObserveCollectionUniqueKeyValidator.java @@ -0,0 +1,276 @@ +package fr.ird.observe.validation.field; + +/* + * #%L + * ObServe :: Validation + * %% + * Copyright (C) 2008 - 2015 IRD, Codelutin, Tony Chemit + * %% + * 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 com.google.common.base.Objects; +import com.opensymphony.xwork2.validator.ValidationException; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.validator.xwork2.field.NuitonFieldValidatorSupport; + +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.Set; +import java.util.TreeSet; + +/** + * Created on 1/23/15. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 4.0.1 + */ +public class ObserveCollectionUniqueKeyValidator extends NuitonFieldValidatorSupport { + + /** + * pour indiquer la propriété qui contient la liste à valider. + * + * Si cette prorpiété n'est pas renseignée alors on utilise la + * {@link #getFieldName()} pour obtenir la collection. + * + * Cela permet d'effectuer une validation si une collection mais portant + * en fait sur un autre champs + * + * @since 1.5 + */ + protected String collectionFieldName; + + /** + * la liste des propriétés d'une entrée de la collection qui définit la + * clef unique. + */ + protected String[] keys; + + public String getCollectionFieldName() { + return collectionFieldName; + } + + public String[] getKeys() { + return keys; + } + + public void setCollectionFieldName(String collectionFieldName) { + this.collectionFieldName = collectionFieldName; + } + + /** + * Can't use a varagrs, otherwise ognl won't set this one + * + * @param keys keys of the unique key comma separated + */ + @SuppressWarnings("MethodCanBeVariableArityMethod") + public void setKeys(String[] keys) { + if (keys != null && keys.length == 1 && keys[0].contains(",")) { + this.keys = keys[0].split(","); + } else { + this.keys = keys; + } + } + + @Override + public void validateWhenNotSkip(Object object) throws ValidationException { + + if (collectionFieldName == null) { + throw new ValidationException("collectionFieldName not defined"); + } + + if (keys == null || keys.length == 0) { + throw new ValidationException("keys not defined"); + } + + Collection<?> col = getCollection(object); + if (log.isDebugEnabled()) { + log.debug("collection found : " + col); + } + + if (log.isDebugEnabled()) { + log.debug("againtBean = " + object); + } + + boolean answer = true; + + @SuppressWarnings("unchecked") + Set<Object> hashCodes = new TreeSet<Object>((Comparator<? super Object>) getComparator()); + + hashCodes.add(object); + + String topiaIdToExclude = ((TopiaEntity) object).getTopiaId(); + int index = -1; + for (Object o : col) { + + index++; + + String topiaId = ((TopiaEntity) o).getTopiaId(); + if (Objects.equal(topiaIdToExclude, topiaId)) { + + // Do not treate against object + continue; + + } + + boolean wasAdded = hashCodes.add(o); + if (!wasAdded) { + answer = false; + if (log.isDebugEnabled()) { + log.debug("duplicated unique entry at " + index); + } + break; + } + + } + + if (!answer) { + + String fieldName = getFieldName(); + addFieldError(fieldName, object); + + } + + } + + @Override + public String getValidatorType() { + return "observeCollectionUniqueKey"; + } + + Comparator<?> comparator; + + private Comparator<?> getComparator() { + if (comparator == null) { + comparator = new MyComparator<Object>(keys); + } + return comparator; + } + + @SuppressWarnings("ComparatorNotSerializable") + private class MyComparator<O> implements Comparator<O> { + + private final String[] comparatorKeys; + + public MyComparator(String... comparatorKeys) { + + this.comparatorKeys = comparatorKeys; + } + + @Override + public int compare(O o1, O o2) { + + boolean equals = true; + + for (String key : comparatorKeys) { + + Object property1 = getPropertyValue(key, o1); + Object property2 = getPropertyValue(key, o2); + + equals = equals(property1, property2); + + if (!equals) { + break; + } + } + + return equals ? 0 : -1; + } + + protected boolean equals(Object o1, Object o2) { + + if (o1 instanceof Date) { + o1 = ((Date)o1).getTime(); + } + if (o2 instanceof Date) { + o2 = ((Date)o2).getTime(); + } + + boolean equals = Objects.equal(o1, o2); + return equals; + + } + + } + + protected Object getPropertyValue(String key, Object o) { + + Object result; + + try { + + result = getFieldValue(key, o); + + } catch (ValidationException e) { + + if (log.isErrorEnabled()) { + log.error("Can't get property '" + key + "'value on oject: " + o, e); + } + result = null; + + } + + return result; + + } + + /** + * @param object the incoming object containing the collection to test + * @return the collection of the incoming object given by the collectionFieldName + * property + * @throws ValidationException if any pb to retreave the collection + */ + protected Collection<?> getCollection(Object object) throws ValidationException { + + String fieldName = getCollectionFieldName(); + + Object obj; + + try { + + obj = getFieldValue(fieldName, object); + + } catch (ValidationException e) { + + throw e; + + } catch (Exception e) { + + if (log.isErrorEnabled()) { + log.error("Can't get collection '" + fieldName + "'value on oject: " + object, e); + } + obj = null; + + } + + if (obj == null) { + + // la collection est nulle, donc on renvoie une collection vide + obj = Collections.emptyList(); + + } else if (!Collection.class.isInstance(obj)) { + + throw new ValidationException("field " + fieldName + " is not a collection type! (" + obj.getClass() + ')'); + + } + + return (Collection<?>) obj; + + } + +} diff --git a/observe-validation/src/main/resources/validators.xml b/observe-validation/src/main/resources/validators.xml index 67fe689..1d9252b 100644 --- a/observe-validation/src/main/resources/validators.xml +++ b/observe-validation/src/main/resources/validators.xml @@ -66,5 +66,6 @@ <validator name="collectionFieldExpression2" class="fr.ird.observe.validation.field.CollectionFieldExpressionValidator2"/> <validator name="collectionFieldExpression" class="fr.ird.observe.validation.field.CollectionFieldExpressionValidator2"/> <validator name="collectionUniqueKey" class="fr.ird.observe.validation.field.CollectionUniqueKeyValidator2"/> + <validator name="observeCollectionUniqueKey" class="fr.ird.observe.validation.field.ObserveCollectionUniqueKeyValidator"/> </validators> -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.