diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/ExperimentProcessor.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/ExperimentProcessor.java index 0666870c6..6c9d8f614 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/ExperimentProcessor.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/ExperimentProcessor.java @@ -2428,6 +2428,13 @@ private void validateObservationValue(Trait variable, String value, addRowError(columnHeader, "Undefined nominal category detected", validationErrors, row); } break; + case TEXT: + //due to null as free text value messing stuff up in backend + if (!validText(value)) { + addRowError(columnHeader, "'Null' is not a valid value", validationErrors, row); + + } + break; default: break; } @@ -2477,6 +2484,10 @@ private boolean validCategory(List categories, return categoryValues.contains(value.toLowerCase()); } + private boolean validText(String value){ + return (value != null) && (!value.equalsIgnoreCase("null")); + } + /** * Converts year String to SeasonDbId *
diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/ExperimentUtilities.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/ExperimentUtilities.java index ae015aab6..718834887 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/ExperimentUtilities.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/ExperimentUtilities.java @@ -530,7 +530,7 @@ public static void validateObservationValue(Trait variable, String value, case NUMERICAL: Optional number = validNumericValue(value); if (number.isEmpty()) { - addRowError(columnHeader, "Non-numeric text detected detected", validationErrors, row); + addRowError(columnHeader, "Non-numeric text detected", validationErrors, row); } else if (!validNumericRange(number.get(), variable.getScale())) { addRowError(columnHeader, "Value outside of min/max range detected", validationErrors, row); } @@ -550,6 +550,11 @@ public static void validateObservationValue(Trait variable, String value, addRowError(columnHeader, "Undefined nominal category detected", validationErrors, row); } break; + case TEXT: + if (!validText(value)) { + addRowError(columnHeader, "'Null' is not a valid value", validationErrors, row); + } + break; default: break; } @@ -589,6 +594,10 @@ public static boolean validCategory(List catego return categoryValues.contains(value.toLowerCase()); } + public static boolean validText(String value){ + return (value != null) && (!value.equalsIgnoreCase("null")); + } + public static boolean isNAObservation(String value){ return value.equalsIgnoreCase("NA"); } diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/service/ObservationService.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/service/ObservationService.java index a6ecac2c0..728cac3b6 100644 --- a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/service/ObservationService.java +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/service/ObservationService.java @@ -97,6 +97,11 @@ public boolean validDateValue(String value) { } return true; } + + public boolean validText(String value){ + return (value != null) && (!value.equalsIgnoreCase("null")); + } + public String getObservationHash(String observationUnitName, String variableName, String studyName) { String concat = DigestUtils.sha256Hex(observationUnitName) + DigestUtils.sha256Hex(variableName) + diff --git a/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/validator/field/TextValidator.java b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/validator/field/TextValidator.java new file mode 100644 index 000000000..e444eb5f9 --- /dev/null +++ b/src/main/java/org/breedinginsight/brapps/importer/services/processors/experiment/validator/field/TextValidator.java @@ -0,0 +1,98 @@ +/* + * See the NOTICE file distributed with this work for additional information + * regarding copyright ownership. + * + * 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 org.breedinginsight.brapps.importer.services.processors.experiment.validator.field; + +import io.micronaut.http.HttpStatus; +import lombok.extern.slf4j.Slf4j; +import org.breedinginsight.api.model.v1.response.ValidationError; +import org.breedinginsight.brapps.importer.services.processors.experiment.service.ObservationService; +import org.breedinginsight.model.Trait; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.Optional; + +import static org.breedinginsight.brapps.importer.services.processors.experiment.model.ExpImportProcessConstants.TIMESTAMP_PREFIX; +import static org.breedinginsight.dao.db.enums.DataType.TEXT; + + + +/** + * This class represents a TextValidator which implements the ObservationValidator interface. + * It is responsible for validating text fields within observations. + */ +@Slf4j +@Singleton +public class TextValidator implements ObservationValidator { + + @Inject + ObservationService observationService; + + /** + * Constructor for TextValidator class that takes an ObservationService as a parameter. + * @param observationService the ObservationService used for validation + */ + public TextValidator(ObservationService observationService) { + this.observationService = observationService; + } + + /** + * Validates a field within an observation for text data. + * + * @param fieldName the name of the field being validated + * @param value the value of the field being validated + * @param variable the Trait variable associated with the field + * @return an Optional containing a ValidationError if validation fails, otherwise an empty Optional + */ + @Override + public Optional validateField(String fieldName, String value, Trait variable) { + // Skip validation if observation is blank + if (observationService.isBlankObservation(value)) { + log.debug(String.format("Skipping validation of observation because there is no value.\n\tvariable: %s", fieldName)); + return Optional.empty(); + } + + // Skip validation if observation is NA + if (observationService.isNAObservation(value)) { + log.debug(String.format("Skipping validation of observation because it is NA.\n\tvariable: %s", fieldName)); + return Optional.empty(); + } + + // Skip if field is a timestamp + if (fieldName.startsWith(TIMESTAMP_PREFIX)) { + return Optional.empty(); + } + + // Skip if there is no trait data + if (variable == null || variable.getScale() == null || variable.getScale().getDataType() == null) { + return Optional.empty(); + } + + // Skip if this is not a text trait + if (!TEXT.equals(variable.getScale().getDataType())) { + return Optional.empty(); + } + + // Validate text + if (!observationService.validText(value)) { + return Optional.of(new ValidationError(fieldName, "'Null' is not a valid value", HttpStatus.UNPROCESSABLE_ENTITY)); + } + + return Optional.empty(); + } +} \ No newline at end of file diff --git a/src/main/resources/version.properties b/src/main/resources/version.properties index 4e43777d2..4ef6916c8 100644 --- a/src/main/resources/version.properties +++ b/src/main/resources/version.properties @@ -15,5 +15,5 @@ # -version=v1.1.0+899 -versionInfo=https://github.com/Breeding-Insight/bi-api/commit/1d19a829223e99b09324a69b51fa47c6b965de64 +version=v1.1.0+901 +versionInfo=https://github.com/Breeding-Insight/bi-api/commit/9c0fdb5b160215a40e5f2df57a7e922ec0036052