branch feature/7493 created (now 259bb2e)
This is an automated email from the git hooks/post-receive script. New change to branch feature/7493 in repository observe. See http://git.codelutin.com/observe.git at 259bb2e ajout du test du service de validation (refs #7493) This branch includes the following new commits: new f2dd923 mise en place du service de validation (refs #7493) new 259bb2e ajout du test du service de validation (refs #7493) The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 259bb2e2b33541ffa4d729085cea5025c21efdae Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Aug 31 17:00:53 2015 +0200 ajout du test du service de validation (refs #7493) commit f2dd923bcf5963de874a51c31c5dc1c727ce4acc Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Aug 31 15:54:35 2015 +0200 mise en place du service de validation (refs #7493) -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/7493 in repository observe. See http://git.codelutin.com/observe.git commit f2dd923bcf5963de874a51c31c5dc1c727ce4acc Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Aug 31 15:54:35 2015 +0200 mise en place du service de validation (refs #7493) --- .../actions/validation/ValidationMessage.java | 39 ++ .../actions/validation/ValidationRequest.java | 86 ++++ .../actions/validation/ValidationResultForDto.java | 32 ++ .../validation/ValidationResultForDtoType.java | 31 ++ .../actions/validation/ValidationService.java | 12 + .../dto/constants/operation/ValidationContext.java | 20 + .../dto/constants/operation/ValidationScope.java | 12 + observe-services-topia/pom.xml | 4 + .../validation/ValidationMessageDetector.java | 562 +++++++++++++++++++++ .../actions/validation/ValidationServiceTopia.java | 278 ++++++++++ .../service/actions/validation/ValidatorsMap.java | 121 +++++ 11 files changed, 1197 insertions(+) diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessage.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessage.java new file mode 100644 index 0000000..e131396 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessage.java @@ -0,0 +1,39 @@ +package fr.ird.observe.services.service.actions.validation; + +import fr.ird.observe.services.dto.constants.operation.ValidationScope; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationMessage { + + protected ValidationScope scope; + + protected String fieldName; + + protected String message; + + public ValidationScope getScope() { + return scope; + } + + public void setScope(ValidationScope scope) { + this.scope = scope; + } + + public String getFieldName() { + return fieldName; + } + + public void setFieldName(String fieldName) { + this.fieldName = fieldName; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java new file mode 100644 index 0000000..d40e60a --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java @@ -0,0 +1,86 @@ +package fr.ird.observe.services.service.actions.validation; + +import com.google.common.collect.ImmutableSet; +import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; +import fr.ird.observe.services.dto.ReferenceDto; +import fr.ird.observe.services.dto.constants.operation.ValidationContext; +import fr.ird.observe.services.dto.constants.operation.ValidationScope; +import fr.ird.observe.services.dto.referential.ReferentialDto; + +import java.util.EnumSet; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationRequest { + + protected ObserveDataSourceConfiguration dataSourceConfiguration; + + protected boolean validateReferential; + + protected boolean validateData; + + protected ValidationContext validationContext; + + protected EnumSet<ValidationScope> scopes; + + protected ImmutableSet<ReferenceDto> tripIds; + + protected ImmutableSet<Class<? extends ReferentialDto>> referentialTypes; + + public ObserveDataSourceConfiguration getDataSourceConfiguration() { + return dataSourceConfiguration; + } + + public void setDataSourceConfiguration(ObserveDataSourceConfiguration dataSourceConfiguration) { + this.dataSourceConfiguration = dataSourceConfiguration; + } + + public boolean isValidateReferential() { + return validateReferential; + } + + public void setValidateReferential(boolean validateReferential) { + this.validateReferential = validateReferential; + } + + public boolean isValidateData() { + return validateData; + } + + public void setValidateData(boolean validateData) { + this.validateData = validateData; + } + + public ValidationContext getValidationContext() { + return validationContext; + } + + public void setValidationContext(ValidationContext validationContext) { + this.validationContext = validationContext; + } + + public EnumSet<ValidationScope> getScopes() { + return scopes; + } + + public void setScopes(EnumSet<ValidationScope> scopes) { + this.scopes = scopes; + } + + public ImmutableSet<ReferenceDto> getTripIds() { + return tripIds; + } + + public void setTripIds(ImmutableSet<ReferenceDto> tripIds) { + this.tripIds = tripIds; + } + + public ImmutableSet<Class<? extends ReferentialDto>> getReferentialTypes() { + return referentialTypes; + } + + public void setReferentialTypes(ImmutableSet<Class<? extends ReferentialDto>> referentialTypes) { + this.referentialTypes = referentialTypes; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDto.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDto.java new file mode 100644 index 0000000..b7efa15 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDto.java @@ -0,0 +1,32 @@ +package fr.ird.observe.services.service.actions.validation; + +import fr.ird.observe.services.dto.IdDto; +import fr.ird.observe.services.dto.ReferenceDto; + +import java.util.List; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationResultForDto<D extends IdDto> { + + protected ReferenceDto<D> dto; + + protected List<ValidationMessage> messages; + + public ReferenceDto<D> getDto() { + return dto; + } + + public void setDto(ReferenceDto<D> dto) { + this.dto = dto; + } + + public List<ValidationMessage> getMessages() { + return messages; + } + + public void setMessages(List<ValidationMessage> messages) { + this.messages = messages; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDtoType.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDtoType.java new file mode 100644 index 0000000..cb52411 --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationResultForDtoType.java @@ -0,0 +1,31 @@ +package fr.ird.observe.services.service.actions.validation; + +import fr.ird.observe.services.dto.IdDto; + +import java.util.List; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationResultForDtoType<D extends IdDto> { + + protected Class<D> DtoType; + + protected List<ValidationResultForDto<D>> validationResultForDtos; + + public Class<D> getDtoType() { + return DtoType; + } + + public void setDtoType(Class<D> dtoType) { + DtoType = dtoType; + } + + public List<ValidationResultForDto<D>> getValidationResultForDtos() { + return validationResultForDtos; + } + + public void setValidationResultForDtos(List<ValidationResultForDto<D>> validationResultForDtos) { + this.validationResultForDtos = validationResultForDtos; + } +} diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java new file mode 100644 index 0000000..4a9d5df --- /dev/null +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java @@ -0,0 +1,12 @@ +package fr.ird.observe.services.service.actions.validation; + +import java.util.List; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public interface ValidationService { + + List<ValidationResultForDtoType> validate(ValidationRequest request); + +} diff --git a/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationContext.java b/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationContext.java new file mode 100644 index 0000000..a463de9 --- /dev/null +++ b/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationContext.java @@ -0,0 +1,20 @@ +package fr.ird.observe.services.dto.constants.operation; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public enum ValidationContext { + + N1_UPDATE("n1-update"), + N1_CREATE("n1-create"); + + protected String contextName; + + ValidationContext(String contextName) { + this.contextName = contextName; + } + + public String getContextName() { + return contextName; + } +} diff --git a/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationScope.java b/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationScope.java new file mode 100644 index 0000000..0eb631e --- /dev/null +++ b/observe-services-model/src/main/java/fr/ird/observe/services/dto/constants/operation/ValidationScope.java @@ -0,0 +1,12 @@ +package fr.ird.observe.services.dto.constants.operation; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public enum ValidationScope { + + INFO, + WARNING, + ERROR, + +} diff --git a/observe-services-topia/pom.xml b/observe-services-topia/pom.xml index 53eb6e1..822c29a 100644 --- a/observe-services-topia/pom.xml +++ b/observe-services-topia/pom.xml @@ -78,6 +78,10 @@ <groupId>org.nuiton.i18n</groupId> <artifactId>nuiton-i18n</artifactId> </dependency> + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>nuiton-validator</artifactId> + </dependency> <!-- persistence --> <!--dependency> diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessageDetector.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessageDetector.java new file mode 100644 index 0000000..3b9b37b --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationMessageDetector.java @@ -0,0 +1,562 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 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% + */ +package fr.ird.observe.services.service.actions.validation; + +import fr.ird.observe.ObserveEntityEnum; +import fr.ird.observe.entities.longline.TripLongline; +import fr.ird.observe.entities.referentiel.Program; +import fr.ird.observe.entities.seine.TripSeine; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.TopiaEntityVisitor; +import org.nuiton.topia.persistence.TopiaException; +import org.nuiton.topia.persistence.util.TopiaEntityRef; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorEvent; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorListener; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; + +/** + * Le detecteur de messages de validation. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 1.3 + */ +public class ValidationMessageDetector implements TopiaEntityVisitor, + SimpleBeanValidatorListener { + + /** Logger */ + private static final Log log = + LogFactory.getLog(ValidationMessageDetector.class); + + public static final String SEPARATOR = "/"; + + /** le path courant depuis le depart */ + protected Deque<TopiaEntity> path; + + /** le dictionnaire des paths d'entites detectees */ + protected SortedMap<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>> refs; + + protected StringBuilder accessorExpression; + + protected TopiaEntity root; + + protected TopiaEntityRef currentRef; + + protected Set<TopiaEntity> explored; + + /** le dictionnaire des validateurs utilisables */ + protected final ValidatorsMap validators; + + protected ValidationContext context; + + public ValidationContext getContext() { + return context; + } + + public void setContext(ValidationContext context) { + this.context = context; + } + + public ValidationMessageDetector(ValidatorsMap validators) { + this.validators = validators; + path = new LinkedList<TopiaEntity>(); + explored = new HashSet<TopiaEntity>(); + refs = new TreeMap<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>>(); + accessorExpression = new StringBuilder(); + for (SimpleBeanValidator<?> v : validators.values()) { + v.setBean(null); + } + } + + public void detectMessages(TopiaEntity... entities) { +// try { + // on reinitialise tous les validateurs +// for (BeanValidator<?> v : validators.values()) { +// v.setBean(null); +//// v.setContextName(contextName); +// } + for (TopiaEntity e : entities) { + if (log.isDebugEnabled()) { + log.debug("start for entity " + e.getTopiaId()); + } + // détection sur l'entité e + try { + e.accept(this); + } catch (TopiaException e1) { + throw new RuntimeException("could not vist entity " + e.getTopiaId(), e1); + } + } + } + + @Override + public void start(TopiaEntity e) { + if (root == null) { + // start come in start method since + // last clear method invocation + root = e; + addPath(e, "$root", -1); + } + explored.add(e); + SimpleBeanValidator<TopiaEntity> validator = getValidator(e); + if (log.isDebugEnabled()) { + log.debug("with entity " + e.getTopiaId() + " : " + accessorExpression); + } + if (validator != null) { + validator.addSimpleBeanValidatorListener(this); + addEntityInContext(e); + try { + currentRef = new TopiaEntityRef( + root, + e, + accessorExpression.toString(), + path.toArray(new TopiaEntity[path.size()])); + validator.setBean(e); + } finally { + validator.removeSimpleBeanValidatorListener(this); + validator.setBean(null); + } + } + } + + @Override + public void end(TopiaEntity e) { + if (root != null && root.equals(e)) { + // global visit is done + root = null; + removePath(); + } + removeEntityFromContext(e); + } + + private void addEntityInContext(TopiaEntity e) { + + DataContext context = getContext().getDataContext(); + + ObserveEntityEnum anEnum = ObserveEntityEnum.valueOf(e); + switch (anEnum) { + case Route: + context.setSelectedRouteId(e.getTopiaId()); + break; + case TripSeine: { + context.setSelectedTripId(e.getTopiaId()); + Program program = ((TripSeine) e).getProgram(); + if (program != null) { + context.setSelectedProgramId(program.getTopiaId()); + } else { + context.setSelectedProgramId(null); + } + } + break; + case ActivitySeine: + context.setSelectedActivityId(e.getTopiaId()); + break; + case SetSeine: + context.setSelectedSetId(e.getTopiaId()); + break; + case TripLongline: { + context.setSelectedTripId(e.getTopiaId()); + Program program = ((TripLongline) e).getProgram(); + if (program != null) { + context.setSelectedProgramId(program.getTopiaId()); + } else { + context.setSelectedProgramId(null); + } + } + break; + case ActivityLongline: + context.setSelectedActivityId(e.getTopiaId()); + break; + case SetLongline: + context.setSelectedSetId(e.getTopiaId()); + break; + case FloatingObject: + context.setSelectedFloatingObjectId(e.getTopiaId()); + break; + case NonTargetLength: + break; + case TargetLength: + break; + case TransmittingBuoy: + break; + case NonTargetCatch: + break; + case TargetCatch: + break; + case NonTargetSample: + break; + case TargetSample: + break; + case ObjectObservedSpecies: + break; + case SchoolEstimate: + break; + case ObjectSchoolEstimate: + break; + case VesselActivitySeine: + break; + case SurroundingActivity: + break; + case Vessel: + break; + case VesselSizeCategory: + break; + case WeightCategory: + break; + case ReasonForNullSet: + break; + case ReasonForNoFishing: + break; + case SpeciesFate: + break; + case ObjectFate: + break; + case Species: + break; + case SpeciesGroup: + break; + case DetectionMode: + break; + case Person: + break; + case Ocean: + break; + case TransmittingBuoyOperation: + break; + case ObjectOperation: + break; + case Organism: + break; + case LengthWeightParameter: + break; + case Country: + break; + case Program: + break; + case ReasonForDiscard: + break; + case SpeciesStatus: + break; + case ObservedSystem: + break; + case TransmittingBuoyType: + break; + case VesselType: + break; + case ObjectType: + break; + case Wind: + break; + } + } + + private void removeEntityFromContext(TopiaEntity e) { + + DataContext context = getContext().getDataContext(); + + ObserveEntityEnum anEnum = ObserveEntityEnum.valueOf(e); + switch (anEnum) { + case Route: + context.setSelectedRouteId(null); + break; + case TripSeine: + context.setSelectedTripId(null); + context.setSelectedProgramId(null); + break; + case ActivitySeine: + context.setSelectedActivityId(null); + break; + case SetSeine: + context.setSelectedSetId(null); + break; + case TripLongline: + context.setSelectedTripId(null); + context.setSelectedProgramId(null); + break; + case ActivityLongline: + context.setSelectedActivityId(null); + break; + case SetLongline: + context.setSelectedSetId(null); + break; + case FloatingObject: + context.setSelectedFloatingObjectId(null); + break; + case NonTargetLength: + break; + case TargetLength: + break; + case TransmittingBuoy: + break; + case NonTargetCatch: + break; + case TargetCatch: + break; + case NonTargetSample: + break; + case TargetSample: + break; + case ObjectObservedSpecies: + break; + case SchoolEstimate: + break; + case ObjectSchoolEstimate: + break; + case VesselActivitySeine: + break; + case SurroundingActivity: + break; + case Vessel: + break; + case VesselSizeCategory: + break; + case WeightCategory: + break; + case ReasonForNullSet: + break; + case ReasonForNoFishing: + break; + case SpeciesFate: + break; + case ObjectFate: + break; + case Species: + break; + case SpeciesGroup: + break; + case DetectionMode: + break; + case Person: + break; + case Ocean: + break; + case TransmittingBuoyOperation: + break; + case ObjectOperation: + break; + case Organism: + break; + case LengthWeightParameter: + break; + case Country: + break; + case Program: + break; + case ReasonForDiscard: + break; + case SpeciesStatus: + break; + case ObservedSystem: + break; + case TransmittingBuoyType: + break; + case VesselType: + break; + case ObjectType: + break; + case Wind: + break; + } + } + + @Override + public void visit(TopiaEntity e, + String name, + Class<?> type, + Object value) { + TopiaEntity e1 = getTopiaValue(value); + if (e1 != null) { + addPath(e1, name, -1); + try { + try { + e1.accept(this); + } catch (TopiaException ex) { + if (log.isErrorEnabled()) { + log.error(ex.getMessage(), ex); + } + } + } finally { + removePath(); + } + } + } + + @Override + public void visit(TopiaEntity e, + String name, + Class<?> collectionType, + Class<?> type, + int index, + Object value) { + TopiaEntity e1 = getTopiaValue(value); + if (e1 != null) { + addPath(e1, name, index); + try { + try { + e1.accept(this); + } catch (TopiaException ex) { + if (log.isErrorEnabled()) { + log.error(ex.getMessage(), ex); + } + } + } finally { + removePath(); + } + } + } + + @Override + public void visit(TopiaEntity e, + String name, + Class<?> collectionType, + Class<?> type, + Object value) { + Collection<?> cValue = (Collection<?>) value; + if (TopiaEntity.class.isAssignableFrom(type) && + cValue != null && !cValue.isEmpty()) { + int i = 0; + for (Object currentValue : cValue) { + visit(e, name, collectionType, type, i++, currentValue); + } + } + } + + public SortedMap<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>> getRefs() { + // on renvoie toujours une copie + // pour pouvoir au plus tôt nettoyer le detecteur + TreeMap<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>> result; + result = new TreeMap<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>>(refs); + return result; + } + + + + @Override + public void clear() { + path.clear(); + refs.clear(); + root = null; + explored.clear(); + accessorExpression.setLength(0); + } + + protected TopiaEntity getTopiaValue(Object value) { + TopiaEntity topiaEntity = (TopiaEntity) (value != null && + value instanceof TopiaEntity ? value : null); + if (topiaEntity != null && explored.contains(topiaEntity)) { + // entite deja visitee + topiaEntity = null; + } + return topiaEntity; + } + + protected <T extends TopiaEntity> SimpleBeanValidator<T> getValidator(T e) { + Class<T> contractClass; + contractClass = (Class<T>) ObserveEntityEnum.getContractClass(e.getClass()); + return validators.getValidator(contractClass); + } + + protected void addPath(TopiaEntity e, String name, int index) { + path.add(e); + if (accessorExpression.length() > 0) { + accessorExpression.append(SEPARATOR); + } + accessorExpression.append(name); + if (index > -1) { + accessorExpression.append("[@topiaId=\""); + accessorExpression.append(e.getTopiaId()); + accessorExpression.append("\"]"); + } + if (log.isTraceEnabled()) { + log.trace("add to stack : " + e.getTopiaId() + ", new size : " + + path.size() + ", path : " + accessorExpression); + } + } + + protected void removePath() { + TopiaEntity e = path.removeLast(); + if (path.isEmpty()) { + accessorExpression.setLength(0); + } else { + int index = accessorExpression.lastIndexOf(SEPARATOR); + if (index > -1) { + accessorExpression.delete(index, + accessorExpression.length()); + } + } + if (log.isTraceEnabled()) { + log.trace("remove from stack : " + e.getTopiaId() + + ", new size : " + path.size() + ", path : " + + accessorExpression); + } + } + + @Override + public void onFieldChanged(SimpleBeanValidatorEvent event) { + SimpleBeanValidator<?> validator = event.getSource(); + + // on ne traite que les messages a ajouter + String[] messagesToAdd = event.getMessagesToAdd(); + + if (messagesToAdd == null || messagesToAdd.length == 0) { + return; + } + + if (log.isDebugEnabled()) { + log.debug("will add " + Arrays.toString(messagesToAdd) + + " for " + currentRef.getAccessorExpression()); + } + List<SimpleBeanValidatorMessage<?>> list = refs.get(currentRef); + if (list == null) { + // first time for this entity + list = new ArrayList<SimpleBeanValidatorMessage<?>>(); + refs.put(currentRef, list); + } + for (String m : messagesToAdd) { + SimpleBeanValidatorMessage<?> message; + message = new SimpleBeanValidatorMessage( + validator, + event.getField(), + m, + event.getScope()); + if (log.isDebugEnabled()) { + log.debug("add message " + message); + } + list.add(message); + } + } + + + +} diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopia.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopia.java new file mode 100644 index 0000000..e6dc863 --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopia.java @@ -0,0 +1,278 @@ +package fr.ird.observe.services.service.actions.validation; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import fr.ird.observe.ObserveEntityEnum; +import fr.ird.observe.entities.Entities; +import fr.ird.observe.entities.Trip; +import fr.ird.observe.entities.longline.TripLongline; +import fr.ird.observe.entities.referentiel.Program; +import fr.ird.observe.entities.seine.TripSeine; +import fr.ird.observe.services.ObserveServiceTopia; +import fr.ird.observe.services.dto.IdDto; +import fr.ird.observe.services.dto.ReferenceDto; +import fr.ird.observe.services.dto.constants.operation.ValidationContext; +import fr.ird.observe.services.dto.constants.operation.ValidationScope; +import fr.ird.observe.services.dto.longline.TripLonglineDto; +import fr.ird.observe.services.dto.referential.ReferentialDto; +import fr.ird.observe.services.dto.seine.TripSeineDto; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.topia.persistence.TopiaEntity; +import org.nuiton.topia.persistence.util.TopiaEntityRef; +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; +import org.nuiton.validator.bean.simple.SimpleBeanValidatorMessage; + +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationServiceTopia extends ObserveServiceTopia implements ValidationService { + + private static final Log log = LogFactory.getLog(ValidationServiceTopia.class); + + @Override + public List<ValidationResultForDtoType> validate(ValidationRequest request) { + + ValidatorsMap validators = getValidators(request); + + ValidationMessageDetector detector = + new ValidationMessageDetector(validators); + + if (request.isValidateReferential()) { + + validateReferential(request, detector); + + } + + if (request.isValidateData()) { + + validateData(request, detector); + + } + + + List<ValidationResultForDtoType> validationResults = getValidationResults(detector); + + return validationResults; + } + + protected ValidatorsMap getValidators(ValidationRequest request) { + + Set<ObserveEntityEnum> beanTypes = Sets.newLinkedHashSet(); + + if (request.isValidateReferential()) { + beanTypes.addAll(Entities.REFERENCE_ENTITIES_LIST); + } + + if (request.isValidateData()) { + beanTypes.addAll(Entities.DATA_ENTITIES_LIST); + } + + ValidatorsMap validators = getValidators( + request.getValidationContext(), + request.getScopes(), + beanTypes); + + return validators; + + + } + + + protected void validateReferential(ValidationRequest request, ValidationMessageDetector detector) { + + for (Class<? extends ReferentialDto> referentialDtoType : request.getReferentialTypes()) { + + Class<TopiaEntity> referentialType = getEntityType(referentialDtoType); + + // on recupere la liste des ids a valider +// String entityLabel = t(DecoratorService.getEntityLabel(klass)); +// sendMessage(t("observe.message.validation.start.referentiel", entityLabel, ids.size())); + for (TopiaEntity entity : loadEntities(referentialType)) { + + detector.detectMessages(entity); + } + } + + + } + + protected void validateData(ValidationRequest request, ValidationMessageDetector detector) { + + for (ReferenceDto referenceDto : request.getTripIds()) { + + Trip trip = null; + + if (referenceDto.getType().isAssignableFrom(TripSeineDto.class)) { + + trip = loadEntity(TripSeineDto.class, TripSeine.class, referenceDto.getId()); + + } else if (referenceDto.getType().isAssignableFrom(TripLonglineDto.class)) { + + trip = loadEntity(TripLonglineDto.class, TripLongline.class, referenceDto.getId()); + + } + + if (trip != null) { + + Program program = trip.getProgram(); + + //messager.sendMessage(t("observe.message.validation.start.maree", decorateEntity(trip), decorateEntity(program))); + + detector.detectMessages(trip); + } + + + } + + + } + + /** + * Obtenir le validateur d'un type objet + * + * @param context le lastName du context de validation + * @param scopes les scopes autorisés + * @param klass type de l'objet à valider + * @param <B> type de l'objet à valider + * @return le validateur trouvé ou {@code null} + */ + public <B extends TopiaEntity> SimpleBeanValidator<B> getValidator( + ValidationContext context, + EnumSet<ValidationScope> scopes, + Class<B> klass) { + + Iterable<NuitonValidatorScope> nuitonScopes = Iterables.transform(scopes, new Function<ValidationScope, NuitonValidatorScope>() { + @Override + public NuitonValidatorScope apply(ValidationScope validationScope) { + return NuitonValidatorScope.valueOf(validationScope.name()); + } + }); + + + SimpleBeanValidator<B> valitator = SimpleBeanValidator.newValidator( + klass, + context.getContextName(), + Iterables.toArray(nuitonScopes, NuitonValidatorScope.class)); + + Set<NuitonValidatorScope> resultScopes = valitator.getEffectiveScopes(); + if (resultScopes.isEmpty()) { + valitator = null; + if (log.isDebugEnabled()) { + log.debug(klass + " : validator skip (no scopes detected)"); + } + } else { + if (log.isDebugEnabled()) { + log.debug(klass + " : keep validator " + valitator); + } + } + return valitator; + } + + /** + * Obtenir le dictionnaire des validateurs pour les types d'entités donnés. + * + * @param context le context de validation + * @param scopes les scopes autorisés + * @param beanTypes types des entités + * @return le dictionnaire des validateurs par type d'entité. + */ + public ValidatorsMap getValidators( + ValidationContext context, + EnumSet<ValidationScope> scopes, + Set<ObserveEntityEnum> beanTypes) { + + ValidatorsMap result = new ValidatorsMap(); + + for (ObserveEntityEnum type : beanTypes) { + // on cherche le validateur + SimpleBeanValidator validator = getValidator(context, scopes, type.getContract()); + if (validator != null) { + // on enregistre le validateur + result.put(type.getContract(), validator); + } + } + return result; + + + } + + public List<ValidationResultForDtoType> getValidationResults(ValidationMessageDetector detector) { + + Map<Class<? extends IdDto>, List<ValidationResultForDto>> validationResultsByDtoType = Maps.newHashMap(); + + for (Map.Entry<TopiaEntityRef, List<SimpleBeanValidatorMessage<?>>> entry : detector.getRefs().entrySet()) { + + TopiaEntity entity = entry.getKey().getRef(); + + Class<? extends TopiaEntity> entityClass = ObserveEntityEnum.getContractClass(entity.getClass()); + + Class<IdDto> dtoType = getDtoType(entityClass); + + List<ValidationResultForDto> messageForDtos = validationResultsByDtoType.get(dtoType); + + if (messageForDtos == null) { + + messageForDtos = Lists.newLinkedList(); + + validationResultsByDtoType.put(dtoType, messageForDtos); + + } + + ReferenceDto reference = entityToReferenceDto(dtoType, entity); + + ValidationResultForDto messageForDto = new ValidationResultForDto(); + + messageForDto.setDto(reference); + + List<ValidationMessage> messages = Lists.newLinkedList(); + + for (SimpleBeanValidatorMessage beanValidatorMessage : entry.getValue()) { + + ValidationMessage message = new ValidationMessage(); + + message.setScope(ValidationScope.valueOf(beanValidatorMessage.getScope().name())); + + message.setFieldName(beanValidatorMessage.getField()); + + message.setMessage(beanValidatorMessage.getMessage()); + + messages.add(message); + + } + + messageForDto.setMessages(messages); + + messageForDtos.add(messageForDto); + + } + + List<ValidationResultForDtoType> validationResults = Lists.newLinkedList(); + + for (Map.Entry<Class<? extends IdDto>, List<ValidationResultForDto>> entry : validationResultsByDtoType.entrySet()) { + + ValidationResultForDtoType messageForDtoType = new ValidationResultForDtoType(); + + messageForDtoType.setDtoType(entry.getKey()); + + messageForDtoType.setValidationResultForDtos(entry.getValue()); + + validationResults.add(messageForDtoType); + + } + + return validationResults; + + } + + +} diff --git a/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidatorsMap.java b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidatorsMap.java new file mode 100644 index 0000000..e6fb418 --- /dev/null +++ b/observe-services-topia/src/main/java/fr/ird/observe/services/service/actions/validation/ValidatorsMap.java @@ -0,0 +1,121 @@ +/* + * #%L + * ObServe :: Business + * %% + * Copyright (C) 2008 - 2010 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% + */ +package fr.ird.observe.services.service.actions.validation; + +import org.nuiton.validator.NuitonValidatorScope; +import org.nuiton.validator.bean.simple.SimpleBeanValidator; + +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Un dictionnaire de validateurs ordonnees par le type de leur bean. + * + * @author Tony Chemit - chemit@codelutin.com + * @since 2.1 + */ +public class ValidatorsMap implements Map<Class<?>, SimpleBeanValidator<?>> { + + protected final Map<Class<?>, SimpleBeanValidator<?>> delegate; + + public ValidatorsMap() { + delegate = new HashMap<Class<?>, SimpleBeanValidator<?>>(); + } + + public NuitonValidatorScope[] getScopes() { + EnumSet<NuitonValidatorScope> result = + EnumSet.noneOf(NuitonValidatorScope.class); + for (SimpleBeanValidator<?> b : values()) { + result.addAll(b.getScopes()); + } + return result.toArray(new NuitonValidatorScope[result.size()]); + } + + public <X> SimpleBeanValidator<X> getValidator(Class<X> klass) { + SimpleBeanValidator<X> beanValidator = (SimpleBeanValidator<X>) get(klass); + return beanValidator; + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + @Override + public SimpleBeanValidator<?> get(Object key) { + return delegate.get(key); + } + + @Override + public SimpleBeanValidator<?> put(Class<?> key, SimpleBeanValidator<?> value) { + return delegate.put(key, value); + } + + @Override + public SimpleBeanValidator<?> remove(Object key) { + return delegate.remove(key); + } + + @Override + public void putAll(Map<? extends Class<?>, ? extends SimpleBeanValidator<?>> m) { + delegate.putAll(m); + } + + @Override + public void clear() { + delegate.clear(); + } + + @Override + public Set<Class<?>> keySet() { + return delegate.keySet(); + } + + @Override + public Collection<SimpleBeanValidator<?>> values() { + return delegate.values(); + } + + @Override + public Set<Entry<Class<?>, SimpleBeanValidator<?>>> entrySet() { + return delegate.entrySet(); + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/7493 in repository observe. See http://git.codelutin.com/observe.git commit 259bb2e2b33541ffa4d729085cea5025c21efdae Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Mon Aug 31 17:00:53 2015 +0200 ajout du test du service de validation (refs #7493) --- .../actions/validation/ValidationRequest.java | 7 +- .../actions/validation/ValidationService.java | 4 +- .../validation/ValidationServiceTopiaTest.java | 107 +++++++++++++++++++++ 3 files changed, 113 insertions(+), 5 deletions(-) diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java index d40e60a..7699bcf 100644 --- a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationRequest.java @@ -2,7 +2,6 @@ package fr.ird.observe.services.service.actions.validation; import com.google.common.collect.ImmutableSet; import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; -import fr.ird.observe.services.dto.ReferenceDto; import fr.ird.observe.services.dto.constants.operation.ValidationContext; import fr.ird.observe.services.dto.constants.operation.ValidationScope; import fr.ird.observe.services.dto.referential.ReferentialDto; @@ -24,7 +23,7 @@ public class ValidationRequest { protected EnumSet<ValidationScope> scopes; - protected ImmutableSet<ReferenceDto> tripIds; + protected ImmutableSet<String> tripIds; protected ImmutableSet<Class<? extends ReferentialDto>> referentialTypes; @@ -68,11 +67,11 @@ public class ValidationRequest { this.scopes = scopes; } - public ImmutableSet<ReferenceDto> getTripIds() { + public ImmutableSet<String> getTripIds() { return tripIds; } - public void setTripIds(ImmutableSet<ReferenceDto> tripIds) { + public void setTripIds(ImmutableSet<String> tripIds) { this.tripIds = tripIds; } diff --git a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java index 4a9d5df..bd196a3 100644 --- a/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java +++ b/observe-services-api/src/main/java/fr/ird/observe/services/service/actions/validation/ValidationService.java @@ -1,11 +1,13 @@ package fr.ird.observe.services.service.actions.validation; +import fr.ird.observe.services.ObserveService; + import java.util.List; /** * @author Sylvain Bavencoff - bavencoff@codelutin.com */ -public interface ValidationService { +public interface ValidationService extends ObserveService { List<ValidationResultForDtoType> validate(ValidationRequest request); diff --git a/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopiaTest.java b/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopiaTest.java new file mode 100644 index 0000000..6d21d51 --- /dev/null +++ b/observe-services-topia/src/test/java/fr/ird/observe/services/service/actions/validation/ValidationServiceTopiaTest.java @@ -0,0 +1,107 @@ +package fr.ird.observe.services.service.actions.validation; + +import com.google.common.collect.ImmutableSet; +import fr.ird.observe.services.configuration.ObserveDataSourceConfiguration; +import fr.ird.observe.services.dto.constants.operation.ValidationContext; +import fr.ird.observe.services.dto.constants.operation.ValidationScope; +import fr.ird.observe.services.dto.referential.ReferentialDto; +import fr.ird.observe.services.dto.seine.ActivitySeineDto; +import fr.ird.observe.services.dto.seine.FloatingObjectDto; +import fr.ird.observe.services.dto.seine.RouteDto; +import fr.ird.observe.services.dto.seine.SetSeineDto; +import fr.ird.observe.services.dto.seine.TripSeineDto; +import fr.ird.observe.services.service.AbstractServiceTopiaTest; +import org.junit.Assert; +import org.junit.Test; + +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +/** + * @author Sylvain Bavencoff - bavencoff@codelutin.com + */ +public class ValidationServiceTopiaTest extends AbstractServiceTopiaTest { + + protected ValidationService service; + + @Override + public Set<String> getTestNamesChangeDataBase() { + return ImmutableSet.of("testConsolidateTripSeines"); + } + + @Override + public String getScriptName() { + return "dataForTestSeine"; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + service = newService(ValidationService.class); + } + + @Test + public void testConsolidateTripSeines() throws Exception { + + ValidationRequest request = new ValidationRequest(); + + ObserveDataSourceConfiguration dataSourceConfiguration = applicationContextResource.createDataSourceConfigurationH2(ValidationServiceTopiaTest.class, "localdb"); + + request.setDataSourceConfiguration(dataSourceConfiguration); + + request.setValidateData(true); + request.setValidateReferential(false); + request.setValidationContext(ValidationContext.N1_CREATE); + request.setScopes(EnumSet.allOf(ValidationScope.class)); + request.setTripIds(ImmutableSet.of(TRIP_SEINE_ID_1, TRIP_SEINE_ID_2)); + request.setReferentialTypes(ImmutableSet.<Class<? extends ReferentialDto>>of()); + + List<ValidationResultForDtoType> validationResults = service.validate(request); + + Assert.assertNotNull(validationResults); + Assert.assertEquals(5, validationResults.size()); + + Assert.assertEquals(ActivitySeineDto.class, validationResults.get(0).getDtoType()); + Assert.assertEquals(SetSeineDto.class, validationResults.get(1).getDtoType()); + Assert.assertEquals(TripSeineDto.class, validationResults.get(2).getDtoType()); + Assert.assertEquals(FloatingObjectDto.class, validationResults.get(3).getDtoType()); + Assert.assertEquals(RouteDto.class, validationResults.get(4).getDtoType()); + + ValidationResultForDtoType tripValidationResult = validationResults.get(2); + + List<ValidationResultForDto> validationResultForDtos = tripValidationResult.getValidationResultForDtos(); + Assert.assertNotNull(validationResultForDtos); + Assert.assertEquals(2, validationResultForDtos.size()); + Assert.assertEquals(TRIP_SEINE_ID_1, validationResultForDtos.get(0).getDto().getId()); + Assert.assertEquals(TRIP_SEINE_ID_2, validationResultForDtos.get(1).getDto().getId()); + + List<ValidationMessage> messages = validationResultForDtos.get(0).getMessages(); + + Assert.assertNotNull(messages); + Assert.assertEquals(5, messages.size()); + + Assert.assertEquals(ValidationScope.ERROR, messages.get(0).getScope()); + Assert.assertEquals("Port de départ", messages.get(0).getFieldName()); + Assert.assertEquals("La sélection d'un port de départ est obligatoire.", messages.get(0).getMessage()); + + Assert.assertEquals(ValidationScope.ERROR, messages.get(1).getScope()); + Assert.assertEquals("Bateau", messages.get(1).getFieldName()); + Assert.assertEquals("Le bateau sélectionné est désactivé.", messages.get(1).getMessage()); + + Assert.assertEquals(ValidationScope.WARNING, messages.get(2).getScope()); + Assert.assertEquals("Capitaine", messages.get(2).getFieldName()); + Assert.assertEquals("Pas de capitaine sélectionné.", messages.get(2).getMessage()); + + Assert.assertEquals(ValidationScope.WARNING, messages.get(3).getScope()); + Assert.assertEquals("Saisisseur", messages.get(3).getFieldName()); + Assert.assertEquals("Pas de saisisseur sélectionné.", messages.get(3).getMessage()); + + Assert.assertEquals(ValidationScope.WARNING, messages.get(4).getScope()); + Assert.assertEquals("Port d'arrivée", messages.get(4).getFieldName()); + Assert.assertEquals("Pas de port d'arrivé sélectionné.", messages.get(4).getMessage()); + + + } + +} -- To stop receiving notification emails like this one, please contact codelutin.com SCM administrator <admin+scm@list.forge.codelutin.com>.
participants (1)
-
codelutin.com scm