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 c3a48f1eb9b9b1e122f75eea30377245e272ef46 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>.