/******************************************************************************* * Copyright 2006 - 2014 Vienna University of Technology, * Department of Software Technology and Interactive Systems, IFS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package eu.scape_project.planning.validation; import java.io.Serializable; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.inject.Inject; import eu.scape_project.planning.model.Alternative; import eu.scape_project.planning.model.Plan; import eu.scape_project.planning.model.PlanState; import eu.scape_project.planning.model.SampleObject; import eu.scape_project.planning.model.tree.TreeNode; /** * Validates a plan against a plan state. * * @author Michael Kraxner */ public class PlanValidator implements Serializable { private static final long serialVersionUID = -1592023039267764507L; @Inject private TreeValidator treeValidator; /** * Empty constructor. */ public PlanValidator() { } /** * Checks if the plan contains all information required for the given state. * * Note: Does not validate the preceding plan states. * * @param plan * the plan to validate * @param state * the plan state to validate against * @param errors * a list of validation errors * @return true if the validation succeeded, false otherwise */ public boolean isPlanStateSatisfied(final Plan plan, final PlanState state, List<ValidationError> errors) { boolean result = true; switch (state) { case BASIS_DEFINED: result = isBasisDefinedSatisfied(plan, errors); break; case RECORDS_CHOSEN: result = isRecordsChosenSatisfied(plan, errors); break; case TREE_DEFINED: result = isRequirementsDefinedSatisfied(plan, errors); break; case ALTERNATIVES_DEFINED: result = isAlternativesDefinedSatisfied(plan, errors); break; case GO_CHOSEN: result = isDecisionChosenSatisfied(plan, errors); break; case EXPERIMENT_DEFINED: result = isExperimentDefinedSatisfied(plan, errors); break; case EXPERIMENT_PERFORMED: result = isExperimentPerformedSatisfied(plan, errors); break; case RESULTS_CAPTURED: result = isResultsCapturedSatisfied(plan, errors); break; case TRANSFORMATION_DEFINED: result = isTransformationDefinedSatisfied(plan, errors); break; case WEIGHTS_SET: result = isWeightsSetSatisfied(plan, errors); break; case ANALYSED: result = isAnalysedSatisfied(plan, errors); break; case EXECUTEABLE_PLAN_CREATED: result = isExecutablePlanCreatedSatisfied(plan, errors); break; case PLAN_DEFINED: result = isPlanDefinedSatisfied(plan, errors); break; case PLAN_VALIDATED: result = isPlanValidatedSatisfied(plan, errors); break; default: break; } return result; } /** * Checks if the state {@link PlanState#BASIS_DEFINED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isBasisDefinedSatisfied(final Plan plan, List<ValidationError> errors) { return true; } /** * Checks if the state {@link PlanState#RECORDS_CHOSEN} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isRecordsChosenSatisfied(final Plan plan, List<ValidationError> errors) { boolean result = true; // At least one sample must be defined if (plan.getSampleRecordsDefinition().getRecords().size() == 0) { result = false; errors.add(new ValidationError("At least one sample must be added to proceed with the workflow.")); } // Sample names must be unique Set<String> names = new HashSet<String>(plan.getSampleRecordsDefinition().getRecords().size()); for (SampleObject sample : plan.getSampleRecordsDefinition().getRecords()) { if (names.contains(sample.getShortName())) { result = false; errors.add(new ValidationError("There are two samples with the same short name '" + sample.getShortName() + "'. Please provide unique names.")); } names.add(sample.getShortName()); } return result; } /** * Checks if the state {@link PlanState#TREE_DEFINED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isRequirementsDefinedSatisfied(final Plan plan, List<ValidationError> errors) { return treeValidator.validate(plan.getTree().getRoot(), new INodeValidator() { public boolean validateNode(TreeNode node, List<ValidationError> errors) { return node.isCompletelySpecified(errors); } }, errors); } /** * Checks if the state {@link PlanState#ALTERNATIVES_DEFINED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isAlternativesDefinedSatisfied(final Plan plan, List<ValidationError> errors) { // At least one alternative must be defined if (plan.getAlternativesDefinition().getAlternatives().size() <= 0) { ValidationError error = new ValidationError( "At least one alternative must be added to proceed with the workflow."); errors.add(error); return false; } return true; } /** * Checks if the state {@link PlanState#GO_CHOSEN} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isDecisionChosenSatisfied(final Plan plan, List<ValidationError> errors) { boolean result = true; if (!plan.getDecision().isGoDecision()) { result = false; errors.add(new ValidationError("You have to take the GO decision to proceed with the workflow.")); } if (plan.getAlternativesDefinition().getConsideredAlternatives().size() == 0) { errors.add(new ValidationError("At least one alternative must be considered for evaluation.")); result = false; } return result; } /** * Checks if the state {@link PlanState#EXPERIMENT_DEFINED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isExperimentDefinedSatisfied(final Plan plan, List<ValidationError> errors) { return true; } /** * Checks if the state {@link PlanState#EXPERIMENT_PERFORMED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isExperimentPerformedSatisfied(final Plan plan, List<ValidationError> errors) { return true; } /** * Checks if the state {@link PlanState#RESULTS_CAPTURED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isResultsCapturedSatisfied(final Plan plan, List<ValidationError> errors) { boolean result = treeValidator.validate(plan.getTree().getRoot(), new INodeValidator() { private List<Alternative> consideredAlternatives = plan.getAlternativesDefinition() .getConsideredAlternatives(); public boolean validateNode(TreeNode node, List<ValidationError> errors) { return node.isCompletelyEvaluated(consideredAlternatives, errors); } }, errors); return result; } /** * Checks if the state {@link PlanState#TRANSFORMATION_DEFINED} is * satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isTransformationDefinedSatisfied(final Plan plan, List<ValidationError> errors) { return treeValidator.validate(plan.getTree().getRoot(), new INodeValidator() { public boolean validateNode(TreeNode node, List<ValidationError> errors) { return node.isCompletelyTransformed(errors); } }, errors); } /** * Checks if the state {@link PlanState#WEIGHTS_SET} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isWeightsSetSatisfied(final Plan plan, List<ValidationError> errors) { return treeValidator.validate(plan.getTree().getRoot(), new INodeValidator() { public boolean validateNode(TreeNode node, List<ValidationError> errors) { return node.isCorrectlyWeighted(errors); } }, errors); } /** * Checks if the state {@link PlanState#ANALYSED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isAnalysedSatisfied(final Plan plan, List<ValidationError> errors) { // if no recommendation is set - validation fails if (plan.getRecommendation().getAlternative() == null) { errors.add(new ValidationError("You have to select a recommendation to proceed with the workflow.")); return false; } return true; } /** * Checks if the state {@link PlanState#EXECUTEABLE_PLAN_CREATED} is * satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isExecutablePlanCreatedSatisfied(final Plan plan, List<ValidationError> errors) { // No validation at this step return true; } /** * Checks if the state {@link PlanState#PLAN_DEFINED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isPlanDefinedSatisfied(final Plan plan, List<ValidationError> errors) { // No validation at this step return true; } /** * Checks if the state {@link PlanState#PLAN_VALIDATED} is satisfied. * * @param plan * the plan to validate * @param errors * a list of errors * @return true if the validation succeeded, false otherwise */ private boolean isPlanValidatedSatisfied(final Plan plan, List<ValidationError> errors) { // No validation at this step return true; } }