All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jaxx.runtime.validator.field.CollectionUniqueKeyValidator Maven / Gradle / Ivy

/*
 * *##% 
 * JAXX Runtime
 * Copyright (C) 2008 - 2009 CodeLutin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * ##%*
 */
package jaxx.runtime.validator.field;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldExpressionValidator;
import org.apache.commons.lang.builder.HashCodeBuilder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Un validateur basé sur {@link FieldExpressionValidator} qui valide une clef
 * unique sur une collection.
 * 

* Le {@link #fieldName} sert à récupérer la propriété de type de collection du * bean. * * @author chemit */ public class CollectionUniqueKeyValidator extends FieldExpressionValidator { /** * 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; /** * Une propriété optionnelle pour valider que l'objet reflétée par cette * propriété ne viole pas l'intégrité de la clef unique. * Cela permet de valider l'unicité sans que l'objet soit dans la collection */ protected String againstProperty; /** * Lors de l'utilisation de la againstProperty et qu'un ne peut pas utiliser * le equals sur l'objet, on peut spécifier une expression pour exclure des * tests lors de la recherche de la violation de clef unique. */ protected String againstIndexExpression; public String getCollectionFieldName() { return collectionFieldName; } public void setCollectionFieldName(String collectionFieldName) { this.collectionFieldName = collectionFieldName; } public String[] getKeys() { return keys; } public void setKeys(String[] keys) { if (keys != null && keys.length == 1 && keys[0].indexOf(',') != -1) { this.keys = keys[0].split(","); } else { this.keys = keys; } } public String getAgainstProperty() { return againstProperty; } public void setAgainstProperty(String againstProperty) { this.againstProperty = againstProperty; } public String getAgainstIndexExpression() { return againstIndexExpression; } public void setAgainstIndexExpression(String againstIndexExpression) { this.againstIndexExpression = againstIndexExpression; } @Override public void validate(Object object) throws ValidationException { if (keys == null || keys.length == 0) { throw new ValidationException("no unique keys defined"); } String fieldName = getFieldName(); Collection col = getCollection(object); if (log.isDebugEnabled()) { log.debug("collection found : " + col); } Object againstBean = againstProperty == null ? null : getFieldValue(againstProperty, object); if (log.isDebugEnabled()) { log.debug("againtBean = " + againstBean); } Integer againstIndex = (Integer) (againstIndexExpression == null ? -1 : getFieldValue(againstIndexExpression, object)); if (againstIndex == null) { againstIndex = -1; } if (againstBean == null && col.size() < 2) { // la liste ne contient pas deux entrées donc c'est valide return; } boolean answer = true; Integer againstHashCode = againstBean == null ? null : getUniqueKeyHashCode(againstBean); if (log.isDebugEnabled()) { log.debug("hash for new key " + againstHashCode); } List hashCodes = new ArrayList(); int index = 0; for (Object o : col) { Integer hash = getUniqueKeyHashCode(o); if (log.isDebugEnabled()) { log.debug("hash for object " + o + " = " + hash); } if (againstBean == null) { if (hashCodes.contains(hash)) { // on a deja rencontre cette clef unique, // donc la validation a echouee answer = false; if (log.isDebugEnabled()) { log.debug("Found same hashcode, not unique!"); } break; } } else { // utilisation de againstBean if (againstIndex != -1) { if (index != againstIndex && hash.equals(againstHashCode)) { // on a deja rencontre cette clef unique, // donc la validation a echouee answer = false; break; } } else { if (!againstBean.equals(o) && hash.equals(againstHashCode)) { // on a deja rencontre cette clef unique, // donc la validation a echouee answer = false; break; } } } // nouveau hashcode enregistre hashCodes.add(hash); // index suivant index++; } if (!answer) { addFieldError(fieldName, object); } } /** * Calcule pour une entrée donné, le hash de la clef unique * * @param o l'entree de la collection dont on va calculer le hash de * la clef unique * @return le hashCode calclé de la clef unique sur l'entrée donné * @throws ValidationException if any pb to retreave properties values */ protected Integer getUniqueKeyHashCode(Object o) throws ValidationException { // calcul du hash à la volée HashCodeBuilder builder = new HashCodeBuilder(); for (String key : this.keys) { Object property = getFieldValue(key, o); builder.append(property); } return builder.toHashCode(); } /** * @param object the incoming object containing the collection to test * @return the collection of the incoming object given by the fieldName * property * @throws ValidationException if any pb to retreave the collection */ protected Collection getCollection(Object object) throws ValidationException { String fieldName = getCollectionFieldName(); if (fieldName == null || fieldName.trim().isEmpty()) { // on travaille directement sur le fieldName fieldName = getFieldName(); } Object obj = null; // obtain the collection to test try { obj = getFieldValue(fieldName, object); } catch (ValidationException e) { throw e; } catch (Exception e) { // let this pass, but it will be logged right below } if (obj == null) { // la collection est nulle, donc on renvoie une collection vide return java.util.Collections.EMPTY_LIST; } if (!Collection.class.isInstance(obj)) { throw new ValidationException("field " + fieldName + " is not a collection type! (" + obj.getClass() + ')'); } return (Collection) obj; } @Override public String getValidatorType() { return "collectionUniqueKey"; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy